From 0688f258cde8602f1f463d69592e2efb9faa209d Mon Sep 17 00:00:00 2001 From: Para <62068271+murd0cc@users.noreply.github.com> Date: Mon, 10 Aug 2026 02:01:45 +0300 Subject: [PATCH 01/66] issue #685 - point 8 --- .../src/components/chat/FollowUpSuggest.tsx | 5 ++-- .../chat/__tests__/FollowUpSuggest.spec.tsx | 23 +++++++++++++++++++ .../settings/AutoApproveSettings.tsx | 8 +++++-- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/webview-ui/src/components/chat/FollowUpSuggest.tsx b/webview-ui/src/components/chat/FollowUpSuggest.tsx index 42b41bacfa..b9e1c9eecd 100644 --- a/webview-ui/src/components/chat/FollowUpSuggest.tsx +++ b/webview-ui/src/components/chat/FollowUpSuggest.tsx @@ -36,14 +36,15 @@ export const FollowUpSuggest = ({ // Start countdown timer when auto-approval is enabled for follow-up questions useEffect(() => { // Only start countdown if auto-approval is enabled for follow-up questions and no suggestion has been selected - // Also stop countdown if the question has been answered or auto-approval is paused (user is typing) + // Also stop countdown if the question has been answered or auto-approval is paused (user is typing) or timer is disabled (set to 0) if ( autoApprovalEnabled && alwaysAllowFollowupQuestions && suggestions.length > 0 && !suggestionSelected && !isAnswered && - !isFollowUpAutoApprovalPaused + !isFollowUpAutoApprovalPaused && + (followupAutoApproveTimeoutMs ?? DEFAULT_FOLLOWUP_TIMEOUT_MS) > 0 ) { // Start with the configured timeout in seconds const timeoutMs = diff --git a/webview-ui/src/components/chat/__tests__/FollowUpSuggest.spec.tsx b/webview-ui/src/components/chat/__tests__/FollowUpSuggest.spec.tsx index a46df75b80..2672e47306 100644 --- a/webview-ui/src/components/chat/__tests__/FollowUpSuggest.spec.tsx +++ b/webview-ui/src/components/chat/__tests__/FollowUpSuggest.spec.tsx @@ -74,6 +74,13 @@ describe("FollowUpSuggest", () => { followupAutoApproveTimeoutMs: 3000, // 3 seconds for testing } + // Test state with timeout disabled (0) + const disabledTimeoutState: TestExtensionState = { + autoApprovalEnabled: true, + alwaysAllowFollowupQuestions: true, + followupAutoApproveTimeoutMs: 0, // Disabled + } + beforeEach(() => { vi.clearAllMocks() vi.useFakeTimers() @@ -218,6 +225,22 @@ describe("FollowUpSuggest", () => { expect(screen.queryByText(/\d+s/)).not.toBeInTheDocument() }) + // Should not show countdown when timeout is disabled (set to 0) + it("should not show countdown when timeout is disabled (set to 0)", () => { + renderWithTestProviders( + , + disabledTimeoutState, + ) + + // Should not show countdown when timeout is disabled + expect(screen.queryByText(/\d+s/)).not.toBeInTheDocument() + }) + it("should not render when no suggestions are provided", () => { const { container } = renderWithTestProviders(
- {followupAutoApproveTimeoutMs / 1000}s + + {followupAutoApproveTimeoutMs === 0 + ? "Disabled" + : `${followupAutoApproveTimeoutMs / 1000}s`} +
{t("settings:autoApprove.followupQuestions.timeoutLabel")} From 04aa5fad937595e2100c935d182aee0a67f737af Mon Sep 17 00:00:00 2001 From: Para <62068271+murd0cc@users.noreply.github.com> Date: Tue, 11 Aug 2026 23:59:03 +0300 Subject: [PATCH 02/66] PR requested changes implemented --- .../chat/__tests__/FollowUpSuggest.spec.tsx | 19 +++++++++ .../settings/AutoApproveSettings.tsx | 2 +- .../__tests__/AutoApproveSettings.spec.tsx | 14 +++++++ .../AutoApproveSettings.visual.fixture.tsx | 36 ++++++++++++++++++ .../__tests__/AutoApproveSettings.visual.tsx | 18 +++++++++ ...approve-followup-timeout-disabled-dark.png | Bin 0 -> 205 bytes webview-ui/src/i18n/locales/ca/settings.json | 3 +- webview-ui/src/i18n/locales/de/settings.json | 3 +- webview-ui/src/i18n/locales/en/settings.json | 3 +- webview-ui/src/i18n/locales/es/settings.json | 3 +- webview-ui/src/i18n/locales/fr/settings.json | 3 +- webview-ui/src/i18n/locales/hi/settings.json | 3 +- webview-ui/src/i18n/locales/id/settings.json | 3 +- webview-ui/src/i18n/locales/it/settings.json | 3 +- webview-ui/src/i18n/locales/ja/settings.json | 3 +- webview-ui/src/i18n/locales/ko/settings.json | 3 +- webview-ui/src/i18n/locales/nl/settings.json | 3 +- webview-ui/src/i18n/locales/pl/settings.json | 3 +- .../src/i18n/locales/pt-BR/settings.json | 3 +- webview-ui/src/i18n/locales/ru/settings.json | 3 +- webview-ui/src/i18n/locales/tr/settings.json | 3 +- webview-ui/src/i18n/locales/vi/settings.json | 3 +- .../src/i18n/locales/zh-CN/settings.json | 3 +- .../src/i18n/locales/zh-TW/settings.json | 3 +- 24 files changed, 124 insertions(+), 19 deletions(-) create mode 100644 webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.fixture.tsx create mode 100644 webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx create mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/auto-approve-followup-timeout-disabled-dark.png diff --git a/webview-ui/src/components/chat/__tests__/FollowUpSuggest.spec.tsx b/webview-ui/src/components/chat/__tests__/FollowUpSuggest.spec.tsx index 2672e47306..169df1aee4 100644 --- a/webview-ui/src/components/chat/__tests__/FollowUpSuggest.spec.tsx +++ b/webview-ui/src/components/chat/__tests__/FollowUpSuggest.spec.tsx @@ -241,6 +241,25 @@ describe("FollowUpSuggest", () => { expect(screen.queryByText(/\d+s/)).not.toBeInTheDocument() }) + it("should not show countdown when timeout is negative", () => { + const negativeTimeoutState: TestExtensionState = { + ...defaultTestState, + followupAutoApproveTimeoutMs: -1000, + } + + renderWithTestProviders( + , + negativeTimeoutState, + ) + + expect(screen.queryByText(/\d+s/)).not.toBeInTheDocument() + }) + it("should not render when no suggestions are provided", () => { const { container } = renderWithTestProviders( {followupAutoApproveTimeoutMs === 0 - ? "Disabled" + ? t("settings:autoApprove.followupQuestions.timeoutDisabled") : `${followupAutoApproveTimeoutMs / 1000}s`}
diff --git a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.spec.tsx b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.spec.tsx index c798b7a4a9..5ee6026ed8 100644 --- a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.spec.tsx +++ b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.spec.tsx @@ -161,4 +161,18 @@ describe("AutoApproveSettings - Save/Discard contract", () => { expect(screen.getByTestId("allowed-commands-heading")).toBeInTheDocument() expect(screen.getByTestId("denied-commands-heading")).toBeInTheDocument() }) + + it("renders disabled timeout label when follow-up auto-approve timeout is 0", () => { + renderSettings({ alwaysAllowFollowupQuestions: true, followupAutoApproveTimeoutMs: 0 }) + + expect(screen.getByTestId("followup-timeout-slider")).toBeInTheDocument() + expect(screen.getByText("settings:autoApprove.followupQuestions.timeoutDisabled")).toBeInTheDocument() + }) + + it("renders timeout in seconds when follow-up auto-approve timeout is non-zero", () => { + renderSettings({ alwaysAllowFollowupQuestions: true, followupAutoApproveTimeoutMs: 5000 }) + + expect(screen.getByTestId("followup-timeout-slider")).toBeInTheDocument() + expect(screen.getByText("5s")).toBeInTheDocument() + }) }) diff --git a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.fixture.tsx b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.fixture.tsx new file mode 100644 index 0000000000..6f4e4707e3 --- /dev/null +++ b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.fixture.tsx @@ -0,0 +1,36 @@ +/* v8 ignore file -- Playwright component fixture is covered by the visual test. */ +import React from "react" + +import { TranslationContext } from "@/i18n/TranslationContext" +import { ExtensionStateContext } from "@/context/ExtensionStateContext" +import { AutoApproveSettings } from "../AutoApproveSettings" + +const extensionStateValue = { + autoApprovalEnabled: false, + setAutoApprovalEnabled: () => {}, + alwaysAllowReadOnly: false, + alwaysAllowWrite: false, + alwaysAllowExecute: false, + alwaysAllowMcp: false, + alwaysAllowModeSwitch: false, + alwaysAllowSubtasks: false, + alwaysAllowFollowupQuestions: true, +} as any + +export const AutoApproveSettingsFixture = () => ( + key, + i18n: null as unknown as typeof import("../../../i18n/setup").default, + }}> + +
+ {}} + /> +
+
+
+) diff --git a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx new file mode 100644 index 0000000000..9fea71d4e0 --- /dev/null +++ b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx @@ -0,0 +1,18 @@ +import React from "react" + +import { expect, test } from "../../../../playwright/coverage-fixture" +import { AutoApproveSettingsFixture } from "./AutoApproveSettings.visual.fixture" + +test("renders follow-up timeout row with disabled state label in the VS Code dark theme", async ({ mount, page }) => { + // The full settings bundle can leave a bare Zod reference after CT tree-shaking. + await page.evaluate(() => Object.assign(globalThis, { z: undefined })) + + const component = await mount() + + await component.evaluate(async () => { + await document.fonts.ready + await new Promise((resolve) => requestAnimationFrame(() => resolve())) + }) + + await expect(component).toHaveScreenshot("auto-approve-followup-timeout-disabled-dark.png") +}) diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/auto-approve-followup-timeout-disabled-dark.png b/webview-ui/src/components/settings/__tests__/__screenshots__/auto-approve-followup-timeout-disabled-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..db87f68911f60194136207b64222fe42540967af GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0y~yVB!F>6*!oH* k|8@~+mw~Qf1G$Eofo~1NT#m%>1wau7Pgg&ebxsLQ04Fjnga7~l literal 0 HcmV?d00001 diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index 73827b1ec1..c8efd130c4 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -323,7 +323,8 @@ "followupQuestions": { "label": "Pregunta", "description": "Seleccionar automàticament la primera resposta suggerida per a preguntes de seguiment després del temps d'espera configurat", - "timeoutLabel": "Temps d'espera abans de seleccionar automàticament la primera resposta" + "timeoutLabel": "Temps d'espera abans de seleccionar automàticament la primera resposta", + "timeoutDisabled": "Desactivat" }, "execute": { "label": "Executar", diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index 8078037525..b650941fc5 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -323,7 +323,8 @@ "followupQuestions": { "label": "Frage", "description": "Automatisch die erste vorgeschlagene Antwort für Folgefragen nach der konfigurierten Zeitüberschreitung auswählen", - "timeoutLabel": "Wartezeit vor der automatischen Auswahl der ersten Antwort" + "timeoutLabel": "Wartezeit vor der automatischen Auswahl der ersten Antwort", + "timeoutDisabled": "Deaktiviert" }, "execute": { "label": "Ausführen", diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index 14a7476a75..6f4ac738f0 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -401,7 +401,8 @@ "followupQuestions": { "label": "Question", "description": "Automatically select the first suggested answer for follow-up questions after the configured timeout", - "timeoutLabel": "Time to wait before auto-selecting the first answer" + "timeoutLabel": "Time to wait before auto-selecting the first answer", + "timeoutDisabled": "Disabled" }, "execute": { "label": "Execute", diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index e629e43b50..529d5f7fad 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -323,7 +323,8 @@ "followupQuestions": { "label": "Pregunta", "description": "Seleccionar automáticamente la primera respuesta sugerida para preguntas de seguimiento después del tiempo de espera configurado", - "timeoutLabel": "Tiempo de espera antes de seleccionar automáticamente la primera respuesta" + "timeoutLabel": "Tiempo de espera antes de seleccionar automáticamente la primera respuesta", + "timeoutDisabled": "Deshabilitado" }, "execute": { "label": "Ejecutar", diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index 6048e2274c..9b2358bae8 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -324,7 +324,8 @@ "followupQuestions": { "label": "Question", "description": "Sélectionner automatiquement la première réponse suggérée pour les questions de suivi après le délai configuré", - "timeoutLabel": "Temps d'attente avant la sélection automatique de la première réponse" + "timeoutLabel": "Temps d'attente avant la sélection automatique de la première réponse", + "timeoutDisabled": "Désactivé" }, "execute": { "label": "Exécuter", diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index 28d0b8699b..2c03328615 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -323,7 +323,8 @@ "followupQuestions": { "label": "प्रश्न", "description": "कॉन्फ़िगर किए गए टाइमआउट के बाद अनुवर्ती प्रश्नों के लिए पहले सुझाए गए उत्तर को स्वचालित रूप से चुनें", - "timeoutLabel": "पहले उत्तर को स्वचालित रूप से चुनने से पहले प्रतीक्षा करने का समय" + "timeoutLabel": "पहले उत्तर को स्वचालित रूप से चुनने से पहले प्रतीक्षा करने का समय", + "timeoutDisabled": "अक्षम" }, "execute": { "label": "निष्पादित करें", diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json index bf049395c4..81c317214a 100644 --- a/webview-ui/src/i18n/locales/id/settings.json +++ b/webview-ui/src/i18n/locales/id/settings.json @@ -323,7 +323,8 @@ "followupQuestions": { "label": "Pertanyaan", "description": "Secara otomatis memilih jawaban pertama yang disarankan untuk pertanyaan lanjutan setelah batas waktu yang dikonfigurasi", - "timeoutLabel": "Waktu tunggu sebelum otomatis memilih jawaban pertama" + "timeoutLabel": "Waktu tunggu sebelum otomatis memilih jawaban pertama", + "timeoutDisabled": "Dinonaktifkan" }, "execute": { "label": "Eksekusi", diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index 577a74a77a..35259f3382 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -323,7 +323,8 @@ "followupQuestions": { "label": "Domanda", "description": "Seleziona automaticamente la prima risposta suggerita per le domande di follow-up dopo il timeout configurato", - "timeoutLabel": "Tempo di attesa prima di selezionare automaticamente la prima risposta" + "timeoutLabel": "Tempo di attesa prima di selezionare automaticamente la prima risposta", + "timeoutDisabled": "Disabilitato" }, "execute": { "label": "Esegui", diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index 1113ac32a6..169eb60858 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -323,7 +323,8 @@ "followupQuestions": { "label": "質問", "description": "設定された時間が経過すると、フォローアップ質問の最初の提案回答を自動的に選択します", - "timeoutLabel": "最初の回答を自動選択するまでの待機時間" + "timeoutLabel": "最初の回答を自動選択するまでの待機時間", + "timeoutDisabled": "無効" }, "execute": { "label": "実行", diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index 27e8493bd4..39e780c3c7 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -323,7 +323,8 @@ "followupQuestions": { "label": "질문", "description": "설정된 시간이 지나면 후속 질문에 대한 첫 번째 제안 답변을 자동으로 선택합니다", - "timeoutLabel": "첫 번째 답변을 자동 선택하기 전 대기 시간" + "timeoutLabel": "첫 번째 답변을 자동 선택하기 전 대기 시간", + "timeoutDisabled": "사용 안 함" }, "execute": { "label": "실행", diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json index 394cdd48f2..27f6ebccfb 100644 --- a/webview-ui/src/i18n/locales/nl/settings.json +++ b/webview-ui/src/i18n/locales/nl/settings.json @@ -323,7 +323,8 @@ "followupQuestions": { "label": "Vraag", "description": "Selecteer automatisch het eerste voorgestelde antwoord voor vervolgvragen na de geconfigureerde time-out", - "timeoutLabel": "Wachttijd voordat het eerste antwoord automatisch wordt geselecteerd" + "timeoutLabel": "Wachttijd voordat het eerste antwoord automatisch wordt geselecteerd", + "timeoutDisabled": "Uitgeschakeld" }, "execute": { "label": "Uitvoeren", diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index 864e4ffde1..1e9fb88c1b 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -323,7 +323,8 @@ "followupQuestions": { "label": "Pytanie", "description": "Automatycznie wybierz pierwszą sugerowaną odpowiedź na pytania uzupełniające po skonfigurowanym limicie czasu", - "timeoutLabel": "Czas oczekiwania przed automatycznym wybraniem pierwszej odpowiedzi" + "timeoutLabel": "Czas oczekiwania przed automatycznym wybraniem pierwszej odpowiedzi", + "timeoutDisabled": "Wyłączone" }, "execute": { "label": "Wykonaj", diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index a1948a0218..078b78e815 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -323,7 +323,8 @@ "followupQuestions": { "label": "Pergunta", "description": "Selecionar automaticamente a primeira resposta sugerida para perguntas de acompanhamento após o tempo limite configurado", - "timeoutLabel": "Tempo de espera antes de selecionar automaticamente a primeira resposta" + "timeoutLabel": "Tempo de espera antes de selecionar automaticamente a primeira resposta", + "timeoutDisabled": "Desativado" }, "execute": { "label": "Executar", diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index f36fe62539..bb807c930f 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -323,7 +323,8 @@ "followupQuestions": { "label": "Вопрос", "description": "Автоматически выбирать первый предложенный ответ на дополнительные вопросы после настроенного тайм-аута", - "timeoutLabel": "Время ожидания перед автоматическим выбором первого ответа" + "timeoutLabel": "Время ожидания перед автоматическим выбором первого ответа", + "timeoutDisabled": "Отключено" }, "execute": { "label": "Выполнение", diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index 9099677679..638fd6c8b2 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -323,7 +323,8 @@ "followupQuestions": { "label": "Soru", "description": "Yapılandırılan zaman aşımından sonra takip sorularına ilişkin ilk önerilen yanıtı otomatik olarak seç", - "timeoutLabel": "İlk yanıtı otomatik olarak seçmeden önce beklenecek süre" + "timeoutLabel": "İlk yanıtı otomatik olarak seçmeden önce beklenecek süre", + "timeoutDisabled": "Devre dışı" }, "execute": { "label": "Yürüt", diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index c66b236165..11d368ea1e 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -323,7 +323,8 @@ "followupQuestions": { "label": "Câu hỏi", "description": "Tự động chọn câu trả lời đầu tiên được đề xuất cho các câu hỏi tiếp theo sau thời gian chờ đã cấu hình", - "timeoutLabel": "Thời gian chờ trước khi tự động chọn câu trả lời đầu tiên" + "timeoutLabel": "Thời gian chờ trước khi tự động chọn câu trả lời đầu tiên", + "timeoutDisabled": "Đã tắt" }, "execute": { "label": "Thực thi", diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index 22742e0e0e..fec2653574 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -323,7 +323,8 @@ "followupQuestions": { "label": "问题", "description": "在配置的超时时间后自动选择后续问题的第一个建议答案", - "timeoutLabel": "自动选择第一个答案前的等待时间" + "timeoutLabel": "自动选择第一个答案前的等待时间", + "timeoutDisabled": "已禁用" }, "execute": { "label": "执行", diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index 4255a2e697..80a7a94dbd 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -348,7 +348,8 @@ "followupQuestions": { "label": "後續提問", "description": "在設定的逾時時間過後,自動選擇後續問題的第一個建議答案", - "timeoutLabel": "自動選擇第一個答案前的等待時間" + "timeoutLabel": "自動選擇第一個答案前的等待時間", + "timeoutDisabled": "已停用" }, "execute": { "label": "執行命令", From 9411e41853f512b970473d7cc0bbccc30a53a009 Mon Sep 17 00:00:00 2001 From: Para <62068271+murd0cc@users.noreply.github.com> Date: Wed, 12 Aug 2026 00:13:19 +0300 Subject: [PATCH 03/66] Maintainability & Code Quality --- webview-ui/eslint-suppressions.json | 1 + .../__tests__/AutoApproveSettings.spec.tsx | 83 +++++++++++++++++-- .../AutoApproveSettings.visual.fixture.tsx | 24 ++---- 3 files changed, 85 insertions(+), 23 deletions(-) create mode 100644 webview-ui/eslint-suppressions.json diff --git a/webview-ui/eslint-suppressions.json b/webview-ui/eslint-suppressions.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/webview-ui/eslint-suppressions.json @@ -0,0 +1 @@ +{} diff --git a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.spec.tsx b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.spec.tsx index 5ee6026ed8..37fa40024d 100644 --- a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.spec.tsx +++ b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.spec.tsx @@ -33,6 +33,24 @@ vi.mock("@/hooks/useAutoApprovalState", () => ({ useAutoApprovalState: () => ({ effectiveAutoApprovalEnabled: false, hasEnabledOptions: false }), })) +vi.mock("@/components/ui", async (importOriginal) => { + const actual = await importOriginal() + + return { + ...actual, + Button: ({ children, ...props }: any) => , + Input: (props: any) => , + Slider: ({ value, onValueChange, ...props }: any) => ( + onValueChange?.([Number((event.target as HTMLInputElement).value)])} + {...props} + /> + ), + } +}) + const renderSettings = (overrides = {}) => { const setCachedStateField = vi.fn() const props = { @@ -163,16 +181,69 @@ describe("AutoApproveSettings - Save/Discard contract", () => { }) it("renders disabled timeout label when follow-up auto-approve timeout is 0", () => { - renderSettings({ alwaysAllowFollowupQuestions: true, followupAutoApproveTimeoutMs: 0 }) - - expect(screen.getByTestId("followup-timeout-slider")).toBeInTheDocument() + const { setCachedStateField } = renderSettings({ + alwaysAllowFollowupQuestions: true, + followupAutoApproveTimeoutMs: 0, + }) + + const slider = screen.getByTestId("followup-timeout-slider") as HTMLInputElement + expect(slider).toBeInTheDocument() + expect(slider.value).toBe("0") expect(screen.getByText("settings:autoApprove.followupQuestions.timeoutDisabled")).toBeInTheDocument() + + fireEvent.change(slider, { target: { value: "4000" } }) + + expect(setCachedStateField).toHaveBeenCalledWith("followupAutoApproveTimeoutMs", 4000) + expectNoImmediateUpdateSettings() }) it("renders timeout in seconds when follow-up auto-approve timeout is non-zero", () => { - renderSettings({ alwaysAllowFollowupQuestions: true, followupAutoApproveTimeoutMs: 5000 }) - - expect(screen.getByTestId("followup-timeout-slider")).toBeInTheDocument() + const { setCachedStateField } = renderSettings({ + alwaysAllowFollowupQuestions: true, + followupAutoApproveTimeoutMs: 5000, + }) + + const slider = screen.getByTestId("followup-timeout-slider") as HTMLInputElement + expect(slider).toBeInTheDocument() + expect(slider.value).toBe("5000") expect(screen.getByText("5s")).toBeInTheDocument() + + fireEvent.change(slider, { target: { value: "0" } }) + + expect(setCachedStateField).toHaveBeenCalledWith("followupAutoApproveTimeoutMs", 0) + expectNoImmediateUpdateSettings() + }) + + it("uses the default timeout value when timeout is unset and follow-up auto-approve is enabled", () => { + renderSettings({ alwaysAllowFollowupQuestions: true }) + + const slider = screen.getByTestId("followup-timeout-slider") as HTMLInputElement + expect(slider.value).toBe("60000") + expect(screen.getByText("60s")).toBeInTheDocument() + }) + + it("does not render the follow-up timeout controls when follow-up auto-approve is disabled or unset", () => { + const { rerender } = render( + , + ) + + expect(screen.queryByTestId("followup-timeout-slider")).not.toBeInTheDocument() + + rerender( + , + ) + + expect(screen.queryByTestId("followup-timeout-slider")).not.toBeInTheDocument() }) }) diff --git a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.fixture.tsx b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.fixture.tsx index 6f4e4707e3..0002607348 100644 --- a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.fixture.tsx +++ b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.fixture.tsx @@ -2,28 +2,18 @@ import React from "react" import { TranslationContext } from "@/i18n/TranslationContext" -import { ExtensionStateContext } from "@/context/ExtensionStateContext" +import i18next from "@/i18n/setup" +import { ExtensionStateContextProvider } from "@/context/ExtensionStateContext" import { AutoApproveSettings } from "../AutoApproveSettings" -const extensionStateValue = { - autoApprovalEnabled: false, - setAutoApprovalEnabled: () => {}, - alwaysAllowReadOnly: false, - alwaysAllowWrite: false, - alwaysAllowExecute: false, - alwaysAllowMcp: false, - alwaysAllowModeSwitch: false, - alwaysAllowSubtasks: false, - alwaysAllowFollowupQuestions: true, -} as any - export const AutoApproveSettingsFixture = () => ( key, - i18n: null as unknown as typeof import("../../../i18n/setup").default, + t: (key) => (key === "settings:autoApprove.followupQuestions.timeoutDisabled" ? "Disabled" : key), + i18n: i18next, }}> - +
( setCachedStateField={() => {}} />
-
+
) From ca2ed956a63a6389e27c5031e9e38d3f0a65880e Mon Sep 17 00:00:00 2001 From: Para <62068271+murd0cc@users.noreply.github.com> Date: Wed, 12 Aug 2026 00:38:51 +0300 Subject: [PATCH 04/66] coverage improvements --- .../chat/__tests__/FollowUpSuggest.spec.tsx | 94 ++++++++++++++++++- 1 file changed, 92 insertions(+), 2 deletions(-) diff --git a/webview-ui/src/components/chat/__tests__/FollowUpSuggest.spec.tsx b/webview-ui/src/components/chat/__tests__/FollowUpSuggest.spec.tsx index 169df1aee4..e6d623b389 100644 --- a/webview-ui/src/components/chat/__tests__/FollowUpSuggest.spec.tsx +++ b/webview-ui/src/components/chat/__tests__/FollowUpSuggest.spec.tsx @@ -1,5 +1,5 @@ import React, { createContext, useContext } from "react" -import { render, screen, act } from "@testing-library/react" +import { render, screen, act, fireEvent } from "@testing-library/react" import { TooltipProvider } from "@radix-ui/react-tooltip" import { FollowUpSuggest } from "../FollowUpSuggest" @@ -28,7 +28,7 @@ vi.mock("@src/i18n/TranslationContext", () => ({ interface TestExtensionState { autoApprovalEnabled: boolean alwaysAllowFollowupQuestions: boolean - followupAutoApproveTimeoutMs: number + followupAutoApproveTimeoutMs?: number } const TestExtensionStateContext = createContext(undefined) @@ -749,4 +749,94 @@ describe("FollowUpSuggest", () => { expect(mockOnCancelAutoApproval).toHaveBeenCalled() }) }) + + describe("suggestion interactions", () => { + it("cancels countdown and forwards click when user clicks a suggestion", () => { + renderWithTestProviders( + , + defaultTestState, + ) + + fireEvent.click(screen.getByText("First suggestion")) + + expect(mockOnSuggestionClick).toHaveBeenCalledWith( + expect.objectContaining({ answer: "First suggestion" }), + expect.objectContaining({ shiftKey: false }), + ) + expect(mockOnCancelAutoApproval).toHaveBeenCalled() + expect(screen.queryByText(/Selecting in \d+s/)).not.toBeInTheDocument() + }) + + it("keeps countdown when shift-clicking a suggestion", () => { + renderWithTestProviders( + , + defaultTestState, + ) + + mockOnCancelAutoApproval.mockClear() + fireEvent.click(screen.getByText("First suggestion"), { shiftKey: true }) + + expect(mockOnSuggestionClick).toHaveBeenCalledWith( + expect.objectContaining({ answer: "First suggestion" }), + expect.objectContaining({ shiftKey: true }), + ) + expect(mockOnCancelAutoApproval).not.toHaveBeenCalled() + expect(screen.getByText(/Selecting in 3s/)).toBeInTheDocument() + }) + + it("copies suggestion into input when the copy affordance is clicked", () => { + const { container } = renderWithTestProviders( + , + defaultTestState, + ) + + const copyAffordance = container.querySelector( + ".absolute.cursor-pointer.top-1\\.5.right-1\\.5", + ) as HTMLElement + + expect(copyAffordance).toBeTruthy() + fireEvent.click(copyAffordance) + + expect(mockOnSuggestionClick).toHaveBeenCalledWith( + expect.objectContaining({ answer: "First suggestion" }), + expect.objectContaining({ shiftKey: true }), + ) + expect(mockOnCancelAutoApproval).toHaveBeenCalled() + expect(screen.queryByText(/Selecting in \d+s/)).not.toBeInTheDocument() + }) + + it("uses default timeout when extension state timeout is undefined", () => { + const stateWithUndefinedTimeout = { + ...defaultTestState, + followupAutoApproveTimeoutMs: undefined, + } + + renderWithTestProviders( + , + stateWithUndefinedTimeout, + ) + + expect(screen.getByText(/Selecting in 60s/)).toBeInTheDocument() + }) + }) }) From d4023d11ad5e15ee7852abc99ad31e6a400b92df Mon Sep 17 00:00:00 2001 From: Alexei Gubin <36731953+WebMad@users.noreply.github.com> Date: Wed, 12 Aug 2026 13:04:28 +0000 Subject: [PATCH 05/66] refactor(types): canonicalize shared provider settings identifiers (#1109) * refactor(types): centralize provider model definitions * fix(types): preserve provider settings compatibility * refactor(types): derive model keys from provider definitions * docs(types): clarify model key compatibility * fix(types): preserve legacy model id keys * fix(types): preserve model id key compatibility * fix(core): adopt active provider type guard * fix(types): preserve provider guard compatibility * refactor(types): retain concise provider guard name * test(types): clarify provider model ID selection * test(types): simplify model ID key contract * refactor(types): make provider model accessors explicit * refactor(types): decompose provider settings * refactor(types): colocate provider setting keys * test(webview): use canonical provider identifiers * docs(types): explain model provider exclusions --- .../src/__tests__/provider-model-id.test.ts | 90 ++++ .../src/__tests__/provider-settings.test.ts | 16 +- packages/types/src/provider-settings.ts | 465 ++++-------------- .../types/src/provider-settings/anthropic.ts | 22 + .../types/src/provider-settings/baseten.ts | 19 + .../types/src/provider-settings/bedrock.ts | 35 ++ .../types/src/provider-settings/common.ts | 76 +++ .../types/src/provider-settings/deepseek.ts | 20 + .../types/src/provider-settings/fake-ai.ts | 19 + .../types/src/provider-settings/fireworks.ts | 19 + .../types/src/provider-settings/friendli.ts | 19 + .../types/src/provider-settings/gemini-cli.ts | 20 + .../types/src/provider-settings/gemini.ts | 20 + packages/types/src/provider-settings/index.ts | 78 +++ .../types/src/provider-settings/kenari.ts | 17 + .../types/src/provider-settings/kimi-code.ts | 23 + .../types/src/provider-settings/litellm.ts | 19 + .../types/src/provider-settings/lm-studio.ts | 19 + packages/types/src/provider-settings/mimo.ts | 27 + .../types/src/provider-settings/minimax.ts | 22 + .../types/src/provider-settings/mistral.ts | 20 + .../types/src/provider-settings/moonshot.ts | 25 + .../types/src/provider-settings/ollama.ts | 19 + .../src/provider-settings/openai-codex.ts | 21 + .../src/provider-settings/openai-native.ts | 24 + .../types/src/provider-settings/openai.ts | 26 + .../src/provider-settings/opencode-go.ts | 17 + .../types/src/provider-settings/openrouter.ts | 19 + packages/types/src/provider-settings/poe.ts | 20 + .../types/src/provider-settings/qwen-code.ts | 19 + .../types/src/provider-settings/requesty.ts | 18 + .../types/src/provider-settings/sambanova.ts | 23 + .../types/src/provider-settings/unbound.ts | 17 + .../provider-settings/vercel-ai-gateway.ts | 17 + .../types/src/provider-settings/vertex.ts | 23 + .../types/src/provider-settings/vscode-lm.ts | 20 + packages/types/src/provider-settings/xai.ts | 19 + packages/types/src/provider-settings/zai.ts | 23 + .../src/provider-settings/zoo-gateway.ts | 18 + packages/types/src/type-fu.ts | 4 + .../src/utils/__tests__/validate.spec.ts | 43 +- webview-ui/src/utils/validate.ts | 28 +- 42 files changed, 1119 insertions(+), 389 deletions(-) create mode 100644 packages/types/src/__tests__/provider-model-id.test.ts create mode 100644 packages/types/src/provider-settings/anthropic.ts create mode 100644 packages/types/src/provider-settings/baseten.ts create mode 100644 packages/types/src/provider-settings/bedrock.ts create mode 100644 packages/types/src/provider-settings/common.ts create mode 100644 packages/types/src/provider-settings/deepseek.ts create mode 100644 packages/types/src/provider-settings/fake-ai.ts create mode 100644 packages/types/src/provider-settings/fireworks.ts create mode 100644 packages/types/src/provider-settings/friendli.ts create mode 100644 packages/types/src/provider-settings/gemini-cli.ts create mode 100644 packages/types/src/provider-settings/gemini.ts create mode 100644 packages/types/src/provider-settings/index.ts create mode 100644 packages/types/src/provider-settings/kenari.ts create mode 100644 packages/types/src/provider-settings/kimi-code.ts create mode 100644 packages/types/src/provider-settings/litellm.ts create mode 100644 packages/types/src/provider-settings/lm-studio.ts create mode 100644 packages/types/src/provider-settings/mimo.ts create mode 100644 packages/types/src/provider-settings/minimax.ts create mode 100644 packages/types/src/provider-settings/mistral.ts create mode 100644 packages/types/src/provider-settings/moonshot.ts create mode 100644 packages/types/src/provider-settings/ollama.ts create mode 100644 packages/types/src/provider-settings/openai-codex.ts create mode 100644 packages/types/src/provider-settings/openai-native.ts create mode 100644 packages/types/src/provider-settings/openai.ts create mode 100644 packages/types/src/provider-settings/opencode-go.ts create mode 100644 packages/types/src/provider-settings/openrouter.ts create mode 100644 packages/types/src/provider-settings/poe.ts create mode 100644 packages/types/src/provider-settings/qwen-code.ts create mode 100644 packages/types/src/provider-settings/requesty.ts create mode 100644 packages/types/src/provider-settings/sambanova.ts create mode 100644 packages/types/src/provider-settings/unbound.ts create mode 100644 packages/types/src/provider-settings/vercel-ai-gateway.ts create mode 100644 packages/types/src/provider-settings/vertex.ts create mode 100644 packages/types/src/provider-settings/vscode-lm.ts create mode 100644 packages/types/src/provider-settings/xai.ts create mode 100644 packages/types/src/provider-settings/zai.ts create mode 100644 packages/types/src/provider-settings/zoo-gateway.ts diff --git a/packages/types/src/__tests__/provider-model-id.test.ts b/packages/types/src/__tests__/provider-model-id.test.ts new file mode 100644 index 0000000000..bec5425b54 --- /dev/null +++ b/packages/types/src/__tests__/provider-model-id.test.ts @@ -0,0 +1,90 @@ +import { getModelId, modelIdKeys, providerIdentifiers, type ProviderSettings } from "../index.js" + +const expectedModelIdKeys = [ + "apiModelId", + "openRouterModelId", + "openAiModelId", + "ollamaModelId", + "lmStudioModelId", + "lmStudioDraftModelId", + "requestyModelId", + "unboundModelId", + "litellmModelId", + "vercelAiGatewayModelId", + "opencodeGoModelId", + "kenariModelId", + "zooGatewayModelId", +] as const + +describe("modelIdKeys", () => { + it("preserves every model ID setting and its legacy precedence order", () => { + expect(modelIdKeys).toEqual(expectedModelIdKeys) + }) +}) + +describe("getModelId", () => { + it("uses a provider-specific model ID field instead of the shared apiModelId field", () => { + const settings: ProviderSettings = { + apiProvider: providerIdentifiers.openrouter, + apiModelId: "unrelated-model", + openRouterModelId: "openrouter-model", + } + + expect(getModelId(settings)).toBe("openrouter-model") + }) + + it("selects the active provider's field when multiple provider-specific model IDs are present", () => { + const settings: ProviderSettings = { + apiProvider: providerIdentifiers.ollama, + openRouterModelId: "inactive-openrouter-model", + ollamaModelId: "ollama-model", + } + + expect(getModelId(settings)).toBe("ollama-model") + }) + + it("uses the nested model selector for VS Code LM", () => { + const settings: ProviderSettings = { + apiProvider: providerIdentifiers.vscodeLm, + vsCodeLmModelSelector: { vendor: "copilot", family: "gpt-4o", id: "vscode-model", version: "1" }, + } + + expect(getModelId(settings)).toBe("vscode-model") + }) + + it("uses openAiModelId for OpenAI Compatible", () => { + const settings: ProviderSettings = { + apiProvider: providerIdentifiers.openai, + apiModelId: "unrelated-model", + openAiModelId: "openai-compatible-model", + } + + expect(getModelId(settings)).toBe("openai-compatible-model") + }) + + it.each([providerIdentifiers.openaiNative, providerIdentifiers.fakeAi])("uses apiModelId for %s", (apiProvider) => { + const settings: ProviderSettings = { apiProvider, apiModelId: "shared-model" } + + expect(getModelId(settings)).toBe("shared-model") + }) + + it("returns undefined when no provider is selected", () => { + expect(getModelId({})).toBeUndefined() + }) + + it("preserves legacy model ID precedence for retired providers", () => { + const settings: ProviderSettings = { + apiProvider: "groq", + lmStudioDraftModelId: "draft-model", + requestyModelId: "requesty-model", + } + + expect(getModelId(settings)).toBe("draft-model") + }) + + it("resolves a model ID for every provider definition without throwing", () => { + for (const apiProvider of Object.values(providerIdentifiers)) { + expect(() => getModelId({ apiProvider })).not.toThrow() + } + }) +}) diff --git a/packages/types/src/__tests__/provider-settings.test.ts b/packages/types/src/__tests__/provider-settings.test.ts index cd786a6529..33fa4e3aac 100644 --- a/packages/types/src/__tests__/provider-settings.test.ts +++ b/packages/types/src/__tests__/provider-settings.test.ts @@ -1,4 +1,4 @@ -import { ANTHROPIC_API_PROTOCOL, OPENAI_API_PROTOCOL, providerIdentifiers } from "../index.js" +import { ANTHROPIC_API_PROTOCOL, OPENAI_API_PROTOCOL, providerIdentifiers, providerNames } from "../index.js" import { getApiProtocol, OPEN_AI_CODEX_SERVICE_TIER_KEY, @@ -7,6 +7,20 @@ import { providerSettingsSchemaDiscriminated, } from "../provider-settings.js" import { OpenAiCodexServiceTier, OpenAiServiceTier } from "../model.js" +import { providerDefinitionList } from "../provider-settings/index.js" + +describe("provider settings discriminated union", () => { + it("composes exactly one provider-specific definition for every provider", () => { + const registeredProviders = providerDefinitionList.map(({ apiProvider }) => apiProvider) + + expect([...registeredProviders].sort()).toEqual([...providerNames].sort()) + expect(new Set(registeredProviders).size).toBe(providerNames.length) + }) + + it.each(providerNames)("accepts the %s provider branch", (apiProvider) => { + expect(providerSettingsSchemaDiscriminated.safeParse({ apiProvider }).success).toBe(true) + }) +}) describe("OpenAI Codex provider settings", () => { it("preserves the Fast preference in general and provider-specific schemas", () => { diff --git a/packages/types/src/provider-settings.ts b/packages/types/src/provider-settings.ts index 99b75de2e4..240e34e152 100644 --- a/packages/types/src/provider-settings.ts +++ b/packages/types/src/provider-settings.ts @@ -1,13 +1,17 @@ import { z } from "zod" -import { - modelInfoSchema, - openAiCodexServiceTierSchema, - reasoningEffortSettingSchema, - verbosityLevelsSchema, - serviceTierSchema, -} from "./model.js" +import { providerDefinitionList, type ProviderDefinition } from "./provider-settings/index.js" +import { API_PROVIDER_FIELD, SETTINGS_SHAPE_FIELD } from "./provider-settings/common.js" +export { + OPEN_AI_CODEX_SERVICE_TIER_KEY, + kimiCodeAuthMethodSchema, + type KimiCodeAuthMethod, + zaiApiLineSchema, + type ZaiApiLine, +} from "./provider-settings/index.js" + import { codebaseIndexProviderSchema } from "./codebase-index.js" +import type { UnionToIntersection } from "./type-fu.js" import { providerIdentifiers, retiredProviderIdentifiers, @@ -44,7 +48,6 @@ import { */ export const DEFAULT_CONSECUTIVE_MISTAKE_LIMIT = 3 -export const OPEN_AI_CODEX_SERVICE_TIER_KEY = "openAiCodexServiceTier" /** * DynamicProvider @@ -163,7 +166,7 @@ export type ProviderNameWithRetired = z.infer * ProviderSettings */ -const baseProviderSettingsSchema = z.object({ - includeMaxTokens: z.boolean().optional(), - todoListEnabled: z.boolean().optional(), - modelTemperature: z.number().nullish(), - rateLimitSeconds: z.number().optional(), - consecutiveMistakeLimit: z.number().min(0).optional(), - - // Model reasoning. - enableReasoningEffort: z.boolean().optional(), - reasoningEffort: reasoningEffortSettingSchema.optional(), - modelMaxTokens: z.number().optional(), - modelMaxThinkingTokens: z.number().optional(), - - // Model verbosity. - verbosity: verbosityLevelsSchema.optional(), -}) - -// Several of the providers share common model config properties. -const apiModelIdProviderModelSchema = baseProviderSettingsSchema.extend({ - apiModelId: z.string().optional(), -}) - -const anthropicSchema = apiModelIdProviderModelSchema.extend({ - apiKey: z.string().optional(), - anthropicBaseUrl: z.string().optional(), - anthropicUseAuthToken: z.boolean().optional(), - anthropicBeta1MContext: z.boolean().optional(), // Enable 'context-1m-2025-08-07' beta for 1M context window. -}) - -const openRouterSchema = baseProviderSettingsSchema.extend({ - openRouterApiKey: z.string().optional(), - openRouterModelId: z.string().optional(), - openRouterBaseUrl: z.string().optional(), - openRouterSpecificProvider: z.string().optional(), -}) - -const bedrockSchema = apiModelIdProviderModelSchema.extend({ - awsAccessKey: z.string().optional(), - awsSecretKey: z.string().optional(), - awsSessionToken: z.string().optional(), - awsRegion: z.string().optional(), - awsUseCrossRegionInference: z.boolean().optional(), - awsUseGlobalInference: z.boolean().optional(), // Enable Global Inference profile routing when supported - awsUsePromptCache: z.boolean().optional(), - awsProfile: z.string().optional(), - awsUseProfile: z.boolean().optional(), - awsApiKey: z.string().optional(), - awsUseApiKey: z.boolean().optional(), - awsCustomArn: z.string().optional(), - awsModelContextWindow: z.number().optional(), - awsBedrockEndpointEnabled: z.boolean().optional(), - awsBedrockEndpoint: z.string().optional(), - awsBedrock1MContext: z.boolean().optional(), // Enable 'context-1m-2025-08-07' beta for 1M context window. - awsBedrockServiceTier: z.enum(["STANDARD", "FLEX", "PRIORITY"]).optional(), // AWS Bedrock service tier selection -}) - -const vertexSchema = apiModelIdProviderModelSchema.extend({ - vertexKeyFile: z.string().optional(), - vertexJsonCredentials: z.string().optional(), - vertexProjectId: z.string().optional(), - vertexRegion: z.string().optional(), - vertex1MContext: z.boolean().optional(), // Enable 'context-1m-2025-08-07' beta for 1M context window. -}) - -const openAiSchema = baseProviderSettingsSchema.extend({ - openAiBaseUrl: z.string().optional(), - openAiApiKey: z.string().optional(), - openAiR1FormatEnabled: z.boolean().optional(), - openAiModelId: z.string().optional(), - openAiCustomModelInfo: modelInfoSchema.nullish(), - openAiUseAzure: z.boolean().optional(), - azureApiVersion: z.string().optional(), - openAiStreamingEnabled: z.boolean().optional(), - openAiHostHeader: z.string().optional(), // Keep temporarily for backward compatibility during migration. - openAiHeaders: z.record(z.string(), z.string()).optional(), -}) - -const ollamaSchema = baseProviderSettingsSchema.extend({ - ollamaModelId: z.string().optional(), - ollamaBaseUrl: z.string().optional(), - ollamaApiKey: z.string().optional(), - ollamaNumCtx: z.number().int().min(128).optional(), -}) - -const vsCodeLmSchema = baseProviderSettingsSchema.extend({ - vsCodeLmModelSelector: z - .object({ - vendor: z.string().optional(), - family: z.string().optional(), - version: z.string().optional(), - id: z.string().optional(), - }) - .optional(), -}) - -const lmStudioSchema = baseProviderSettingsSchema.extend({ - lmStudioModelId: z.string().optional(), - lmStudioBaseUrl: z.string().optional(), - lmStudioDraftModelId: z.string().optional(), - lmStudioSpeculativeDecodingEnabled: z.boolean().optional(), -}) - -const geminiSchema = apiModelIdProviderModelSchema.extend({ - geminiApiKey: z.string().optional(), - googleGeminiBaseUrl: z.string().optional(), -}) - -const geminiCliSchema = apiModelIdProviderModelSchema.extend({ - geminiCliOAuthPath: z.string().optional(), - geminiCliProjectId: z.string().optional(), -}) - -const openAiCodexSchema = apiModelIdProviderModelSchema.extend({ - // Codex "Fast" mode maps to the Responses API priority service tier. - [OPEN_AI_CODEX_SERVICE_TIER_KEY]: openAiCodexServiceTierSchema.optional(), -}) - -const openAiNativeSchema = apiModelIdProviderModelSchema.extend({ - openAiNativeApiKey: z.string().optional(), - openAiNativeBaseUrl: z.string().optional(), - // OpenAI Responses API service tier for openai-native provider only. - // UI should only expose this when the selected model supports flex/priority. - openAiNativeServiceTier: serviceTierSchema.optional(), -}) - -const mistralSchema = apiModelIdProviderModelSchema.extend({ - mistralApiKey: z.string().optional(), - mistralCodestralUrl: z.string().optional(), -}) - -const deepSeekSchema = apiModelIdProviderModelSchema.extend({ - deepSeekBaseUrl: z.string().optional(), - deepSeekApiKey: z.string().optional(), -}) - -const poeSchema = apiModelIdProviderModelSchema.extend({ - poeApiKey: z.string().optional(), - poeBaseUrl: z.string().optional(), -}) - -const moonshotSchema = apiModelIdProviderModelSchema.extend({ - moonshotBaseUrl: z - .union([z.literal("https://api.moonshot.ai/v1"), z.literal("https://api.moonshot.cn/v1")]) - .optional(), - moonshotApiKey: z.string().optional(), -}) - -export const kimiCodeAuthMethodSchema = z.enum(["oauth", "api-key"]) -export type KimiCodeAuthMethod = z.infer - -const kimiCodeSchema = apiModelIdProviderModelSchema.extend({ - kimiCodeAuthMethod: kimiCodeAuthMethodSchema.optional(), - kimiCodeApiKey: z.string().optional(), -}) - -const minimaxSchema = apiModelIdProviderModelSchema.extend({ - minimaxBaseUrl: z - .union([z.literal("https://api.minimax.io/v1"), z.literal("https://api.minimaxi.com/v1")]) - .optional(), - minimaxApiKey: z.string().optional(), -}) - -const mimoSchema = apiModelIdProviderModelSchema.extend({ - mimoBaseUrl: z - .union([ - z.literal("https://api.xiaomimimo.com/v1"), - z.literal("https://token-plan-cn.xiaomimimo.com/v1"), - z.literal("https://token-plan-sgp.xiaomimimo.com/v1"), - z.literal("https://token-plan-ams.xiaomimimo.com/v1"), - ]) - .optional(), - mimoApiKey: z.string().optional(), -}) - -const requestySchema = baseProviderSettingsSchema.extend({ - requestyBaseUrl: z.string().optional(), - requestyApiKey: z.string().optional(), - requestyModelId: z.string().optional(), -}) - -const unboundSchema = baseProviderSettingsSchema.extend({ - unboundApiKey: z.string().optional(), - unboundModelId: z.string().optional(), -}) - -const fakeAiSchema = baseProviderSettingsSchema.extend({ - fakeAi: z.unknown().optional(), -}) - -const xaiSchema = apiModelIdProviderModelSchema.extend({ - xaiApiKey: z.string().optional(), -}) - -const litellmSchema = baseProviderSettingsSchema.extend({ - litellmBaseUrl: z.string().optional(), - litellmApiKey: z.string().optional(), - litellmModelId: z.string().optional(), - litellmUsePromptCache: z.boolean().optional(), -}) +type ListedProvider = (typeof providerDefinitionList)[number][typeof API_PROVIDER_FIELD] +const allProvidersAreDefined: Exclude extends never ? true : never = true +void allProvidersAreDefined -const sambaNovaSchema = apiModelIdProviderModelSchema.extend({ - sambaNovaApiKey: z.string().optional(), -}) +const indexProviderDefinitions = ( + definitions: readonly ProviderDefinition[], +): Partial> => { + const indexedDefinitions: Partial> = {} -export const zaiApiLineSchema = z.enum(["international_coding", "china_coding", "international_api", "china_api"]) + // Keep registry construction non-throwing so a malformed definition cannot prevent the extension from starting in production. + for (const definition of definitions) { + if (indexedDefinitions[definition.apiProvider]) { + console.warn(`Duplicate provider definition ignored: ${definition.apiProvider}`) + } -export type ZaiApiLine = z.infer + indexedDefinitions[definition.apiProvider] ??= definition + } -const zaiSchema = apiModelIdProviderModelSchema.extend({ - zaiApiKey: z.string().optional(), - zaiApiLine: zaiApiLineSchema.optional(), -}) + for (const provider of providerNames) { + if (!indexedDefinitions[provider]) { + console.warn(`Missing provider definition: ${provider}`) + } + } -const fireworksSchema = apiModelIdProviderModelSchema.extend({ - fireworksApiKey: z.string().optional(), -}) + return indexedDefinitions +} -const friendliSchema = apiModelIdProviderModelSchema.extend({ - friendliApiKey: z.string().optional(), -}) +const providerDefinitions = indexProviderDefinitions(providerDefinitionList) -const qwenCodeSchema = apiModelIdProviderModelSchema.extend({ - qwenCodeOauthPath: z.string().optional(), +const defaultSchema = z.object({ + [API_PROVIDER_FIELD]: z.undefined(), }) -const vercelAiGatewaySchema = baseProviderSettingsSchema.extend({ - vercelAiGatewayApiKey: z.string().optional(), - vercelAiGatewayModelId: z.string().optional(), -}) +type ProviderDefinitionSchemas = { + [K in keyof D]: D[K]["schema"] +} -const opencodeGoSchema = baseProviderSettingsSchema.extend({ - opencodeGoApiKey: z.string().optional(), - opencodeGoModelId: z.string().optional(), -}) +const getDiscriminatedSchemas = ( + definitions: D, +): ProviderDefinitionSchemas => { + const [firstDefinition, ...remainingDefinitions] = definitions + // Array mapping widens the tuple, so restore the per-definition schema tuple type expected by Zod. + return [ + firstDefinition.schema, + ...remainingDefinitions.map((definition) => definition.schema), + ] as ProviderDefinitionSchemas +} -const kenariSchema = baseProviderSettingsSchema.extend({ - kenariApiKey: z.string().optional(), - kenariModelId: z.string().optional(), -}) +const providerDiscriminatedSchemas = getDiscriminatedSchemas(providerDefinitionList) -const zooGatewaySchema = baseProviderSettingsSchema.extend({ - zooSessionToken: z.string().optional(), - zooGatewayModelId: z.string().optional(), - zooGatewayBaseUrl: z.string().optional(), -}) +export const providerSettingsSchemaDiscriminated = z.discriminatedUnion(API_PROVIDER_FIELD, [ + ...providerDiscriminatedSchemas, + defaultSchema, +]) -const basetenSchema = apiModelIdProviderModelSchema.extend({ - basetenApiKey: z.string().optional(), -}) +type ProviderSettingsShape = UnionToIntersection<(typeof providerDefinitionList)[number][typeof SETTINGS_SHAPE_FIELD]> -const defaultSchema = z.object({ - apiProvider: z.undefined(), -}) +const providerSettingsObjectSchema = providerDefinitionList.reduce( + (schema, definition) => schema.merge(z.object(definition[SETTINGS_SHAPE_FIELD])), + z.object({}), +) -export const providerSettingsSchemaDiscriminated = z.discriminatedUnion("apiProvider", [ - anthropicSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.anthropic) })), - openRouterSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.openrouter) })), - bedrockSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.bedrock) })), - vertexSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.vertex) })), - openAiSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.openai) })), - ollamaSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.ollama) })), - vsCodeLmSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.vscodeLm) })), - lmStudioSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.lmstudio) })), - geminiSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.gemini) })), - geminiCliSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.geminiCli) })), - openAiCodexSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.openaiCodex) })), - openAiNativeSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.openaiNative) })), - mistralSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.mistral) })), - deepSeekSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.deepseek) })), - poeSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.poe) })), - moonshotSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.moonshot) })), - kimiCodeSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.kimiCode) })), - minimaxSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.minimax) })), - mimoSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.mimo) })), - requestySchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.requesty) })), - unboundSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.unbound) })), - fakeAiSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.fakeAi) })), - xaiSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.xai) })), - basetenSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.baseten) })), - litellmSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.litellm) })), - sambaNovaSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.sambanova) })), - zaiSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.zai) })), - fireworksSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.fireworks) })), - friendliSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.friendli) })), - qwenCodeSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.qwenCode) })), - vercelAiGatewaySchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.vercelAiGateway) })), - opencodeGoSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.opencodeGo) })), - kenariSchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.kenari) })), - zooGatewaySchema.merge(z.object({ apiProvider: z.literal(providerIdentifiers.zooGateway) })), - defaultSchema, -]) +// `AnyZodObject.shape` loses the merged shape precision, so restore the type derived from the provider definitions. +const providerSettingsShape = providerSettingsObjectSchema.shape as ProviderSettingsShape export const providerSettingsSchema = z.object({ - apiProvider: providerNamesWithRetiredSchema.optional(), - ...anthropicSchema.shape, - ...openRouterSchema.shape, - ...bedrockSchema.shape, - ...vertexSchema.shape, - ...openAiSchema.shape, - ...ollamaSchema.shape, - ...vsCodeLmSchema.shape, - ...lmStudioSchema.shape, - ...geminiSchema.shape, - ...geminiCliSchema.shape, - ...openAiCodexSchema.shape, - ...openAiNativeSchema.shape, - ...mistralSchema.shape, - ...deepSeekSchema.shape, - ...poeSchema.shape, - ...moonshotSchema.shape, - ...kimiCodeSchema.shape, - ...minimaxSchema.shape, - ...mimoSchema.shape, - ...requestySchema.shape, - ...unboundSchema.shape, - ...fakeAiSchema.shape, - ...xaiSchema.shape, - ...basetenSchema.shape, - ...litellmSchema.shape, - ...sambaNovaSchema.shape, - ...zaiSchema.shape, - ...fireworksSchema.shape, - ...friendliSchema.shape, - ...qwenCodeSchema.shape, - ...vercelAiGatewaySchema.shape, - ...opencodeGoSchema.shape, - ...kenariSchema.shape, - ...zooGatewaySchema.shape, + [API_PROVIDER_FIELD]: providerNamesWithRetiredSchema.optional(), + ...providerSettingsShape, ...codebaseIndexProviderSchema.shape, }) @@ -517,9 +260,13 @@ export type ProviderSettingsWithId = z.infer +/** + * @deprecated Use `getModelId()` to resolve the model ID for the active provider. + */ export const modelIdKeys = [ "apiModelId", "openRouterModelId", @@ -534,56 +281,47 @@ export const modelIdKeys = [ "opencodeGoModelId", "kenariModelId", "zooGatewayModelId", -] as const satisfies readonly (keyof ProviderSettings)[] - -export type ModelIdKey = (typeof modelIdKeys)[number] - -export const getModelId = (settings: ProviderSettings): string | undefined => { - const modelIdKey = modelIdKeys.find((key) => settings[key]) - return modelIdKey ? settings[modelIdKey] : undefined -} +] as const satisfies readonly ModelIdKey[] /** - * TypicalProvider + * @deprecated Provider categories should use the specific provider type guards. */ - export type TypicalProvider = Exclude +/** + * @deprecated Use the specific provider type guards instead. + */ export const isTypicalProvider = (key: unknown): key is TypicalProvider => isProviderName(key) && !isInternalProvider(key) && !isCustomProvider(key) && !isFauxProvider(key) -export const modelIdKeysByProvider: Record = { - [providerIdentifiers.anthropic]: "apiModelId", - [providerIdentifiers.openrouter]: "openRouterModelId", - [providerIdentifiers.bedrock]: "apiModelId", - [providerIdentifiers.vertex]: "apiModelId", - [providerIdentifiers.openaiCodex]: "apiModelId", - [providerIdentifiers.openaiNative]: "openAiModelId", - [providerIdentifiers.ollama]: "ollamaModelId", - [providerIdentifiers.lmstudio]: "lmStudioModelId", - [providerIdentifiers.gemini]: "apiModelId", - [providerIdentifiers.geminiCli]: "apiModelId", - [providerIdentifiers.mistral]: "apiModelId", - [providerIdentifiers.moonshot]: "apiModelId", - [providerIdentifiers.kimiCode]: "apiModelId", - [providerIdentifiers.minimax]: "apiModelId", - [providerIdentifiers.mimo]: "apiModelId", - [providerIdentifiers.deepseek]: "apiModelId", - [providerIdentifiers.poe]: "apiModelId", - [providerIdentifiers.qwenCode]: "apiModelId", - [providerIdentifiers.requesty]: "requestyModelId", - [providerIdentifiers.unbound]: "unboundModelId", - [providerIdentifiers.xai]: "apiModelId", - [providerIdentifiers.baseten]: "apiModelId", - [providerIdentifiers.litellm]: "litellmModelId", - [providerIdentifiers.sambanova]: "apiModelId", - [providerIdentifiers.zai]: "apiModelId", - [providerIdentifiers.fireworks]: "apiModelId", - [providerIdentifiers.friendli]: "apiModelId", - [providerIdentifiers.vercelAiGateway]: "vercelAiGatewayModelId", - [providerIdentifiers.opencodeGo]: "opencodeGoModelId", - [providerIdentifiers.kenari]: "kenariModelId", - [providerIdentifiers.zooGateway]: "zooGatewayModelId", +/** + * @deprecated Use `getModelId()` instead. This map is retained for API compatibility. + */ +export const modelIdKeysByProvider = Object.fromEntries( + providerDefinitionList.flatMap((definition) => { + if (!isTypicalProvider(definition.apiProvider)) { + return [] + } + + if (!definition.modelIdKey) { + throw new Error(`Missing model ID key for provider definition: ${definition.apiProvider}`) + } + + return [[definition.apiProvider, definition.modelIdKey] as const] + }), +) as Record + +export function getModelId(settings: ProviderSettings): string | undefined { + if (isProviderName(settings.apiProvider)) { + return providerDefinitions[settings.apiProvider]?.getModelId(settings) + } + + if (typeof settings.apiProvider === "string" && isRetiredProvider(settings.apiProvider)) { + const modelIdKey = modelIdKeys.find((key) => settings[key]) + return modelIdKey ? settings[modelIdKey] : undefined + } + + return undefined } /** @@ -655,6 +393,7 @@ export const getApiProtocol = (provider: ProviderName | undefined, modelId?: str export const MODELS_BY_PROVIDER: Record< Exclude< ProviderName, + // OpenAI is custom-configured; Fake AI and Gemini CLI do not expose model lists. typeof providerIdentifiers.fakeAi | typeof providerIdentifiers.geminiCli | typeof providerIdentifiers.openai >, { id: ProviderName; label: string; models: string[] } diff --git a/packages/types/src/provider-settings/anthropic.ts b/packages/types/src/provider-settings/anthropic.ts new file mode 100644 index 0000000000..80ff6f15fb --- /dev/null +++ b/packages/types/src/provider-settings/anthropic.ts @@ -0,0 +1,22 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { + API_MODEL_ID_FIELD, + apiModelIdProviderModelShape, + createModelIdAccessor, + createProviderDefinition, +} from "./common.js" + +export const anthropicProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.anthropic, + modelIdKey: API_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(API_MODEL_ID_FIELD), + schema: { + ...apiModelIdProviderModelShape, + apiKey: z.string().optional(), + anthropicBaseUrl: z.string().optional(), + anthropicUseAuthToken: z.boolean().optional(), + anthropicBeta1MContext: z.boolean().optional(), // Enable 'context-1m-2025-08-07' beta for 1M context window. + }, +}) diff --git a/packages/types/src/provider-settings/baseten.ts b/packages/types/src/provider-settings/baseten.ts new file mode 100644 index 0000000000..ac9649af30 --- /dev/null +++ b/packages/types/src/provider-settings/baseten.ts @@ -0,0 +1,19 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { + API_MODEL_ID_FIELD, + apiModelIdProviderModelShape, + createModelIdAccessor, + createProviderDefinition, +} from "./common.js" + +export const basetenProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.baseten, + modelIdKey: API_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(API_MODEL_ID_FIELD), + schema: { + ...apiModelIdProviderModelShape, + basetenApiKey: z.string().optional(), + }, +}) diff --git a/packages/types/src/provider-settings/bedrock.ts b/packages/types/src/provider-settings/bedrock.ts new file mode 100644 index 0000000000..0456c7c232 --- /dev/null +++ b/packages/types/src/provider-settings/bedrock.ts @@ -0,0 +1,35 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { + API_MODEL_ID_FIELD, + apiModelIdProviderModelShape, + createModelIdAccessor, + createProviderDefinition, +} from "./common.js" + +export const bedrockProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.bedrock, + modelIdKey: API_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(API_MODEL_ID_FIELD), + schema: { + ...apiModelIdProviderModelShape, + awsAccessKey: z.string().optional(), + awsSecretKey: z.string().optional(), + awsSessionToken: z.string().optional(), + awsRegion: z.string().optional(), + awsUseCrossRegionInference: z.boolean().optional(), + awsUseGlobalInference: z.boolean().optional(), // Enable Global Inference profile routing when supported + awsUsePromptCache: z.boolean().optional(), + awsProfile: z.string().optional(), + awsUseProfile: z.boolean().optional(), + awsApiKey: z.string().optional(), + awsUseApiKey: z.boolean().optional(), + awsCustomArn: z.string().optional(), + awsModelContextWindow: z.number().optional(), + awsBedrockEndpointEnabled: z.boolean().optional(), + awsBedrockEndpoint: z.string().optional(), + awsBedrock1MContext: z.boolean().optional(), // Enable 'context-1m-2025-08-07' beta for 1M context window. + awsBedrockServiceTier: z.enum(["STANDARD", "FLEX", "PRIORITY"]).optional(), // AWS Bedrock service tier selection + }, +}) diff --git a/packages/types/src/provider-settings/common.ts b/packages/types/src/provider-settings/common.ts new file mode 100644 index 0000000000..e73a05f143 --- /dev/null +++ b/packages/types/src/provider-settings/common.ts @@ -0,0 +1,76 @@ +import { z } from "zod" + +import { reasoningEffortSettingSchema, verbosityLevelsSchema } from "../model.js" +import type { ProviderIdentifier } from "../provider-identifiers.js" + +export const API_PROVIDER_FIELD = "apiProvider" +export const SETTINGS_SHAPE_FIELD = "settingsShape" +export const API_MODEL_ID_FIELD = "apiModelId" + +export const baseProviderSettingsShape = { + includeMaxTokens: z.boolean().optional(), + todoListEnabled: z.boolean().optional(), + modelTemperature: z.number().nullish(), + rateLimitSeconds: z.number().optional(), + consecutiveMistakeLimit: z.number().min(0).optional(), + enableReasoningEffort: z.boolean().optional(), + reasoningEffort: reasoningEffortSettingSchema.optional(), + modelMaxTokens: z.number().optional(), + modelMaxThinkingTokens: z.number().optional(), + verbosity: verbosityLevelsSchema.optional(), +} + +export const apiModelIdProviderModelShape = { + ...baseProviderSettingsShape, + [API_MODEL_ID_FIELD]: z.string().optional(), +} + +type ModelId = string | undefined +type UntypedProviderSettings = Record +type ProviderModelIdAccessor = (settings: UntypedProviderSettings) => ModelId +type ProviderSettingsFromSchema = z.infer> +type TypedProviderModelIdAccessor = (settings: ProviderSettingsFromSchema) => ModelId + +type ProviderDefinitionInput

= { + apiProvider: P + schema: S + modelIdKey?: Extract + getModelId: TypedProviderModelIdAccessor +} + +export type ProviderDefinition = { + apiProvider: ProviderIdentifier + settingsShape: z.ZodRawShape + modelIdKey?: string + schema: z.ZodDiscriminatedUnionOption + getModelId: ProviderModelIdAccessor +} + +export const createModelIdAccessor = + (modelIdKey: string): ProviderModelIdAccessor => + (settings) => + settings[modelIdKey] as ModelId + +// `modelIdKey` supports deprecated exports. Remove it in favor of an accessor-only contract when those exports are removed. +export const createProviderDefinition =

({ + apiProvider, + schema, + ...modelIdDefinition +}: ProviderDefinitionInput) => { + const settingsSchema = z.object(schema) + const getModelId: ProviderModelIdAccessor = (settings) => { + const parsedSettings = settingsSchema.safeParse(settings) + return parsedSettings.success ? modelIdDefinition.getModelId(parsedSettings.data) : undefined + } + + return { + apiProvider, + settingsShape: schema, + modelIdKey: modelIdDefinition.modelIdKey, + schema: z.object({ + ...schema, + [API_PROVIDER_FIELD]: z.literal(apiProvider), + }), + getModelId, + } +} diff --git a/packages/types/src/provider-settings/deepseek.ts b/packages/types/src/provider-settings/deepseek.ts new file mode 100644 index 0000000000..746f87e421 --- /dev/null +++ b/packages/types/src/provider-settings/deepseek.ts @@ -0,0 +1,20 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { + API_MODEL_ID_FIELD, + apiModelIdProviderModelShape, + createModelIdAccessor, + createProviderDefinition, +} from "./common.js" + +export const deepSeekProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.deepseek, + modelIdKey: API_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(API_MODEL_ID_FIELD), + schema: { + ...apiModelIdProviderModelShape, + deepSeekBaseUrl: z.string().optional(), + deepSeekApiKey: z.string().optional(), + }, +}) diff --git a/packages/types/src/provider-settings/fake-ai.ts b/packages/types/src/provider-settings/fake-ai.ts new file mode 100644 index 0000000000..f6be6c72ed --- /dev/null +++ b/packages/types/src/provider-settings/fake-ai.ts @@ -0,0 +1,19 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { + API_MODEL_ID_FIELD, + apiModelIdProviderModelShape, + createModelIdAccessor, + createProviderDefinition, +} from "./common.js" + +export const fakeAiProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.fakeAi, + modelIdKey: API_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(API_MODEL_ID_FIELD), + schema: { + ...apiModelIdProviderModelShape, + fakeAi: z.unknown().optional(), + }, +}) diff --git a/packages/types/src/provider-settings/fireworks.ts b/packages/types/src/provider-settings/fireworks.ts new file mode 100644 index 0000000000..8d5e1ef3fa --- /dev/null +++ b/packages/types/src/provider-settings/fireworks.ts @@ -0,0 +1,19 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { + API_MODEL_ID_FIELD, + apiModelIdProviderModelShape, + createModelIdAccessor, + createProviderDefinition, +} from "./common.js" + +export const fireworksProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.fireworks, + modelIdKey: API_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(API_MODEL_ID_FIELD), + schema: { + ...apiModelIdProviderModelShape, + fireworksApiKey: z.string().optional(), + }, +}) diff --git a/packages/types/src/provider-settings/friendli.ts b/packages/types/src/provider-settings/friendli.ts new file mode 100644 index 0000000000..c64aa3595b --- /dev/null +++ b/packages/types/src/provider-settings/friendli.ts @@ -0,0 +1,19 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { + API_MODEL_ID_FIELD, + apiModelIdProviderModelShape, + createModelIdAccessor, + createProviderDefinition, +} from "./common.js" + +export const friendliProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.friendli, + modelIdKey: API_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(API_MODEL_ID_FIELD), + schema: { + ...apiModelIdProviderModelShape, + friendliApiKey: z.string().optional(), + }, +}) diff --git a/packages/types/src/provider-settings/gemini-cli.ts b/packages/types/src/provider-settings/gemini-cli.ts new file mode 100644 index 0000000000..29cd66d0ec --- /dev/null +++ b/packages/types/src/provider-settings/gemini-cli.ts @@ -0,0 +1,20 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { + API_MODEL_ID_FIELD, + apiModelIdProviderModelShape, + createModelIdAccessor, + createProviderDefinition, +} from "./common.js" + +export const geminiCliProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.geminiCli, + modelIdKey: API_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(API_MODEL_ID_FIELD), + schema: { + ...apiModelIdProviderModelShape, + geminiCliOAuthPath: z.string().optional(), + geminiCliProjectId: z.string().optional(), + }, +}) diff --git a/packages/types/src/provider-settings/gemini.ts b/packages/types/src/provider-settings/gemini.ts new file mode 100644 index 0000000000..fd287e34ac --- /dev/null +++ b/packages/types/src/provider-settings/gemini.ts @@ -0,0 +1,20 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { + API_MODEL_ID_FIELD, + apiModelIdProviderModelShape, + createModelIdAccessor, + createProviderDefinition, +} from "./common.js" + +export const geminiProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.gemini, + modelIdKey: API_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(API_MODEL_ID_FIELD), + schema: { + ...apiModelIdProviderModelShape, + geminiApiKey: z.string().optional(), + googleGeminiBaseUrl: z.string().optional(), + }, +}) diff --git a/packages/types/src/provider-settings/index.ts b/packages/types/src/provider-settings/index.ts new file mode 100644 index 0000000000..e97fbf5995 --- /dev/null +++ b/packages/types/src/provider-settings/index.ts @@ -0,0 +1,78 @@ +import { anthropicProviderDefinition } from "./anthropic.js" +import { openRouterProviderDefinition } from "./openrouter.js" +import { bedrockProviderDefinition } from "./bedrock.js" +import { vertexProviderDefinition } from "./vertex.js" +import { openAiProviderDefinition } from "./openai.js" +import { ollamaProviderDefinition } from "./ollama.js" +import { vsCodeLmProviderDefinition } from "./vscode-lm.js" +import { lmStudioProviderDefinition } from "./lm-studio.js" +import { geminiProviderDefinition } from "./gemini.js" +import { geminiCliProviderDefinition } from "./gemini-cli.js" +import { openAiCodexProviderDefinition } from "./openai-codex.js" +import { openAiNativeProviderDefinition } from "./openai-native.js" +import { mistralProviderDefinition } from "./mistral.js" +import { deepSeekProviderDefinition } from "./deepseek.js" +import { poeProviderDefinition } from "./poe.js" +import { moonshotProviderDefinition } from "./moonshot.js" +import { kimiCodeProviderDefinition } from "./kimi-code.js" +import { minimaxProviderDefinition } from "./minimax.js" +import { mimoProviderDefinition } from "./mimo.js" +import { requestyProviderDefinition } from "./requesty.js" +import { unboundProviderDefinition } from "./unbound.js" +import { fakeAiProviderDefinition } from "./fake-ai.js" +import { xaiProviderDefinition } from "./xai.js" +import { litellmProviderDefinition } from "./litellm.js" +import { sambaNovaProviderDefinition } from "./sambanova.js" +import { zaiProviderDefinition } from "./zai.js" +import { fireworksProviderDefinition } from "./fireworks.js" +import { friendliProviderDefinition } from "./friendli.js" +import { qwenCodeProviderDefinition } from "./qwen-code.js" +import { vercelAiGatewayProviderDefinition } from "./vercel-ai-gateway.js" +import { opencodeGoProviderDefinition } from "./opencode-go.js" +import { kenariProviderDefinition } from "./kenari.js" +import { zooGatewayProviderDefinition } from "./zoo-gateway.js" +import { basetenProviderDefinition } from "./baseten.js" + +import type { ProviderDefinition } from "./common.js" + +export { OPEN_AI_CODEX_SERVICE_TIER_KEY } from "./openai-codex.js" +export { kimiCodeAuthMethodSchema, type KimiCodeAuthMethod } from "./kimi-code.js" +export { zaiApiLineSchema, type ZaiApiLine } from "./zai.js" +export type { ProviderDefinition } from "./common.js" + +export const providerDefinitionList = [ + anthropicProviderDefinition, + openRouterProviderDefinition, + bedrockProviderDefinition, + vertexProviderDefinition, + openAiProviderDefinition, + ollamaProviderDefinition, + vsCodeLmProviderDefinition, + lmStudioProviderDefinition, + geminiProviderDefinition, + geminiCliProviderDefinition, + openAiCodexProviderDefinition, + openAiNativeProviderDefinition, + mistralProviderDefinition, + deepSeekProviderDefinition, + poeProviderDefinition, + moonshotProviderDefinition, + kimiCodeProviderDefinition, + minimaxProviderDefinition, + mimoProviderDefinition, + requestyProviderDefinition, + unboundProviderDefinition, + fakeAiProviderDefinition, + xaiProviderDefinition, + litellmProviderDefinition, + sambaNovaProviderDefinition, + zaiProviderDefinition, + fireworksProviderDefinition, + friendliProviderDefinition, + qwenCodeProviderDefinition, + vercelAiGatewayProviderDefinition, + opencodeGoProviderDefinition, + kenariProviderDefinition, + zooGatewayProviderDefinition, + basetenProviderDefinition, +] as const satisfies readonly ProviderDefinition[] diff --git a/packages/types/src/provider-settings/kenari.ts b/packages/types/src/provider-settings/kenari.ts new file mode 100644 index 0000000000..da1a082059 --- /dev/null +++ b/packages/types/src/provider-settings/kenari.ts @@ -0,0 +1,17 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { baseProviderSettingsShape, createModelIdAccessor, createProviderDefinition } from "./common.js" + +const KENARI_MODEL_ID_FIELD = "kenariModelId" + +export const kenariProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.kenari, + modelIdKey: KENARI_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(KENARI_MODEL_ID_FIELD), + schema: { + ...baseProviderSettingsShape, + kenariApiKey: z.string().optional(), + [KENARI_MODEL_ID_FIELD]: z.string().optional(), + }, +}) diff --git a/packages/types/src/provider-settings/kimi-code.ts b/packages/types/src/provider-settings/kimi-code.ts new file mode 100644 index 0000000000..44e6fd8d7b --- /dev/null +++ b/packages/types/src/provider-settings/kimi-code.ts @@ -0,0 +1,23 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { + API_MODEL_ID_FIELD, + apiModelIdProviderModelShape, + createModelIdAccessor, + createProviderDefinition, +} from "./common.js" + +export const kimiCodeAuthMethodSchema = z.enum(["oauth", "api-key"]) +export type KimiCodeAuthMethod = z.infer + +export const kimiCodeProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.kimiCode, + modelIdKey: API_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(API_MODEL_ID_FIELD), + schema: { + ...apiModelIdProviderModelShape, + kimiCodeAuthMethod: kimiCodeAuthMethodSchema.optional(), + kimiCodeApiKey: z.string().optional(), + }, +}) diff --git a/packages/types/src/provider-settings/litellm.ts b/packages/types/src/provider-settings/litellm.ts new file mode 100644 index 0000000000..018cbdecdd --- /dev/null +++ b/packages/types/src/provider-settings/litellm.ts @@ -0,0 +1,19 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { baseProviderSettingsShape, createModelIdAccessor, createProviderDefinition } from "./common.js" + +export const LITELLM_MODEL_ID_FIELD = "litellmModelId" + +export const litellmProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.litellm, + modelIdKey: LITELLM_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(LITELLM_MODEL_ID_FIELD), + schema: { + ...baseProviderSettingsShape, + litellmBaseUrl: z.string().optional(), + litellmApiKey: z.string().optional(), + [LITELLM_MODEL_ID_FIELD]: z.string().optional(), + litellmUsePromptCache: z.boolean().optional(), + }, +}) diff --git a/packages/types/src/provider-settings/lm-studio.ts b/packages/types/src/provider-settings/lm-studio.ts new file mode 100644 index 0000000000..dea9659d9b --- /dev/null +++ b/packages/types/src/provider-settings/lm-studio.ts @@ -0,0 +1,19 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { baseProviderSettingsShape, createModelIdAccessor, createProviderDefinition } from "./common.js" + +export const LM_STUDIO_MODEL_ID_FIELD = "lmStudioModelId" + +export const lmStudioProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.lmstudio, + modelIdKey: LM_STUDIO_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(LM_STUDIO_MODEL_ID_FIELD), + schema: { + ...baseProviderSettingsShape, + [LM_STUDIO_MODEL_ID_FIELD]: z.string().optional(), + lmStudioBaseUrl: z.string().optional(), + lmStudioDraftModelId: z.string().optional(), + lmStudioSpeculativeDecodingEnabled: z.boolean().optional(), + }, +}) diff --git a/packages/types/src/provider-settings/mimo.ts b/packages/types/src/provider-settings/mimo.ts new file mode 100644 index 0000000000..690ede3839 --- /dev/null +++ b/packages/types/src/provider-settings/mimo.ts @@ -0,0 +1,27 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { + API_MODEL_ID_FIELD, + apiModelIdProviderModelShape, + createModelIdAccessor, + createProviderDefinition, +} from "./common.js" + +export const mimoProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.mimo, + modelIdKey: API_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(API_MODEL_ID_FIELD), + schema: { + ...apiModelIdProviderModelShape, + mimoBaseUrl: z + .union([ + z.literal("https://api.xiaomimimo.com/v1"), + z.literal("https://token-plan-cn.xiaomimimo.com/v1"), + z.literal("https://token-plan-sgp.xiaomimimo.com/v1"), + z.literal("https://token-plan-ams.xiaomimimo.com/v1"), + ]) + .optional(), + mimoApiKey: z.string().optional(), + }, +}) diff --git a/packages/types/src/provider-settings/minimax.ts b/packages/types/src/provider-settings/minimax.ts new file mode 100644 index 0000000000..86e8b1ce98 --- /dev/null +++ b/packages/types/src/provider-settings/minimax.ts @@ -0,0 +1,22 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { + API_MODEL_ID_FIELD, + apiModelIdProviderModelShape, + createModelIdAccessor, + createProviderDefinition, +} from "./common.js" + +export const minimaxProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.minimax, + modelIdKey: API_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(API_MODEL_ID_FIELD), + schema: { + ...apiModelIdProviderModelShape, + minimaxBaseUrl: z + .union([z.literal("https://api.minimax.io/v1"), z.literal("https://api.minimaxi.com/v1")]) + .optional(), + minimaxApiKey: z.string().optional(), + }, +}) diff --git a/packages/types/src/provider-settings/mistral.ts b/packages/types/src/provider-settings/mistral.ts new file mode 100644 index 0000000000..d2353563b6 --- /dev/null +++ b/packages/types/src/provider-settings/mistral.ts @@ -0,0 +1,20 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { + API_MODEL_ID_FIELD, + apiModelIdProviderModelShape, + createModelIdAccessor, + createProviderDefinition, +} from "./common.js" + +export const mistralProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.mistral, + modelIdKey: API_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(API_MODEL_ID_FIELD), + schema: { + ...apiModelIdProviderModelShape, + mistralApiKey: z.string().optional(), + mistralCodestralUrl: z.string().optional(), + }, +}) diff --git a/packages/types/src/provider-settings/moonshot.ts b/packages/types/src/provider-settings/moonshot.ts new file mode 100644 index 0000000000..96292872f3 --- /dev/null +++ b/packages/types/src/provider-settings/moonshot.ts @@ -0,0 +1,25 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { + API_MODEL_ID_FIELD, + apiModelIdProviderModelShape, + createModelIdAccessor, + createProviderDefinition, +} from "./common.js" + +export const moonshotProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.moonshot, + modelIdKey: API_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(API_MODEL_ID_FIELD), + schema: { + ...apiModelIdProviderModelShape, + moonshotBaseUrl: z + .union([z.literal("https://api.moonshot.ai/v1"), z.literal("https://api.moonshot.cn/v1")]) + .optional(), + moonshotApiKey: z.string().optional(), + }, +}) + +export const kimiCodeAuthMethodSchema = z.enum(["oauth", "api-key"]) +export type KimiCodeAuthMethod = z.infer diff --git a/packages/types/src/provider-settings/ollama.ts b/packages/types/src/provider-settings/ollama.ts new file mode 100644 index 0000000000..323484ad8d --- /dev/null +++ b/packages/types/src/provider-settings/ollama.ts @@ -0,0 +1,19 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { baseProviderSettingsShape, createModelIdAccessor, createProviderDefinition } from "./common.js" + +export const OLLAMA_MODEL_ID_FIELD = "ollamaModelId" + +export const ollamaProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.ollama, + modelIdKey: OLLAMA_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(OLLAMA_MODEL_ID_FIELD), + schema: { + ...baseProviderSettingsShape, + [OLLAMA_MODEL_ID_FIELD]: z.string().optional(), + ollamaBaseUrl: z.string().optional(), + ollamaApiKey: z.string().optional(), + ollamaNumCtx: z.number().int().min(128).optional(), + }, +}) diff --git a/packages/types/src/provider-settings/openai-codex.ts b/packages/types/src/provider-settings/openai-codex.ts new file mode 100644 index 0000000000..93117224ae --- /dev/null +++ b/packages/types/src/provider-settings/openai-codex.ts @@ -0,0 +1,21 @@ +import { providerIdentifiers } from "../provider-identifiers.js" +import { openAiCodexServiceTierSchema } from "../model.js" +import { + API_MODEL_ID_FIELD, + apiModelIdProviderModelShape, + createModelIdAccessor, + createProviderDefinition, +} from "./common.js" + +export const OPEN_AI_CODEX_SERVICE_TIER_KEY = "openAiCodexServiceTier" + +export const openAiCodexProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.openaiCodex, + modelIdKey: API_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(API_MODEL_ID_FIELD), + schema: { + ...apiModelIdProviderModelShape, + // Codex "Fast" mode maps to the Responses API priority service tier. + [OPEN_AI_CODEX_SERVICE_TIER_KEY]: openAiCodexServiceTierSchema.optional(), + }, +}) diff --git a/packages/types/src/provider-settings/openai-native.ts b/packages/types/src/provider-settings/openai-native.ts new file mode 100644 index 0000000000..683fd4dfee --- /dev/null +++ b/packages/types/src/provider-settings/openai-native.ts @@ -0,0 +1,24 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { serviceTierSchema } from "../model.js" +import { + API_MODEL_ID_FIELD, + apiModelIdProviderModelShape, + createModelIdAccessor, + createProviderDefinition, +} from "./common.js" + +export const openAiNativeProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.openaiNative, + modelIdKey: API_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(API_MODEL_ID_FIELD), + schema: { + ...apiModelIdProviderModelShape, + openAiNativeApiKey: z.string().optional(), + openAiNativeBaseUrl: z.string().optional(), + // OpenAI Responses API service tier for openai-native provider only. + // UI should only expose this when the selected model supports flex/priority. + openAiNativeServiceTier: serviceTierSchema.optional(), + }, +}) diff --git a/packages/types/src/provider-settings/openai.ts b/packages/types/src/provider-settings/openai.ts new file mode 100644 index 0000000000..651d90f60d --- /dev/null +++ b/packages/types/src/provider-settings/openai.ts @@ -0,0 +1,26 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { modelInfoSchema } from "../model.js" +import { baseProviderSettingsShape, createModelIdAccessor, createProviderDefinition } from "./common.js" + +export const OPEN_AI_MODEL_ID_FIELD = "openAiModelId" + +export const openAiProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.openai, + modelIdKey: OPEN_AI_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(OPEN_AI_MODEL_ID_FIELD), + schema: { + ...baseProviderSettingsShape, + openAiBaseUrl: z.string().optional(), + openAiApiKey: z.string().optional(), + openAiR1FormatEnabled: z.boolean().optional(), + [OPEN_AI_MODEL_ID_FIELD]: z.string().optional(), + openAiCustomModelInfo: modelInfoSchema.nullish(), + openAiUseAzure: z.boolean().optional(), + azureApiVersion: z.string().optional(), + openAiStreamingEnabled: z.boolean().optional(), + openAiHostHeader: z.string().optional(), // Keep temporarily for backward compatibility during migration. + openAiHeaders: z.record(z.string(), z.string()).optional(), + }, +}) diff --git a/packages/types/src/provider-settings/opencode-go.ts b/packages/types/src/provider-settings/opencode-go.ts new file mode 100644 index 0000000000..f1e51890a0 --- /dev/null +++ b/packages/types/src/provider-settings/opencode-go.ts @@ -0,0 +1,17 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { baseProviderSettingsShape, createModelIdAccessor, createProviderDefinition } from "./common.js" + +export const OPENCODE_GO_MODEL_ID_FIELD = "opencodeGoModelId" + +export const opencodeGoProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.opencodeGo, + modelIdKey: OPENCODE_GO_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(OPENCODE_GO_MODEL_ID_FIELD), + schema: { + ...baseProviderSettingsShape, + opencodeGoApiKey: z.string().optional(), + [OPENCODE_GO_MODEL_ID_FIELD]: z.string().optional(), + }, +}) diff --git a/packages/types/src/provider-settings/openrouter.ts b/packages/types/src/provider-settings/openrouter.ts new file mode 100644 index 0000000000..8ed4480f88 --- /dev/null +++ b/packages/types/src/provider-settings/openrouter.ts @@ -0,0 +1,19 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { baseProviderSettingsShape, createModelIdAccessor, createProviderDefinition } from "./common.js" + +export const OPEN_ROUTER_MODEL_ID_FIELD = "openRouterModelId" + +export const openRouterProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.openrouter, + modelIdKey: OPEN_ROUTER_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(OPEN_ROUTER_MODEL_ID_FIELD), + schema: { + ...baseProviderSettingsShape, + openRouterApiKey: z.string().optional(), + [OPEN_ROUTER_MODEL_ID_FIELD]: z.string().optional(), + openRouterBaseUrl: z.string().optional(), + openRouterSpecificProvider: z.string().optional(), + }, +}) diff --git a/packages/types/src/provider-settings/poe.ts b/packages/types/src/provider-settings/poe.ts new file mode 100644 index 0000000000..d5c1055490 --- /dev/null +++ b/packages/types/src/provider-settings/poe.ts @@ -0,0 +1,20 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { + API_MODEL_ID_FIELD, + apiModelIdProviderModelShape, + createModelIdAccessor, + createProviderDefinition, +} from "./common.js" + +export const poeProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.poe, + modelIdKey: API_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(API_MODEL_ID_FIELD), + schema: { + ...apiModelIdProviderModelShape, + poeApiKey: z.string().optional(), + poeBaseUrl: z.string().optional(), + }, +}) diff --git a/packages/types/src/provider-settings/qwen-code.ts b/packages/types/src/provider-settings/qwen-code.ts new file mode 100644 index 0000000000..c1c2f8be81 --- /dev/null +++ b/packages/types/src/provider-settings/qwen-code.ts @@ -0,0 +1,19 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { + API_MODEL_ID_FIELD, + apiModelIdProviderModelShape, + createModelIdAccessor, + createProviderDefinition, +} from "./common.js" + +export const qwenCodeProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.qwenCode, + modelIdKey: API_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(API_MODEL_ID_FIELD), + schema: { + ...apiModelIdProviderModelShape, + qwenCodeOauthPath: z.string().optional(), + }, +}) diff --git a/packages/types/src/provider-settings/requesty.ts b/packages/types/src/provider-settings/requesty.ts new file mode 100644 index 0000000000..ec37d6bb68 --- /dev/null +++ b/packages/types/src/provider-settings/requesty.ts @@ -0,0 +1,18 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { baseProviderSettingsShape, createModelIdAccessor, createProviderDefinition } from "./common.js" + +export const REQUESTY_MODEL_ID_FIELD = "requestyModelId" + +export const requestyProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.requesty, + modelIdKey: REQUESTY_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(REQUESTY_MODEL_ID_FIELD), + schema: { + ...baseProviderSettingsShape, + requestyBaseUrl: z.string().optional(), + requestyApiKey: z.string().optional(), + [REQUESTY_MODEL_ID_FIELD]: z.string().optional(), + }, +}) diff --git a/packages/types/src/provider-settings/sambanova.ts b/packages/types/src/provider-settings/sambanova.ts new file mode 100644 index 0000000000..257883747b --- /dev/null +++ b/packages/types/src/provider-settings/sambanova.ts @@ -0,0 +1,23 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { + API_MODEL_ID_FIELD, + apiModelIdProviderModelShape, + createModelIdAccessor, + createProviderDefinition, +} from "./common.js" + +export const sambaNovaProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.sambanova, + modelIdKey: API_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(API_MODEL_ID_FIELD), + schema: { + ...apiModelIdProviderModelShape, + sambaNovaApiKey: z.string().optional(), + }, +}) + +export const zaiApiLineSchema = z.enum(["international_coding", "china_coding", "international_api", "china_api"]) + +export type ZaiApiLine = z.infer diff --git a/packages/types/src/provider-settings/unbound.ts b/packages/types/src/provider-settings/unbound.ts new file mode 100644 index 0000000000..cadecf5912 --- /dev/null +++ b/packages/types/src/provider-settings/unbound.ts @@ -0,0 +1,17 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { baseProviderSettingsShape, createModelIdAccessor, createProviderDefinition } from "./common.js" + +export const UNBOUND_MODEL_ID_FIELD = "unboundModelId" + +export const unboundProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.unbound, + modelIdKey: UNBOUND_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(UNBOUND_MODEL_ID_FIELD), + schema: { + ...baseProviderSettingsShape, + unboundApiKey: z.string().optional(), + [UNBOUND_MODEL_ID_FIELD]: z.string().optional(), + }, +}) diff --git a/packages/types/src/provider-settings/vercel-ai-gateway.ts b/packages/types/src/provider-settings/vercel-ai-gateway.ts new file mode 100644 index 0000000000..c9d838d7bc --- /dev/null +++ b/packages/types/src/provider-settings/vercel-ai-gateway.ts @@ -0,0 +1,17 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { baseProviderSettingsShape, createModelIdAccessor, createProviderDefinition } from "./common.js" + +export const VERCEL_AI_GATEWAY_MODEL_ID_FIELD = "vercelAiGatewayModelId" + +export const vercelAiGatewayProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.vercelAiGateway, + modelIdKey: VERCEL_AI_GATEWAY_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(VERCEL_AI_GATEWAY_MODEL_ID_FIELD), + schema: { + ...baseProviderSettingsShape, + vercelAiGatewayApiKey: z.string().optional(), + [VERCEL_AI_GATEWAY_MODEL_ID_FIELD]: z.string().optional(), + }, +}) diff --git a/packages/types/src/provider-settings/vertex.ts b/packages/types/src/provider-settings/vertex.ts new file mode 100644 index 0000000000..2bfa3b114e --- /dev/null +++ b/packages/types/src/provider-settings/vertex.ts @@ -0,0 +1,23 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { + API_MODEL_ID_FIELD, + apiModelIdProviderModelShape, + createModelIdAccessor, + createProviderDefinition, +} from "./common.js" + +export const vertexProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.vertex, + modelIdKey: API_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(API_MODEL_ID_FIELD), + schema: { + ...apiModelIdProviderModelShape, + vertexKeyFile: z.string().optional(), + vertexJsonCredentials: z.string().optional(), + vertexProjectId: z.string().optional(), + vertexRegion: z.string().optional(), + vertex1MContext: z.boolean().optional(), // Enable 'context-1m-2025-08-07' beta for 1M context window. + }, +}) diff --git a/packages/types/src/provider-settings/vscode-lm.ts b/packages/types/src/provider-settings/vscode-lm.ts new file mode 100644 index 0000000000..8579d69a5b --- /dev/null +++ b/packages/types/src/provider-settings/vscode-lm.ts @@ -0,0 +1,20 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { baseProviderSettingsShape, createProviderDefinition } from "./common.js" + +export const vsCodeLmProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.vscodeLm, + getModelId: (settings) => settings.vsCodeLmModelSelector?.id, + schema: { + ...baseProviderSettingsShape, + vsCodeLmModelSelector: z + .object({ + vendor: z.string().optional(), + family: z.string().optional(), + version: z.string().optional(), + id: z.string().optional(), + }) + .optional(), + }, +}) diff --git a/packages/types/src/provider-settings/xai.ts b/packages/types/src/provider-settings/xai.ts new file mode 100644 index 0000000000..d5c2fbb874 --- /dev/null +++ b/packages/types/src/provider-settings/xai.ts @@ -0,0 +1,19 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { + API_MODEL_ID_FIELD, + apiModelIdProviderModelShape, + createModelIdAccessor, + createProviderDefinition, +} from "./common.js" + +export const xaiProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.xai, + modelIdKey: API_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(API_MODEL_ID_FIELD), + schema: { + ...apiModelIdProviderModelShape, + xaiApiKey: z.string().optional(), + }, +}) diff --git a/packages/types/src/provider-settings/zai.ts b/packages/types/src/provider-settings/zai.ts new file mode 100644 index 0000000000..0f4c4a0333 --- /dev/null +++ b/packages/types/src/provider-settings/zai.ts @@ -0,0 +1,23 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { + API_MODEL_ID_FIELD, + apiModelIdProviderModelShape, + createModelIdAccessor, + createProviderDefinition, +} from "./common.js" + +export const zaiApiLineSchema = z.enum(["international_coding", "china_coding", "international_api", "china_api"]) +export type ZaiApiLine = z.infer + +export const zaiProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.zai, + modelIdKey: API_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(API_MODEL_ID_FIELD), + schema: { + ...apiModelIdProviderModelShape, + zaiApiKey: z.string().optional(), + zaiApiLine: zaiApiLineSchema.optional(), + }, +}) diff --git a/packages/types/src/provider-settings/zoo-gateway.ts b/packages/types/src/provider-settings/zoo-gateway.ts new file mode 100644 index 0000000000..d2082bff33 --- /dev/null +++ b/packages/types/src/provider-settings/zoo-gateway.ts @@ -0,0 +1,18 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { baseProviderSettingsShape, createModelIdAccessor, createProviderDefinition } from "./common.js" + +export const ZOO_GATEWAY_MODEL_ID_FIELD = "zooGatewayModelId" + +export const zooGatewayProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.zooGateway, + modelIdKey: ZOO_GATEWAY_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(ZOO_GATEWAY_MODEL_ID_FIELD), + schema: { + ...baseProviderSettingsShape, + zooSessionToken: z.string().optional(), + [ZOO_GATEWAY_MODEL_ID_FIELD]: z.string().optional(), + zooGatewayBaseUrl: z.string().optional(), + }, +}) diff --git a/packages/types/src/type-fu.ts b/packages/types/src/type-fu.ts index 0014e9b187..69f558f21a 100644 --- a/packages/types/src/type-fu.ts +++ b/packages/types/src/type-fu.ts @@ -6,6 +6,10 @@ export type Keys = keyof T export type Values = T[keyof T] +export type UnionToIntersection = (U extends unknown ? (value: U) => void : never) extends (value: infer I) => void + ? I + : never + export type Equals = (() => T extends X ? 1 : 2) extends () => T extends Y ? 1 : 2 ? true : false export type AssertEqual = T diff --git a/webview-ui/src/utils/__tests__/validate.spec.ts b/webview-ui/src/utils/__tests__/validate.spec.ts index 6ce9bf5245..8e2e223977 100644 --- a/webview-ui/src/utils/__tests__/validate.spec.ts +++ b/webview-ui/src/utils/__tests__/validate.spec.ts @@ -1,4 +1,9 @@ -import { type ProviderSettings, type OrganizationAllowList, type RouterModels } from "@roo-code/types" +import { + providerIdentifiers, + type ProviderSettings, + type OrganizationAllowList, + type RouterModels, +} from "@roo-code/types" // Mock i18next to return translation keys with interpolated values vi.mock("i18next", () => ({ @@ -114,6 +119,42 @@ describe("Model Validation Functions", () => { expect(result).toBeUndefined() }) + it.each([ + { + name: "OpenAI Native", + config: { + apiProvider: providerIdentifiers.openaiNative, + apiModelId: "blocked-model", + } satisfies ProviderSettings, + }, + { + name: "OpenAI Compatible", + config: { + apiProvider: providerIdentifiers.openai, + openAiModelId: "blocked-model", + } satisfies ProviderSettings, + }, + { + name: "VS Code LM", + config: { + apiProvider: providerIdentifiers.vscodeLm, + vsCodeLmModelSelector: { id: "blocked-model" }, + } satisfies ProviderSettings, + }, + ])("uses the provider-specific model field for $name organization validation", ({ config }) => { + const organizationAllowList: OrganizationAllowList = { + allowAll: false, + providers: { + [config.apiProvider!]: { allowAll: false, models: ["allowed-model"] }, + }, + } + + const result = getModelValidationError(config, undefined, organizationAllowList) + + expect(result).toContain("settings:validation.modelNotAllowed") + expect(result).toContain("model=blocked-model") + }) + it("handles empty model IDs gracefully", () => { const config: ProviderSettings = { apiProvider: "openrouter", diff --git a/webview-ui/src/utils/validate.ts b/webview-ui/src/utils/validate.ts index b750d8833b..e946906e10 100644 --- a/webview-ui/src/utils/validate.ts +++ b/webview-ui/src/utils/validate.ts @@ -3,14 +3,9 @@ import i18next from "i18next" import { type ProviderSettings, type OrganizationAllowList, - type ProviderName, type RouterModels, - modelIdKeysByProvider, - isProviderName, - isRetiredProvider, + getModelId, isDynamicProvider, - isFauxProvider, - isCustomProvider, providerIdentifiers, } from "@roo-code/types" @@ -189,8 +184,7 @@ function validateProviderAgainstOrganizationSettings( } if (!providerConfig.allowAll) { - const activeProvider = isRetiredProvider(provider) ? undefined : provider - const modelId = activeProvider ? getModelIdForProvider(apiConfiguration, activeProvider) : undefined + const modelId = getModelId(apiConfiguration) const allowedModels = providerConfig.models || [] if (modelId && !allowedModels.includes(modelId)) { @@ -206,18 +200,6 @@ function validateProviderAgainstOrganizationSettings( } } -function getModelIdForProvider(apiConfiguration: ProviderSettings, provider: ProviderName): string | undefined { - if (provider === providerIdentifiers.vscodeLm) { - return apiConfiguration.vsCodeLmModelSelector?.id - } - - if (isCustomProvider(provider) || isFauxProvider(provider)) { - return apiConfiguration.apiModelId - } - - return apiConfiguration[modelIdKeysByProvider[provider]] -} - /** * Validates an Amazon Bedrock ARN and optionally checks if the region in * the ARN matches the provided region. @@ -261,7 +243,7 @@ function validateDynamicProviderModelId( return undefined } - const modelId = getModelIdForProvider(apiConfiguration, provider) + const modelId = getModelId(apiConfiguration) if (!modelId) { return i18next.t("settings:validation.modelId") @@ -285,9 +267,7 @@ export function getModelValidationError( routerModels?: RouterModels, organizationAllowList?: OrganizationAllowList, ): string | undefined { - const modelId = isProviderName(apiConfiguration.apiProvider) - ? getModelIdForProvider(apiConfiguration, apiConfiguration.apiProvider) - : apiConfiguration.apiModelId + const modelId = getModelId(apiConfiguration) ?? apiConfiguration.apiModelId const configWithModelId = { ...apiConfiguration, From c35f6e89414ba07b982d1cdee0a6e0b90271bf9d Mon Sep 17 00:00:00 2001 From: "zoomote[bot]" <305051434+zoomote[bot]@users.noreply.github.com> Date: Fri, 14 Aug 2026 18:14:15 +0000 Subject: [PATCH 06/66] [Feat] Add GLM 5.3 support to Z AI and OpenCode Go (#1244) * feat(providers): add GLM 5.3 support * feat(providers): enable GLM 5.3 for Z AI coding plans * test(webview): cover Z AI model selection --------- Co-authored-by: @taltas <6816042+taltas@users.noreply.github.com> --- packages/types/src/__tests__/lite-llm.test.ts | 2 +- .../types/src/__tests__/opencode-go.test.ts | 17 ++++ .../src/__tests__/provider-settings.test.ts | 2 +- packages/types/src/providers/lite-llm.ts | 1 + packages/types/src/providers/opencode-go.ts | 15 +++ packages/types/src/providers/zai.ts | 44 +++++++++ .../providers/__tests__/opencode-go.spec.ts | 2 +- src/api/providers/__tests__/zai.spec.ts | 99 +++++++++++++++++++ .../fetchers/__tests__/litellm.spec.ts | 4 +- .../fetchers/__tests__/opencode-go.spec.ts | 14 +++ src/api/providers/zai.ts | 21 ++-- .../src/components/settings/ApiOptions.tsx | 1 + .../components/settings/ThinkingBudget.tsx | 21 ++-- .../__tests__/ThinkingBudget.spec.tsx | 20 ++++ .../__tests__/providerModelConfig.spec.ts | 33 +++++++ .../settings/utils/providerModelConfig.ts | 12 ++- .../hooks/__tests__/useSelectedModel.spec.ts | 47 +++++++++ .../components/ui/hooks/useSelectedModel.ts | 13 +-- 18 files changed, 337 insertions(+), 31 deletions(-) diff --git a/packages/types/src/__tests__/lite-llm.test.ts b/packages/types/src/__tests__/lite-llm.test.ts index 74436c1848..d276333aa5 100644 --- a/packages/types/src/__tests__/lite-llm.test.ts +++ b/packages/types/src/__tests__/lite-llm.test.ts @@ -20,7 +20,7 @@ describe("LiteLLM preserveReasoning model detection", () => { it("matches case-insensitively", () => { expect(isLiteLLMPreserveReasoningModel("MiniMax-M2.7-Highspeed")).toBe(true) - expect(isLiteLLMPreserveReasoningModel("GLM-5.2")).toBe(true) + expect(isLiteLLMPreserveReasoningModel("GLM-5.3")).toBe(true) }) it("does not match model ids that merely contain a known family as a substring", () => { diff --git a/packages/types/src/__tests__/opencode-go.test.ts b/packages/types/src/__tests__/opencode-go.test.ts index 8079fe1bcb..99376e3c35 100644 --- a/packages/types/src/__tests__/opencode-go.test.ts +++ b/packages/types/src/__tests__/opencode-go.test.ts @@ -21,6 +21,7 @@ describe("opencode-go registry", () => { "glm-5", "glm-5.1", "glm-5.2", + "glm-5.3", "kimi-k3", "kimi-k2.5", "kimi-k2.6", @@ -78,6 +79,22 @@ describe("opencode-go registry", () => { expect(info?.outputPrice).toBe(15.0) expect(info?.cacheReadsPrice).toBe(0.3) }) + + it("glm-5.3 exposes its native context, pricing, and always-on reasoning levels", () => { + const info = getOpencodeGoModelInfo("glm-5.3") + expect(info).toBeDefined() + expect(info?.maxTokens).toBe(131_072) + expect(info?.contextWindow).toBe(1_000_000) + expect(info?.supportsImages).toBe(false) + expect(info?.supportsPromptCache).toBe(true) + expect(info?.supportsMaxTokens).toBe(true) + expect(info?.supportsReasoningEffort).toEqual(["low", "high", "max"]) + expect(info?.reasoningEffort).toBe("max") + expect(info?.preserveReasoning).toBe(true) + expect(info?.inputPrice).toBe(1.4) + expect(info?.outputPrice).toBe(4.4) + expect(info?.cacheReadsPrice).toBe(0.26) + }) }) describe("OPENCODE_GO_ANTHROPIC_FORMAT_MODELS", () => { diff --git a/packages/types/src/__tests__/provider-settings.test.ts b/packages/types/src/__tests__/provider-settings.test.ts index 33fa4e3aac..ddf1ff4f5d 100644 --- a/packages/types/src/__tests__/provider-settings.test.ts +++ b/packages/types/src/__tests__/provider-settings.test.ts @@ -139,7 +139,7 @@ describe("getApiProtocol", () => { }) it("should return 'openai' for opencode-go OpenAI-format models (GLM/DeepSeek/etc.)", () => { - expect(getApiProtocol(providerIdentifiers.opencodeGo, "glm-5.2")).toBe(OPENAI_API_PROTOCOL) + expect(getApiProtocol(providerIdentifiers.opencodeGo, "glm-5.3")).toBe(OPENAI_API_PROTOCOL) expect(getApiProtocol(providerIdentifiers.opencodeGo, "deepseek-v4-pro")).toBe(OPENAI_API_PROTOCOL) expect(getApiProtocol(providerIdentifiers.opencodeGo, "kimi-k2.5")).toBe(OPENAI_API_PROTOCOL) expect(getApiProtocol(providerIdentifiers.opencodeGo, "mimo-v2.5")).toBe(OPENAI_API_PROTOCOL) diff --git a/packages/types/src/providers/lite-llm.ts b/packages/types/src/providers/lite-llm.ts index 2b72de9d51..36277774d7 100644 --- a/packages/types/src/providers/lite-llm.ts +++ b/packages/types/src/providers/lite-llm.ts @@ -56,6 +56,7 @@ export const LITELLM_PRESERVE_REASONING_MODEL_IDS = [ "glm-5", "glm-5.1", "glm-5.2", + "glm-5.3", "glm-5-turbo", // bedrock.ts, minimax.ts, opencode-go.ts diff --git a/packages/types/src/providers/opencode-go.ts b/packages/types/src/providers/opencode-go.ts index bd60c4d349..77e89fb80f 100644 --- a/packages/types/src/providers/opencode-go.ts +++ b/packages/types/src/providers/opencode-go.ts @@ -86,6 +86,21 @@ export const opencodeGoModels: Record = { description: "GLM-5.1 is Zhipu's most capable model with a 200k context window, 128k max output, and built-in thinking capabilities. Available via the Opencode Go plan.", }, + "glm-5.3": { + maxTokens: 131_072, + contextWindow: 1_000_000, + supportsImages: false, + supportsPromptCache: true, + supportsMaxTokens: true, + supportsReasoningEffort: ["low", "high", "max"], + reasoningEffort: "max", + preserveReasoning: true, + inputPrice: 1.4, + outputPrice: 4.4, + cacheReadsPrice: 0.26, + description: + "GLM-5.3 is Zhipu's flagship coding and agent model with a 1M context window, 128k max output, and always-on reasoning with configurable effort (Low/High/Max). Available via the Opencode Go plan.", + }, "glm-5.2": { maxTokens: 131_072, contextWindow: 1_000_000, diff --git a/packages/types/src/providers/zai.ts b/packages/types/src/providers/zai.ts index c2bd079264..a14edfe9e3 100644 --- a/packages/types/src/providers/zai.ts +++ b/packages/types/src/providers/zai.ts @@ -5,6 +5,7 @@ import { ZaiApiLine } from "../provider-settings.js" // https://docs.z.ai/guides/llm/glm-4-32b-0414-128k // https://docs.z.ai/guides/llm/glm-4.5 // https://docs.z.ai/guides/llm/glm-4.6 +// https://docs.z.ai/guides/llm/glm-5.3 // https://docs.z.ai/guides/llm/glm-5.1 // https://docs.z.ai/guides/llm/glm-5-turbo // https://docs.z.ai/guides/overview/pricing @@ -473,6 +474,42 @@ export const mainlandZAiModels = { }, } as const satisfies Record +const glm53CodingPlanModelInfo = { + maxTokens: 131_072, + contextWindow: 1_000_000, + supportsImages: false, + supportsPromptCache: true, + supportsMaxTokens: true, + supportsReasoningEffort: ["low", "high", "max"], + requiredReasoningEffort: true, + reasoningEffort: "max", + preserveReasoning: true, + description: + "GLM-5.3 is Zhipu's flagship coding and agent model with a 1M context window, 128k max output, and always-on reasoning with configurable effort (Low/High/Max). Available to GLM Coding Plan users.", +} as const satisfies ModelInfo + +export const internationalZAiCodingPlanOnlyModels = { + "glm-5.3": { + ...glm53CodingPlanModelInfo, + // GLM-5.3 API pricing is not published yet; use GLM-5.2 pricing provisionally. + inputPrice: 1.4, + outputPrice: 4.4, + cacheWritesPrice: 0, + cacheReadsPrice: 0.26, + }, +} as const satisfies Record + +export const mainlandZAiCodingPlanOnlyModels = { + "glm-5.3": { + ...glm53CodingPlanModelInfo, + // GLM-5.3 API pricing is not published yet; use GLM-5.2 pricing provisionally. + inputPrice: 0.68, + outputPrice: 2.28, + cacheWritesPrice: 0, + cacheReadsPrice: 0.13, + }, +} as const satisfies Record + export const ZAI_DEFAULT_TEMPERATURE = 0.6 export const zaiApiLineConfigs = { @@ -497,3 +534,10 @@ export const zaiApiLineConfigs = { isChina: true, }, } satisfies Record + +export function getZAiModels(apiLine: ZaiApiLine = "international_coding"): Record { + const isChina = zaiApiLineConfigs[apiLine].isChina + const regionalModels = isChina ? mainlandZAiModels : internationalZAiModels + const codingPlanOnlyModels = isChina ? mainlandZAiCodingPlanOnlyModels : internationalZAiCodingPlanOnlyModels + return apiLine.endsWith("_coding") ? { ...regionalModels, ...codingPlanOnlyModels } : regionalModels +} diff --git a/src/api/providers/__tests__/opencode-go.spec.ts b/src/api/providers/__tests__/opencode-go.spec.ts index 721e795eb4..98209ae325 100644 --- a/src/api/providers/__tests__/opencode-go.spec.ts +++ b/src/api/providers/__tests__/opencode-go.spec.ts @@ -802,7 +802,7 @@ describe("OpencodeGoHandler", () => { }) it("classifies OpenAI-compatible Go models as non-Anthropic-format", () => { - expect(isOpencodeGoAnthropicFormatModel("glm-5.2")).toBe(false) + expect(isOpencodeGoAnthropicFormatModel("glm-5.3")).toBe(false) expect(isOpencodeGoAnthropicFormatModel("kimi-k2.6")).toBe(false) expect(isOpencodeGoAnthropicFormatModel("deepseek-v4-pro")).toBe(false) expect(isOpencodeGoAnthropicFormatModel("mimo-v2.5")).toBe(false) diff --git a/src/api/providers/__tests__/zai.spec.ts b/src/api/providers/__tests__/zai.spec.ts index ac13152f37..440bbc2328 100644 --- a/src/api/providers/__tests__/zai.spec.ts +++ b/src/api/providers/__tests__/zai.spec.ts @@ -11,6 +11,7 @@ import { internationalZAiModels, mainlandZAiModels, ZAI_DEFAULT_TEMPERATURE, + getZAiModels, } from "@roo-code/types" import { ZAiHandler } from "../zai" @@ -141,6 +142,30 @@ describe("ZAiHandler", () => { expect(model.info.cacheReadsPrice).toBe(0.26) }) + it("should expose GLM-5.3 for the international Coding Plan with provisional GLM-5.2 pricing", () => { + const handlerWithModel = new ZAiHandler({ + apiModelId: "glm-5.3", + zaiApiKey: "test-zai-api-key", + zaiApiLine: "international_coding", + }) + const model = handlerWithModel.getModel() + expect(model.id).toBe("glm-5.3") + expect(model.info).toMatchObject({ + contextWindow: 1_000_000, + maxTokens: 131_072, + supportsImages: false, + supportsPromptCache: true, + supportsMaxTokens: true, + supportsReasoningEffort: ["low", "high", "max"], + requiredReasoningEffort: true, + reasoningEffort: "max", + preserveReasoning: true, + }) + expect(model.info.inputPrice).toBe(1.4) + expect(model.info.outputPrice).toBe(4.4) + expect(model.info.cacheReadsPrice).toBe(0.26) + }) + it("should return GLM-5-Turbo international model with thinking support", () => { const testModelId: InternationalZAiModelId = "glm-5-turbo" const handlerWithModel = new ZAiHandler({ @@ -277,6 +302,22 @@ describe("ZAiHandler", () => { expect(model.info.cacheReadsPrice).toBe(0.13) }) + it("should expose GLM-5.3 for the China Coding Plan", () => { + const handlerWithModel = new ZAiHandler({ + apiModelId: "glm-5.3", + zaiApiKey: "test-zai-api-key", + zaiApiLine: "china_coding", + }) + const model = handlerWithModel.getModel() + expect(model.id).toBe("glm-5.3") + expect(model.info.supportsReasoningEffort).toEqual(["low", "high", "max"]) + expect(model.info.requiredReasoningEffort).toBe(true) + expect(model.info.reasoningEffort).toBe("max") + expect(model.info.inputPrice).toBe(0.68) + expect(model.info.outputPrice).toBe(2.28) + expect(model.info.cacheReadsPrice).toBe(0.13) + }) + it("should return GLM-4.7 China model with thinking support", () => { const testModelId: MainlandZAiModelId = "glm-4.7" const handlerWithModel = new ZAiHandler({ @@ -348,6 +389,16 @@ describe("ZAiHandler", () => { expect(model.id).toBe(testModelId) expect(model.info).toEqual(internationalZAiModels[testModelId]) }) + + it("should not expose Coding Plan-only models", () => { + expect(getZAiModels("international_api")).not.toHaveProperty("glm-5.3") + const handlerWithModel = new ZAiHandler({ + apiModelId: "glm-5.3", + zaiApiKey: "test-zai-api-key", + zaiApiLine: "international_api", + }) + expect(handlerWithModel.getModel().id).toBe(internationalZAiDefaultModelId) + }) }) describe("China API", () => { @@ -387,6 +438,10 @@ describe("ZAiHandler", () => { expect(model.id).toBe(testModelId) expect(model.info).toEqual(mainlandZAiModels[testModelId]) }) + + it("should not expose Coding Plan-only models", () => { + expect(getZAiModels("china_api")).not.toHaveProperty("glm-5.3") + }) }) describe("Default behavior", () => { @@ -613,6 +668,50 @@ describe("ZAiHandler", () => { ) }) + it("should keep GLM-5.3 reasoning enabled when a persisted setting requests disable", async () => { + const handlerWithModel = new ZAiHandler({ + apiModelId: "glm-5.3", + zaiApiKey: "test-zai-api-key", + zaiApiLine: "international_coding", + reasoningEffort: "disable", + }) + + mockCreate.mockImplementationOnce(() => asyncStreamFrom([])) + + const messageGenerator = handlerWithModel.createMessage("system prompt", []) + await messageGenerator.next() + + expect(mockCreate).toHaveBeenCalledWith( + expect.objectContaining({ + model: "glm-5.3", + thinking: { type: "enabled" }, + reasoning_effort: "max", + }), + ) + }) + + it("should keep GLM-5.3 reasoning enabled when the master reasoning setting is disabled", async () => { + const handlerWithModel = new ZAiHandler({ + apiModelId: "glm-5.3", + zaiApiKey: "test-zai-api-key", + zaiApiLine: "international_coding", + enableReasoningEffort: false, + }) + + mockCreate.mockImplementationOnce(() => asyncStreamFrom([])) + + const messageGenerator = handlerWithModel.createMessage("system prompt", []) + await messageGenerator.next() + + expect(mockCreate).toHaveBeenCalledWith( + expect.objectContaining({ + model: "glm-5.3", + thinking: { type: "enabled" }, + reasoning_effort: "max", + }), + ) + }) + it("should omit reasoning_effort for GLM-5.2 when reasoningEffort is set to disable", async () => { const handlerWithModel = new ZAiHandler({ apiModelId: "glm-5.2", diff --git a/src/api/providers/fetchers/__tests__/litellm.spec.ts b/src/api/providers/fetchers/__tests__/litellm.spec.ts index 8e6d49ddae..9f7b80cb31 100644 --- a/src/api/providers/fetchers/__tests__/litellm.spec.ts +++ b/src/api/providers/fetchers/__tests__/litellm.spec.ts @@ -765,7 +765,7 @@ describe("getLiteLLMModels", () => { data: { data: [ { - model_name: "glm-5.2", + model_name: "glm-5.3", model_info: { max_tokens: 8192, max_input_tokens: 128000, @@ -782,7 +782,7 @@ describe("getLiteLLMModels", () => { const result = await getLiteLLMModels("test-api-key", "http://localhost:4000") - expect(result["glm-5.2"]).toMatchObject({ preserveReasoning: true }) + expect(result["glm-5.3"]).toMatchObject({ preserveReasoning: true }) }) it("does not match a model id that merely contains a known family as a substring", async () => { diff --git a/src/api/providers/fetchers/__tests__/opencode-go.spec.ts b/src/api/providers/fetchers/__tests__/opencode-go.spec.ts index c8607db4d3..20040ffb22 100644 --- a/src/api/providers/fetchers/__tests__/opencode-go.spec.ts +++ b/src/api/providers/fetchers/__tests__/opencode-go.spec.ts @@ -157,6 +157,20 @@ describe("Opencode Go Fetchers", () => { expect(info.outputPrice).toBe(4.4) }) + it("resolves GLM-5.3 with always-on Low/High/Max reasoning effort", () => { + const info = parseOpencodeGoModel({ id: "glm-5.3" }) + expect(info.contextWindow).toBe(1_000_000) + expect(info.maxTokens).toBe(131_072) + expect(info.supportsPromptCache).toBe(true) + expect(info.supportsMaxTokens).toBe(true) + expect(info.supportsReasoningEffort).toEqual(["low", "high", "max"]) + expect(info.reasoningEffort).toBe("max") + expect(info.preserveReasoning).toBe(true) + expect(info.inputPrice).toBe(1.4) + expect(info.outputPrice).toBe(4.4) + expect(info.cacheReadsPrice).toBe(0.26) + }) + it("falls back to defaults for an unknown model with no cache pricing", () => { const info = parseOpencodeGoModel({ id: "x", context_window: 100000, max_tokens: 8000 }) expect(info.supportsPromptCache).toBe(false) diff --git a/src/api/providers/zai.ts b/src/api/providers/zai.ts index 4854c814fd..65a6bf458c 100644 --- a/src/api/providers/zai.ts +++ b/src/api/providers/zai.ts @@ -2,13 +2,12 @@ import { Anthropic } from "@anthropic-ai/sdk" import OpenAI from "openai" import { - internationalZAiModels, - mainlandZAiModels, internationalZAiDefaultModelId, mainlandZAiDefaultModelId, type ModelInfo, ZAI_DEFAULT_TEMPERATURE, zaiApiLineConfigs, + getZAiModels, } from "@roo-code/types" import { type ApiHandlerOptions, getModelMaxOutputTokens } from "../../shared/api" @@ -29,14 +28,15 @@ type ZAiChatCompletionParams = Omit { constructor(options: ApiHandlerOptions) { - const isChina = zaiApiLineConfigs[options.zaiApiLine ?? "international_coding"].isChina - const models = (isChina ? mainlandZAiModels : internationalZAiModels) as unknown as Record + const apiLine = options.zaiApiLine ?? "international_coding" + const isChina = zaiApiLineConfigs[apiLine].isChina + const models = getZAiModels(apiLine) const defaultModelId = (isChina ? mainlandZAiDefaultModelId : internationalZAiDefaultModelId) as string super({ ...options, providerName: "Z.ai", - baseURL: zaiApiLineConfigs[options.zaiApiLine ?? "international_coding"].baseUrl, + baseURL: zaiApiLineConfigs[apiLine].baseUrl, apiKey: options.zaiApiKey ?? "not-provided", defaultProviderModelId: defaultModelId, providerModels: models, @@ -85,12 +85,15 @@ export class ZAiHandler extends BaseOpenAiCompatibleProvider { this.options.enableReasoningEffort === false ? undefined : (this.options.reasoningEffort ?? info.reasoningEffort) + const requiresReasoning = info.requiredReasoningEffort === true const effort = - raw && raw !== "disable" && Array.isArray(supported) && !supported.includes(raw) + requiresReasoning && (!raw || raw === "disable") ? info.reasoningEffort - : raw + : raw && Array.isArray(supported) && !supported.includes(raw) + ? info.reasoningEffort + : raw const reasoningEffort = effort && effort !== "disable" ? effort : undefined - const useReasoning = reasoningEffort !== undefined + const useReasoning = requiresReasoning || reasoningEffort !== undefined const max_tokens = this.options.modelMaxTokens || @@ -114,7 +117,7 @@ export class ZAiHandler extends BaseOpenAiCompatibleProvider { messages: [{ role: "system", content: systemPrompt }, ...convertedMessages], stream: true, stream_options: { include_usage: true }, - // Thinking is ON by default for these models, so explicitly disable it when needed. + // Models with required reasoning stay enabled even when an old setting requests disable. thinking: useReasoning ? { type: "enabled" } : { type: "disabled" }, reasoning_effort: reasoningEffort, tools: this.convertToolsForOpenAI(metadata?.tools), diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx index 0cc61052db..be7dad7542 100644 --- a/webview-ui/src/components/settings/ApiOptions.tsx +++ b/webview-ui/src/components/settings/ApiOptions.tsx @@ -722,6 +722,7 @@ const ApiOptions = ({ models={getStaticModelsForProvider( activeSelectedProvider, t("settings:labels.useCustomArn"), + apiConfiguration, )} modelIdKey="apiModelId" serviceName={getProviderServiceConfig(activeSelectedProvider).serviceName} diff --git a/webview-ui/src/components/settings/ThinkingBudget.tsx b/webview-ui/src/components/settings/ThinkingBudget.tsx index 9525ba7a95..d8ee0cd448 100644 --- a/webview-ui/src/components/settings/ThinkingBudget.tsx +++ b/webview-ui/src/components/settings/ThinkingBudget.tsx @@ -109,22 +109,27 @@ export const ThinkingBudget = ({ apiConfiguration, setApiConfigurationField, mod // Clamp to availableOptions so the Select trigger always renders a valid option. const storedReasoningEffort = apiConfiguration.reasoningEffort as ReasoningEffortOption | undefined const rawReasoningEffort: ReasoningEffortOption = storedReasoningEffort || defaultReasoningEffort + const fallbackReasoningEffort = availableOptions.includes(defaultReasoningEffort) + ? defaultReasoningEffort + : (availableOptions[0] ?? rawReasoningEffort) const currentReasoningEffort: ReasoningEffortOption = availableOptions.includes(rawReasoningEffort) ? rawReasoningEffort - : (availableOptions[0] ?? rawReasoningEffort) + : fallbackReasoningEffort // Set default reasoning effort when model supports it and no value is set useEffect(() => { - if (isReasoningEffortSupported && !apiConfiguration.reasoningEffort) { - // Only set a default if reasoning is required, otherwise leave as undefined (which maps to "disable") - if (modelInfo?.requiredReasoningEffort && defaultReasoningEffort !== "disable") { - setApiConfigurationField("reasoningEffort", defaultReasoningEffort as ReasoningEffortExtended, false) - } + if ( + isReasoningEffortSupported && + modelInfo?.requiredReasoningEffort && + storedReasoningEffort !== currentReasoningEffort && + currentReasoningEffort !== "disable" + ) { + setApiConfigurationField("reasoningEffort", currentReasoningEffort as ReasoningEffortExtended, false) } }, [ isReasoningEffortSupported, - apiConfiguration.reasoningEffort, - defaultReasoningEffort, + storedReasoningEffort, + currentReasoningEffort, modelInfo?.requiredReasoningEffort, setApiConfigurationField, ]) diff --git a/webview-ui/src/components/settings/__tests__/ThinkingBudget.spec.tsx b/webview-ui/src/components/settings/__tests__/ThinkingBudget.spec.tsx index 5f9b74dfe0..3c97ee20e9 100644 --- a/webview-ui/src/components/settings/__tests__/ThinkingBudget.spec.tsx +++ b/webview-ui/src/components/settings/__tests__/ThinkingBudget.spec.tsx @@ -289,6 +289,26 @@ describe("ThinkingBudget", () => { expect(screen.getByTestId("select")).toHaveAttribute("data-value", "low") }) + it("should normalize an invalid disabled value to the default for required reasoning", () => { + const setApiConfigurationField = vi.fn() + render( + , + ) + + expect(screen.getByTestId("select")).toHaveAttribute("data-value", "max") + expect(setApiConfigurationField).toHaveBeenCalledWith("reasoningEffort", "max", false) + }) + it("should fall back to rawReasoningEffort when availableOptions is empty", () => { // Covers the ?? rawReasoningEffort branch when availableOptions[0] is undefined render( diff --git a/webview-ui/src/components/settings/utils/__tests__/providerModelConfig.spec.ts b/webview-ui/src/components/settings/utils/__tests__/providerModelConfig.spec.ts index 153f30b0e2..868bdac319 100644 --- a/webview-ui/src/components/settings/utils/__tests__/providerModelConfig.spec.ts +++ b/webview-ui/src/components/settings/utils/__tests__/providerModelConfig.spec.ts @@ -110,6 +110,15 @@ describe("providerModelConfig", () => { expect(defaultId.length).toBeGreaterThan(0) }) + it("returns mainland default for Z.ai with china_api entrypoint", () => { + expect( + getDefaultModelIdForProvider("zai", { + apiProvider: "zai", + zaiApiLine: "china_api", + }), + ).toBe(mainlandZAiDefaultModelId) + }) + it("returns international default for Z.ai with international_coding entrypoint", () => { const defaultId = getDefaultModelIdForProvider("zai", { apiProvider: "zai", @@ -177,6 +186,30 @@ describe("providerModelConfig", () => { const models = getStaticModelsForProvider("openrouter") expect(Object.keys(models).length).toBe(0) }) + + it("shows GLM-5.3 only for Z.ai Coding Plan entrypoints", () => { + const internationalCoding = getStaticModelsForProvider("zai", undefined, { + apiProvider: "zai", + zaiApiLine: "international_coding", + }) + const chinaCoding = getStaticModelsForProvider("zai", undefined, { + apiProvider: "zai", + zaiApiLine: "china_coding", + }) + const internationalApi = getStaticModelsForProvider("zai", undefined, { + apiProvider: "zai", + zaiApiLine: "international_api", + }) + const chinaApi = getStaticModelsForProvider("zai", undefined, { + apiProvider: "zai", + zaiApiLine: "china_api", + }) + + expect(internationalCoding).toHaveProperty("glm-5.3") + expect(chinaCoding).toHaveProperty("glm-5.3") + expect(internationalApi).not.toHaveProperty("glm-5.3") + expect(chinaApi).not.toHaveProperty("glm-5.3") + }) }) describe("isStaticModelProvider", () => { diff --git a/webview-ui/src/components/settings/utils/providerModelConfig.ts b/webview-ui/src/components/settings/utils/providerModelConfig.ts index eccbf7ba1d..5e18944951 100644 --- a/webview-ui/src/components/settings/utils/providerModelConfig.ts +++ b/webview-ui/src/components/settings/utils/providerModelConfig.ts @@ -30,6 +30,8 @@ import { opencodeGoDefaultModelId, kenariDefaultModelId, zooGatewayDefaultModelId, + zaiApiLineConfigs, + getZAiModels, } from "@roo-code/types" import { MODELS_BY_PROVIDER } from "../constants" @@ -97,9 +99,8 @@ export const getProviderServiceConfig = (provider: ProviderName): ProviderServic export const getDefaultModelIdForProvider = (provider: ProviderName, apiConfiguration?: ProviderSettings): string => { // Handle Z.ai's China/International entrypoint distinction if (provider === providerIdentifiers.zai && apiConfiguration) { - return apiConfiguration.zaiApiLine === "china_coding" - ? mainlandZAiDefaultModelId - : internationalZAiDefaultModelId + const apiLine = apiConfiguration.zaiApiLine ?? "international_coding" + return zaiApiLineConfigs[apiLine].isChina ? mainlandZAiDefaultModelId : internationalZAiDefaultModelId } return PROVIDER_DEFAULT_MODEL_IDS[provider] ?? "" @@ -176,7 +177,12 @@ export function getProviderDocsSlug(provider: string) { export const getStaticModelsForProvider = ( provider: ProviderName, customArnLabel?: string, + apiConfiguration?: ProviderSettings, ): Record => { + if (provider === providerIdentifiers.zai) { + return getZAiModels(apiConfiguration?.zaiApiLine) + } + const models = MODELS_BY_PROVIDER[provider] ?? {} // Add custom-arn option for Bedrock diff --git a/webview-ui/src/components/ui/hooks/__tests__/useSelectedModel.spec.ts b/webview-ui/src/components/ui/hooks/__tests__/useSelectedModel.spec.ts index 2571614085..1619270457 100644 --- a/webview-ui/src/components/ui/hooks/__tests__/useSelectedModel.spec.ts +++ b/webview-ui/src/components/ui/hooks/__tests__/useSelectedModel.spec.ts @@ -30,6 +30,9 @@ import { kimiCodeDefaultModelInfo, lMStudioDefaultModelInfo, opencodeGoDefaultModelInfo, + getZAiModels, + internationalZAiDefaultModelId, + mainlandZAiDefaultModelId, providerIdentifiers, retiredProviderIdentifiers, } from "@roo-code/types" @@ -1281,6 +1284,50 @@ describe("useSelectedModel", () => { }) }) + describe("Z AI provider", () => { + it("uses the International Coding catalog when no API line is configured", () => { + const apiConfiguration: ProviderSettings = { + apiProvider: providerIdentifiers.zai, + apiModelId: "glm-5.3", + } + + const { result } = renderHook(() => useSelectedModel(apiConfiguration), { wrapper: createWrapper() }) + + expect(result.current.id).toBe("glm-5.3") + expect(result.current.info).toEqual(getZAiModels("international_coding")["glm-5.3"]) + }) + + it("uses the China Coding catalog for GLM-5.3", () => { + const apiConfiguration: ProviderSettings = { + apiProvider: providerIdentifiers.zai, + apiModelId: "glm-5.3", + zaiApiLine: "china_coding", + } + + const { result } = renderHook(() => useSelectedModel(apiConfiguration), { wrapper: createWrapper() }) + + expect(result.current.id).toBe("glm-5.3") + expect(result.current.info).toEqual(getZAiModels("china_coding")["glm-5.3"]) + expect(result.current.info?.inputPrice).toBe(0.68) + }) + + it.each([ + ["international_api", internationalZAiDefaultModelId], + ["china_api", mainlandZAiDefaultModelId], + ] as const)("falls back when GLM-5.3 is unavailable on %s", (zaiApiLine, expectedModelId) => { + const apiConfiguration: ProviderSettings = { + apiProvider: providerIdentifiers.zai, + apiModelId: "glm-5.3", + zaiApiLine, + } + + const { result } = renderHook(() => useSelectedModel(apiConfiguration), { wrapper: createWrapper() }) + + expect(result.current.id).toBe(expectedModelId) + expect(result.current.info).toEqual(getZAiModels(zaiApiLine)[expectedModelId]) + }) + }) + describe("Kimi Code provider", () => { it("should use the Kimi Code default while router models are loading and no model is configured", () => { mockUseRouterModels.mockReturnValue(createRouterModelsResult(undefined, { isLoading: true })) diff --git a/webview-ui/src/components/ui/hooks/useSelectedModel.ts b/webview-ui/src/components/ui/hooks/useSelectedModel.ts index 6ed20ef47d..d73edf57f9 100644 --- a/webview-ui/src/components/ui/hooks/useSelectedModel.ts +++ b/webview-ui/src/components/ui/hooks/useSelectedModel.ts @@ -20,8 +20,8 @@ import { vscodeLlmDefaultModelId, openAiCodexModels, sambaNovaModels, - internationalZAiModels, - mainlandZAiModels, + getZAiModels, + zaiApiLineConfigs, fireworksModels, friendliModels, basetenModels, @@ -305,11 +305,12 @@ function getSelectedModel({ return { id, info } } case providerIdentifiers.zai: { - const isChina = apiConfiguration.zaiApiLine === "china_coding" - const models = isChina ? mainlandZAiModels : internationalZAiModels + const apiLine = apiConfiguration.zaiApiLine ?? "international_coding" + const isChina = zaiApiLineConfigs[apiLine].isChina + const models = getZAiModels(apiLine) const defaultModelId = getProviderDefaultModelId(provider, { isChina }) - const id = apiConfiguration.apiModelId ?? defaultModelId - const info = models[id as keyof typeof models] + const id = getValidatedModelId(apiConfiguration.apiModelId, models, defaultModelId) + const info = models[id] return { id, info } } case providerIdentifiers.openaiNative: { From 13cc3fe724c2cc0a70c39fbec46f47508b94445d Mon Sep 17 00:00:00 2001 From: "zoomote[bot]" <305051434+zoomote[bot]@users.noreply.github.com> Date: Fri, 14 Aug 2026 18:17:57 +0000 Subject: [PATCH 07/66] [Feat] Add Gemini 3.7 Flash support (#1241) * feat(types): add Gemini 3.7 Flash support * fix(types): correct Gemini 3.7 Flash metadata --------- Co-authored-by: @taltas <6816042+taltas@users.noreply.github.com> --- packages/types/src/__tests__/google-models.test.ts | 12 ++++++++++++ packages/types/src/providers/gemini.ts | 13 +++++++++++++ packages/types/src/providers/vertex.ts | 13 +++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 packages/types/src/__tests__/google-models.test.ts diff --git a/packages/types/src/__tests__/google-models.test.ts b/packages/types/src/__tests__/google-models.test.ts new file mode 100644 index 0000000000..674fb5d83c --- /dev/null +++ b/packages/types/src/__tests__/google-models.test.ts @@ -0,0 +1,12 @@ +import { geminiModels } from "../providers/gemini.js" +import { vertexModels } from "../providers/vertex.js" + +describe.each([ + ["Gemini API", geminiModels["gemini-3.7-flash"]], + ["Vertex AI", vertexModels["gemini-3.7-flash"]], +])("Gemini 3.7 Flash on %s", (_provider, model) => { + it("exposes the supported thinking levels and introductory cache storage price", () => { + expect(model.supportsReasoningEffort).toEqual(["low", "medium", "high"]) + expect(model.cacheWritesPrice).toBe(0.5) + }) +}) diff --git a/packages/types/src/providers/gemini.ts b/packages/types/src/providers/gemini.ts index e180be0867..d3051a8229 100644 --- a/packages/types/src/providers/gemini.ts +++ b/packages/types/src/providers/gemini.ts @@ -6,6 +6,19 @@ export type GeminiModelId = keyof typeof geminiModels export const geminiDefaultModelId: GeminiModelId = "gemini-3.1-pro-preview" export const geminiModels = { + "gemini-3.7-flash": { + maxTokens: 65_536, + contextWindow: 1_048_576, + supportsImages: true, + supportsPromptCache: true, + supportsReasoningEffort: ["low", "medium", "high"], + reasoningEffort: "medium", + inputPrice: 0.75, + outputPrice: 3.75, + cacheReadsPrice: 0.075, + cacheWritesPrice: 0.5, + supportsReasoningBudget: false, + }, "gemini-3.6-flash": { maxTokens: 65_536, contextWindow: 1_048_576, diff --git a/packages/types/src/providers/vertex.ts b/packages/types/src/providers/vertex.ts index 46ff835682..1509f40469 100644 --- a/packages/types/src/providers/vertex.ts +++ b/packages/types/src/providers/vertex.ts @@ -6,6 +6,19 @@ export type VertexModelId = keyof typeof vertexModels export const vertexDefaultModelId: VertexModelId = "claude-sonnet-4-5@20250929" export const vertexModels = { + "gemini-3.7-flash": { + maxTokens: 65_536, + contextWindow: 1_048_576, + supportsImages: true, + supportsPromptCache: true, + supportsReasoningEffort: ["low", "medium", "high"], + reasoningEffort: "medium", + inputPrice: 0.75, + outputPrice: 3.75, + cacheReadsPrice: 0.075, + cacheWritesPrice: 0.5, + supportsReasoningBudget: false, + }, "gemini-3.6-flash": { maxTokens: 65_536, contextWindow: 1_048_576, From c4daefcc11ff23f6a2dbc65b2c73c5d9837af144 Mon Sep 17 00:00:00 2001 From: "zoomote[bot]" <305051434+zoomote[bot]@users.noreply.github.com> Date: Fri, 14 Aug 2026 19:10:49 +0000 Subject: [PATCH 08/66] [Feat] Add Qwen3.8 Max to OpenCode Go (#1245) * feat(opencode-go): add GLM-5.3 and Qwen3.8 Max * chore(opencode-go): narrow model update to Qwen * fix(opencode-go): avoid unsupported reasoning preservation * chore(opencode-go): keep provider sections separated --------- Co-authored-by: @taltas <6816042+taltas@users.noreply.github.com> --- packages/types/src/__tests__/lite-llm.test.ts | 1 + .../types/src/__tests__/opencode-go.test.ts | 17 +++++++++++++++++ .../src/__tests__/provider-settings.test.ts | 1 + packages/types/src/providers/lite-llm.ts | 15 +++++++-------- packages/types/src/providers/opencode-go.ts | 14 ++++++++++++++ src/api/providers/opencode-go.ts | 6 +++--- 6 files changed, 43 insertions(+), 11 deletions(-) diff --git a/packages/types/src/__tests__/lite-llm.test.ts b/packages/types/src/__tests__/lite-llm.test.ts index d276333aa5..87fdfdd0ad 100644 --- a/packages/types/src/__tests__/lite-llm.test.ts +++ b/packages/types/src/__tests__/lite-llm.test.ts @@ -21,6 +21,7 @@ describe("LiteLLM preserveReasoning model detection", () => { it("matches case-insensitively", () => { expect(isLiteLLMPreserveReasoningModel("MiniMax-M2.7-Highspeed")).toBe(true) expect(isLiteLLMPreserveReasoningModel("GLM-5.3")).toBe(true) + expect(isLiteLLMPreserveReasoningModel("QWEN3.8-MAX")).toBe(true) }) it("does not match model ids that merely contain a known family as a substring", () => { diff --git a/packages/types/src/__tests__/opencode-go.test.ts b/packages/types/src/__tests__/opencode-go.test.ts index 99376e3c35..adacbe274c 100644 --- a/packages/types/src/__tests__/opencode-go.test.ts +++ b/packages/types/src/__tests__/opencode-go.test.ts @@ -10,6 +10,7 @@ import { describe("opencode-go registry", () => { const anthropicFormatModels = [ + "qwen3.8-max", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-plus", @@ -80,6 +81,22 @@ describe("opencode-go registry", () => { expect(info?.cacheReadsPrice).toBe(0.3) }) + it("exposes current Qwen3.8 Max capabilities and Go pricing", () => { + const info = getOpencodeGoModelInfo("qwen3.8-max") + expect(info).toMatchObject({ + maxTokens: 131_072, + contextWindow: 1_000_000, + supportsImages: true, + supportsPromptCache: true, + supportsMaxTokens: true, + inputPrice: 2.0, + outputPrice: 6.0, + cacheReadsPrice: 0.25, + cacheWritesPrice: 2.5, + }) + expect(info?.preserveReasoning).toBeUndefined() + }) + it("glm-5.3 exposes its native context, pricing, and always-on reasoning levels", () => { const info = getOpencodeGoModelInfo("glm-5.3") expect(info).toBeDefined() diff --git a/packages/types/src/__tests__/provider-settings.test.ts b/packages/types/src/__tests__/provider-settings.test.ts index ddf1ff4f5d..b29a93ca3e 100644 --- a/packages/types/src/__tests__/provider-settings.test.ts +++ b/packages/types/src/__tests__/provider-settings.test.ts @@ -130,6 +130,7 @@ describe("getApiProtocol", () => { describe("Opencode Go provider", () => { it("should return 'anthropic' for opencode-go Anthropic-format models (Qwen/MiniMax)", () => { + expect(getApiProtocol(providerIdentifiers.opencodeGo, "qwen3.8-max")).toBe(ANTHROPIC_API_PROTOCOL) expect(getApiProtocol(providerIdentifiers.opencodeGo, "qwen3.7-max")).toBe(ANTHROPIC_API_PROTOCOL) expect(getApiProtocol(providerIdentifiers.opencodeGo, "qwen3.7-plus")).toBe(ANTHROPIC_API_PROTOCOL) expect(getApiProtocol(providerIdentifiers.opencodeGo, "qwen3.6-plus")).toBe(ANTHROPIC_API_PROTOCOL) diff --git a/packages/types/src/providers/lite-llm.ts b/packages/types/src/providers/lite-llm.ts index 36277774d7..2e19b5b8b7 100644 --- a/packages/types/src/providers/lite-llm.ts +++ b/packages/types/src/providers/lite-llm.ts @@ -24,14 +24,12 @@ export const litellmDefaultModelInfo: ModelInfo = { * * Rather than matching model-family substrings with a regex (which can * over-match unrelated aliases, e.g. a family fragment appearing inside a - * longer unrelated model id), this is an explicit list of the exact model - * ids that set `preserveReasoning: true` in their native provider config - * (see deepseek.ts, mimo.ts, moonshot.ts, bedrock.ts, fireworks.ts, zai.ts, - * minimax.ts, opencode-go.ts). The same behavior is inferred for a - * LiteLLM-routed alias of the same underlying model. Keep this list in sync - * with those registries. This is still best-effort: unrecognized aliases or - * renamed deployments will not match, and callers should treat it as a - * heuristic, not a source of truth. + * longer unrelated model id), this is an explicit list of models whose + * OpenAI-compatible routes use interleaved `reasoning_content`. Native + * provider metadata informs this list where applicable, but gateway routes + * can have different preservation semantics. This is still best-effort: + * unrecognized aliases or renamed deployments will not match, and callers + * should treat it as a heuristic, not a source of truth. */ export const LITELLM_PRESERVE_REASONING_MODEL_IDS = [ // deepseek.ts @@ -75,6 +73,7 @@ export const LITELLM_PRESERVE_REASONING_MODEL_IDS = [ "qwen3.6-plus", "qwen3.7-plus", "qwen3.7-max", + "qwen3.8-max", ] as const const LITELLM_PRESERVE_REASONING_MODEL_ID_SET = new Set(LITELLM_PRESERVE_REASONING_MODEL_IDS) diff --git a/packages/types/src/providers/opencode-go.ts b/packages/types/src/providers/opencode-go.ts index 77e89fb80f..0d218a3274 100644 --- a/packages/types/src/providers/opencode-go.ts +++ b/packages/types/src/providers/opencode-go.ts @@ -307,6 +307,19 @@ export const opencodeGoModels: Record = { description: "Qwen3.7 Max - Alibaba's flagship text-only reasoning agent model with a 1M context window, designed for long-horizon agent workflows. Available via the Opencode Go plan.", }, + "qwen3.8-max": { + maxTokens: 131_072, + contextWindow: 1_000_000, + supportsImages: true, + supportsPromptCache: true, + supportsMaxTokens: true, + inputPrice: 2.0, + outputPrice: 6.0, + cacheReadsPrice: 0.25, + cacheWritesPrice: 2.5, + description: + "Qwen3.8 Max - Alibaba's flagship multimodal reasoning model with a 1M context window, 128k max output, and long-horizon coding and agentic capabilities. Available via the Opencode Go plan.", + }, // --- DeepSeek --- "deepseek-v4-pro": { @@ -364,6 +377,7 @@ export const opencodeGoModels: Record = { */ export const OPENCODE_GO_ANTHROPIC_FORMAT_MODELS = new Set([ // --- Alibaba Qwen --- + "qwen3.8-max", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-plus", diff --git a/src/api/providers/opencode-go.ts b/src/api/providers/opencode-go.ts index be53dc1c02..6b3f633829 100644 --- a/src/api/providers/opencode-go.ts +++ b/src/api/providers/opencode-go.ts @@ -54,9 +54,9 @@ import { * * - OpenAI-compatible chat completions (`/v1/chat/completions`, "oa-compat") * — used by GLM, Kimi, DeepSeek, and MiMo models. - * - Anthropic Messages (`/v1/messages`) — used by Qwen (qwen3.7-max, - * qwen3.7-plus, qwen3.6-plus) and MiniMax (minimax-m3, minimax-m2.7, - * minimax-m2.5) models. + * - Anthropic Messages (`/v1/messages`) — used by Qwen (qwen3.8-max, + * qwen3.7-max, qwen3.7-plus, qwen3.6-plus) and MiniMax (minimax-m3, + * minimax-m2.7, minimax-m2.5) models. * * Sending an Anthropic-format model to the chat completions endpoint is * rejected with `401 Model is not supported for format oa-compat`, so this From 63634be70afdf5eafbb6bca57f8c112aa391912c Mon Sep 17 00:00:00 2001 From: "zoomote[bot]" <305051434+zoomote[bot]@users.noreply.github.com> Date: Fri, 14 Aug 2026 20:51:32 +0000 Subject: [PATCH 09/66] [Fix] DeepSeek V4 costs are underestimated after pricing changes (#1237) * feat(providers): add DeepSeek V4 Pro 0813 * fix(providers): distinguish DeepSeek V4 checkpoints * fix(providers): update DeepSeek V4 pricing --------- Co-authored-by: @taltas <6816042+taltas@users.noreply.github.com> --- .../src/__tests__/deepseek-v4-pro.test.ts | 82 +++++++++++++++++++ packages/types/src/providers/baseten.ts | 26 ++++++ packages/types/src/providers/deepseek.ts | 23 +++--- packages/types/src/providers/fireworks.ts | 16 +++- packages/types/src/providers/opencode-go.ts | 9 +- src/api/providers/__tests__/deepseek.spec.ts | 6 +- src/api/providers/__tests__/fireworks.spec.ts | 9 +- 7 files changed, 151 insertions(+), 20 deletions(-) create mode 100644 packages/types/src/__tests__/deepseek-v4-pro.test.ts diff --git a/packages/types/src/__tests__/deepseek-v4-pro.test.ts b/packages/types/src/__tests__/deepseek-v4-pro.test.ts new file mode 100644 index 0000000000..4449bfd1f6 --- /dev/null +++ b/packages/types/src/__tests__/deepseek-v4-pro.test.ts @@ -0,0 +1,82 @@ +import { basetenModels, deepSeekModels, fireworksModels, opencodeGoModels } from "../providers/index.js" + +describe("DeepSeek V4 Pro 0813 provider catalogs", () => { + it.each([ + ["DeepSeek", deepSeekModels["deepseek-v4-pro"]], + ["OpenCode Go", opencodeGoModels["deepseek-v4-pro"]], + ])("labels the first-party API checkpoint through %s", (_provider, model) => { + expect(model).toBeDefined() + expect(model?.displayName).toBe("DeepSeek V4 Pro 0813") + expect(model?.contextWindow).toBeGreaterThanOrEqual(1_000_000) + }) + + it("uses peak first-party pricing and unchanged OpenCode Go pricing", () => { + expect(deepSeekModels["deepseek-v4-flash"]).toMatchObject({ + supportsImages: false, + outputPrice: 1.32, + cacheWritesPrice: 0.44, + cacheReadsPrice: 0.014, + }) + expect(deepSeekModels["deepseek-v4-pro"].supportsImages).toBe(false) + expect(deepSeekModels["deepseek-v4-pro"]).toMatchObject({ + outputPrice: 3.96, + cacheWritesPrice: 1.32, + cacheReadsPrice: 0.044, + }) + expect(opencodeGoModels["deepseek-v4-pro"]).toMatchObject({ + inputPrice: 0.435, + outputPrice: 0.87, + cacheReadsPrice: 0.003625, + }) + expect(opencodeGoModels["deepseek-v4-flash"]).toMatchObject({ + inputPrice: 0.14, + outputPrice: 0.28, + cacheReadsPrice: 0.0028, + }) + }) + + // Self-hosted providers retain separate IDs for the preview weights and 0813 checkpoint. + it.each([ + ["Fireworks AI", fireworksModels["accounts/fireworks/models/deepseek-v4-pro"]], + ["Baseten", basetenModels["deepseek-ai/DeepSeek-V4-Pro"]], + ])("does not apply the API checkpoint label to %s", (_provider, model) => { + expect(model).toBeDefined() + expect("displayName" in model && typeof model.displayName === "string" ? model.displayName : "").not.toContain( + "0813", + ) + expect(model?.contextWindow).toBeGreaterThanOrEqual(1_000_000) + }) + + it.each([ + [ + "Fireworks AI", + fireworksModels["accounts/fireworks/models/deepseek-v4-pro-0813"], + { inputPrice: 1.32, outputPrice: 3.96, cacheReadsPrice: 0.044 }, + ], + [ + "Baseten", + basetenModels["deepseek-ai/DeepSeek-V4-Pro-0813"], + { inputPrice: 1.32, outputPrice: 3.96, cacheReadsPrice: 0.132 }, + ], + ])("publishes the dated checkpoint and provider-specific pricing for %s", (_provider, model, pricing) => { + expect(model).toMatchObject({ + displayName: "DeepSeek V4 Pro 0813", + ...pricing, + }) + }) + + it("keeps preview pricing separate and omits unverified cache-write prices", () => { + expect(fireworksModels["accounts/fireworks/models/deepseek-v4-pro"]).toMatchObject({ + inputPrice: 1.74, + outputPrice: 3.48, + cacheReadsPrice: 0.145, + }) + expect(basetenModels["deepseek-ai/DeepSeek-V4-Pro"]).toMatchObject({ + inputPrice: 1.74, + outputPrice: 3.48, + cacheReadsPrice: 0.145, + }) + expect(basetenModels["deepseek-ai/DeepSeek-V4-Pro"]).not.toHaveProperty("cacheWritesPrice") + expect(basetenModels["deepseek-ai/DeepSeek-V4-Pro-0813"]).not.toHaveProperty("cacheWritesPrice") + }) +}) diff --git a/packages/types/src/providers/baseten.ts b/packages/types/src/providers/baseten.ts index 27b8cbff4a..2c1701ab0a 100644 --- a/packages/types/src/providers/baseten.ts +++ b/packages/types/src/providers/baseten.ts @@ -83,6 +83,32 @@ export const basetenModels = { description: "DeepSeek's hybrid reasoning model with efficient long context scaling with GPT-5 level performance", }, + "deepseek-ai/DeepSeek-V4-Pro": { + displayName: "DeepSeek V4 Pro", + maxTokens: 384_000, + contextWindow: 1_000_000, + supportsImages: false, + supportsPromptCache: true, + supportsMaxTokens: true, + inputPrice: 1.74, + outputPrice: 3.48, + cacheReadsPrice: 0.145, + description: + "DeepSeek V4 Pro is a 1.6T-parameter mixture-of-experts model with a 1M context window for advanced reasoning, coding, and agentic workloads.", + }, + "deepseek-ai/DeepSeek-V4-Pro-0813": { + displayName: "DeepSeek V4 Pro 0813", + maxTokens: 384_000, + contextWindow: 1_000_000, + supportsImages: false, + supportsPromptCache: true, + supportsMaxTokens: true, + inputPrice: 1.32, + outputPrice: 3.96, + cacheReadsPrice: 0.132, + description: + "DeepSeek V4 Pro 0813 is a 1.6T-parameter mixture-of-experts model with a 1M context window for advanced reasoning, coding, and agentic workloads.", + }, "openai/gpt-oss-120b": { maxTokens: 16_384, contextWindow: 128_072, diff --git a/packages/types/src/providers/deepseek.ts b/packages/types/src/providers/deepseek.ts index 9387d6a4ae..806a7e162c 100644 --- a/packages/types/src/providers/deepseek.ts +++ b/packages/types/src/providers/deepseek.ts @@ -12,32 +12,33 @@ export const deepSeekModels = { "deepseek-v4-flash": { maxTokens: 384_000, contextWindow: 1_000_000, - supportsImages: true, + supportsImages: false, supportsPromptCache: true, supportsReasoningEffort: ["disable", "low", "high", "max"], // Updated 2026-08-01 preserveReasoning: true, reasoningEffort: "high", inputPrice: 0, // the inputs are priced as cache read/write, so `inputPrice` should be 0 - // the peak/off-peak pricing policy has not been implemented yet - Updated 2026-08-01 - outputPrice: 0.28, // $0.28 per million tokens - Updated 2026-08-01 - cacheWritesPrice: 0.14, // $0.14 per million tokens (cache miss) - Updated 2026-08-01 - cacheReadsPrice: 0.0028, // $0.0028 per million tokens (cache hit) - Updated 2026-08-01 + // Static estimates use peak rates; off-peak rates are 50% lower. Effective 2026-08-16. + outputPrice: 1.32, + cacheWritesPrice: 0.44, + cacheReadsPrice: 0.014, description: `DeepSeek-V4-Flash is DeepSeek's fast, cost-efficient V4 model. It supports thinking and non-thinking modes, JSON output, tool calls, chat prefix completion (beta), and FIM completion (beta) in non-thinking mode.`, }, "deepseek-v4-pro": { + displayName: "DeepSeek V4 Pro 0813", maxTokens: 384_000, contextWindow: 1_000_000, - supportsImages: true, + supportsImages: false, supportsPromptCache: true, supportsReasoningEffort: ["disable", "high", "max"], // Updated 2026-08-01 preserveReasoning: true, reasoningEffort: "high", inputPrice: 0, // the inputs are priced as cache read/write, so `inputPrice` should be 0 - // the peak/off-peak pricing policy has not been implemented yet - Updated 2026-08-01 - outputPrice: 0.87, // $0.87 per million tokens - Updated 2026-08-01 - cacheWritesPrice: 0.435, // $0.435 per million tokens (cache miss) - Updated 2026-08-01 - cacheReadsPrice: 0.003625, // $0.003625 per million tokens (cache hit) - Updated 2026-08-01 - description: `DeepSeek-V4-Pro is DeepSeek's strongest V4 model for reasoning, coding, long-context, and agentic workloads. It supports thinking and non-thinking modes, JSON output, tool calls, chat prefix completion (beta), and FIM completion (beta) in non-thinking mode.`, + // Static estimates use peak rates; off-peak rates are 50% lower. Effective 2026-08-16. + outputPrice: 3.96, + cacheWritesPrice: 1.32, + cacheReadsPrice: 0.044, + description: `DeepSeek-V4-Pro-0813 is DeepSeek's strongest V4 model for reasoning, coding, long-context, and agentic workloads. It supports thinking and non-thinking modes, JSON output, tool calls, chat prefix completion (beta), and FIM completion (beta) in non-thinking mode.`, }, } as const satisfies Record diff --git a/packages/types/src/providers/fireworks.ts b/packages/types/src/providers/fireworks.ts index 3b18ad50b8..993bf1ad8e 100644 --- a/packages/types/src/providers/fireworks.ts +++ b/packages/types/src/providers/fireworks.ts @@ -16,6 +16,7 @@ export type FireworksModelId = | "accounts/fireworks/models/deepseek-v3p1" | "accounts/fireworks/models/deepseek-v3p2" | "accounts/fireworks/models/deepseek-v4-pro" + | "accounts/fireworks/models/deepseek-v4-pro-0813" | "accounts/fireworks/models/glm-4p5" | "accounts/fireworks/models/glm-4p5-air" | "accounts/fireworks/models/glm-4p6" @@ -262,10 +263,23 @@ export const fireworksModels = { supportsPromptCache: true, inputPrice: 1.74, outputPrice: 3.48, - cacheReadsPrice: 0.14, + cacheReadsPrice: 0.145, description: "DeepSeek V4 Pro is the latest iteration of the DeepSeek model family, with improved reasoning, code generation, and instruction following over the V3 series.", }, + "accounts/fireworks/models/deepseek-v4-pro-0813": { + displayName: "DeepSeek V4 Pro 0813", + maxTokens: 384_000, + contextWindow: 1_000_000, + supportsImages: false, + supportsPromptCache: true, + supportsMaxTokens: true, + inputPrice: 1.32, + outputPrice: 3.96, + cacheReadsPrice: 0.044, + description: + "DeepSeek V4 Pro 0813 is DeepSeek's production checkpoint for advanced reasoning, coding, and long-context agentic workloads.", + }, "accounts/fireworks/models/kimi-k2p7-code": { maxTokens: 16384, contextWindow: 262144, diff --git a/packages/types/src/providers/opencode-go.ts b/packages/types/src/providers/opencode-go.ts index 0d218a3274..a7ae0de259 100644 --- a/packages/types/src/providers/opencode-go.ts +++ b/packages/types/src/providers/opencode-go.ts @@ -323,6 +323,7 @@ export const opencodeGoModels: Record = { // --- DeepSeek --- "deepseek-v4-pro": { + displayName: "DeepSeek V4 Pro 0813", maxTokens: 384_000, contextWindow: 1_000_000, supportsImages: false, @@ -336,11 +337,11 @@ export const opencodeGoModels: Record = { supportsReasoningEffort: ["disable", "low", "medium", "high", "xhigh"], preserveReasoning: true, reasoningEffort: "high", - inputPrice: 1.74, - outputPrice: 3.48, - cacheReadsPrice: 0.0145, + inputPrice: 0.435, + outputPrice: 0.87, + cacheReadsPrice: 0.003625, description: - "DeepSeek-V4-Pro is DeepSeek's strongest V4 model for reasoning, coding, long-context, and agentic workloads. Available via the Opencode Go plan.", + "DeepSeek-V4-Pro-0813 is DeepSeek's strongest V4 model for reasoning, coding, long-context, and agentic workloads. Available via the Opencode Go plan.", }, "deepseek-v4-flash": { maxTokens: 384_000, diff --git a/src/api/providers/__tests__/deepseek.spec.ts b/src/api/providers/__tests__/deepseek.spec.ts index 4f3cccdc08..0c9dc1d5c8 100644 --- a/src/api/providers/__tests__/deepseek.spec.ts +++ b/src/api/providers/__tests__/deepseek.spec.ts @@ -214,7 +214,7 @@ describe("DeepSeekHandler", () => { expect(model.info).toBeDefined() expect(model.info.maxTokens).toBe(384_000) expect(model.info.contextWindow).toBe(1_000_000) - expect(model.info.supportsImages).toBe(true) + expect(model.info.supportsImages).toBe(false) expect(model.info.supportsPromptCache).toBe(true) // Should be true now expect((model.info as ModelInfo).preserveReasoning).toBe(true) }) @@ -229,7 +229,7 @@ describe("DeepSeekHandler", () => { expect(model.id).toBe("deepseek-v4-flash") expect(model.info.maxTokens).toBe(384_000) expect(model.info.contextWindow).toBe(1_000_000) - expect(model.info.supportsImages).toBe(true) + expect(model.info.supportsImages).toBe(false) expect((model.info as ModelInfo).supportsReasoningEffort).toContain("max") }) @@ -243,7 +243,7 @@ describe("DeepSeekHandler", () => { expect(model.info).toBeDefined() expect(model.info.maxTokens).toBe(384_000) expect(model.info.contextWindow).toBe(1_000_000) - expect(model.info.supportsImages).toBe(true) + expect(model.info.supportsImages).toBe(false) expect(model.info.supportsPromptCache).toBe(true) expect((model.info as ModelInfo).preserveReasoning).toBe(true) expect((model.info as ModelInfo).reasoningEffort).toBe("high") diff --git a/src/api/providers/__tests__/fireworks.spec.ts b/src/api/providers/__tests__/fireworks.spec.ts index 353ee31552..bde144591d 100644 --- a/src/api/providers/__tests__/fireworks.spec.ts +++ b/src/api/providers/__tests__/fireworks.spec.ts @@ -118,7 +118,14 @@ describe("FireworksHandler", () => { contextWindow: 1048576, inputPrice: 1.74, outputPrice: 3.48, - cacheReadsPrice: 0.14, + cacheReadsPrice: 0.145, + }, + { + modelId: "accounts/fireworks/models/deepseek-v4-pro-0813" as const, + contextWindow: 1_000_000, + inputPrice: 1.32, + outputPrice: 3.96, + cacheReadsPrice: 0.044, }, ])( "should expose newly added model $modelId", From f7239c8751a5bac880a718a2a6062e1c140bf883 Mon Sep 17 00:00:00 2001 From: WHMHammer <35433952+WHMHammer@users.noreply.github.com> Date: Fri, 14 Aug 2026 23:59:38 +0000 Subject: [PATCH 10/66] fix: update deepseek-v4-pro reasoning efforts and mappings (#1236) * fix: update deepseek-v4-pro reasoning efforts and mappings * fix: deepseek-v4-pro unit testing * fix: remove deepseek price comment changes Prices are going to change on 2026-08-16. We need a separate PR for that. --- packages/types/src/providers/deepseek.ts | 4 ++-- src/api/providers/__tests__/deepseek.spec.ts | 13 +++++++++++- src/api/providers/deepseek.ts | 22 +++----------------- 3 files changed, 17 insertions(+), 22 deletions(-) diff --git a/packages/types/src/providers/deepseek.ts b/packages/types/src/providers/deepseek.ts index 806a7e162c..d9cf7ce755 100644 --- a/packages/types/src/providers/deepseek.ts +++ b/packages/types/src/providers/deepseek.ts @@ -14,7 +14,7 @@ export const deepSeekModels = { contextWindow: 1_000_000, supportsImages: false, supportsPromptCache: true, - supportsReasoningEffort: ["disable", "low", "high", "max"], // Updated 2026-08-01 + supportsReasoningEffort: ["disable", "low", "high", "max"], // Updated 2026-08-13 preserveReasoning: true, reasoningEffort: "high", inputPrice: 0, // the inputs are priced as cache read/write, so `inputPrice` should be 0 @@ -30,7 +30,7 @@ export const deepSeekModels = { contextWindow: 1_000_000, supportsImages: false, supportsPromptCache: true, - supportsReasoningEffort: ["disable", "high", "max"], // Updated 2026-08-01 + supportsReasoningEffort: ["disable", "low", "high", "max"], // Updated 2026-08-13 preserveReasoning: true, reasoningEffort: "high", inputPrice: 0, // the inputs are priced as cache read/write, so `inputPrice` should be 0 diff --git a/src/api/providers/__tests__/deepseek.spec.ts b/src/api/providers/__tests__/deepseek.spec.ts index 0c9dc1d5c8..dd2c3d4019 100644 --- a/src/api/providers/__tests__/deepseek.spec.ts +++ b/src/api/providers/__tests__/deepseek.spec.ts @@ -617,6 +617,7 @@ describe("DeepSeekHandler", () => { describe("normalizeDeepSeekReasoningEffort", () => { // https://api-docs.deepseek.com/guides/thinking_mode/ + // updated on 2026-08-13 it("should map acceptable reasoning efforts the same way as stated by the official documentation", async () => { const mappings: { modelId: DeepSeekModelId @@ -633,6 +634,11 @@ describe("DeepSeekHandler", () => { rawReasoningEffort: "low", mappedReasoningEffort: "low", }, + { + modelId: "deepseek-v4-flash", + rawReasoningEffort: "medium", + mappedReasoningEffort: "high", + }, { modelId: "deepseek-v4-flash", rawReasoningEffort: "high", @@ -656,6 +662,11 @@ describe("DeepSeekHandler", () => { { modelId: "deepseek-v4-pro", rawReasoningEffort: "low", + mappedReasoningEffort: "low", + }, + { + modelId: "deepseek-v4-pro", + rawReasoningEffort: "medium", mappedReasoningEffort: "high", }, { @@ -666,7 +677,7 @@ describe("DeepSeekHandler", () => { { modelId: "deepseek-v4-pro", rawReasoningEffort: "xhigh", - mappedReasoningEffort: "max", + mappedReasoningEffort: "high", }, { modelId: "deepseek-v4-pro", diff --git a/src/api/providers/deepseek.ts b/src/api/providers/deepseek.ts index 2e85c016b0..12d4afaae2 100644 --- a/src/api/providers/deepseek.ts +++ b/src/api/providers/deepseek.ts @@ -46,38 +46,22 @@ export const normalizeDeepSeekReasoningEffort = ( modelId: DeepSeekModelId, reasoningEffort?: string, ): "low" | "high" | "max" | undefined => { + // still check the modelId so non-supported models won't produce reasoning efforts switch (modelId) { case "deepseek-v4-flash": + case "deepseek-v4-pro": switch (reasoningEffort) { case "low": return "low" + case "medium": case "high": - return "high" - case "xhigh": return "high" case "max": return "max" } - break - - case "deepseek-v4-pro": - switch (reasoningEffort) { - case "low": - return "high" - - case "high": - return "high" - - case "xhigh": - return "max" - - case "max": - return "max" - } - break } return undefined From 193c2f2af9308cf93693274c441adf50ec1b62ad Mon Sep 17 00:00:00 2001 From: T Date: Sat, 15 Aug 2026 00:09:11 +0000 Subject: [PATCH 11/66] feat(api): add NanoGPT provider support (#1239) * feat: add NanoGPT provider backend * feat: add NanoGPT provider settings * fix: harden NanoGPT provider boundaries * no-mistakes(review): Handle NanoGPT null metadata and reasoning capabilities * no-mistakes(review): Fix NanoGPT cache-capable request routing * fix(api): harden NanoGPT metadata handling * chore: retrigger checks --------- Co-authored-by: @taltas <6816042+taltas@users.noreply.github.com> --- .../utils/__tests__/context-window.test.ts | 1 + apps/cli/src/lib/utils/context-window.ts | 2 + packages/types/src/__tests__/nanogpt.test.ts | 67 ++++ .../__tests__/provider-identifiers.test.ts | 2 + .../src/__tests__/provider-model-id.test.ts | 1 + packages/types/src/global-settings.ts | 1 + packages/types/src/provider-identifiers.ts | 1 + packages/types/src/provider-settings.ts | 7 + packages/types/src/provider-settings/index.ts | 8 + .../types/src/provider-settings/nanogpt.ts | 24 ++ packages/types/src/providers/index.ts | 4 + packages/types/src/providers/nanogpt.ts | 57 ++++ src/api/__tests__/index.spec.ts | 2 + src/api/index.ts | 3 + src/api/providers/__tests__/nanogpt.spec.ts | 313 ++++++++++++++++++ .../fetchers/__tests__/modelCache.spec.ts | 44 +++ .../fetchers/__tests__/nanogpt.spec.ts | 192 +++++++++++ src/api/providers/fetchers/modelCache.ts | 9 + src/api/providers/fetchers/nanogpt.ts | 103 ++++++ src/api/providers/index.ts | 1 + src/api/providers/nanogpt.ts | 175 ++++++++++ src/api/providers/router-provider.ts | 18 +- .../config/__tests__/ContextProxy.spec.ts | 19 ++ .../webview/__tests__/ClineProvider.spec.ts | 28 ++ .../__tests__/webviewMessageHandler.spec.ts | 54 +++ src/core/webview/webviewMessageHandler.ts | 14 + src/shared/api.ts | 1 + .../src/components/settings/ApiOptions.tsx | 12 + .../src/components/settings/ModelPicker.tsx | 1 + .../ApiOptions.interactions.spec.tsx | 2 + .../settings/__tests__/ApiOptions.spec.tsx | 1 + .../SettingsView.unsaved-changes.spec.tsx | 106 ++++++ .../src/components/settings/constants.ts | 1 + .../components/settings/providers/NanoGPT.tsx | 141 ++++++++ .../providers/__tests__/NanoGPT.spec.tsx | 181 ++++++++++ .../components/settings/providers/index.ts | 1 + .../__tests__/providerModelConfig.spec.ts | 21 +- .../settings/utils/providerModelConfig.ts | 2 + .../hooks/__tests__/useSelectedModel.spec.ts | 44 +++ .../components/ui/hooks/useSelectedModel.ts | 10 + webview-ui/src/i18n/locales/ca/settings.json | 19 ++ webview-ui/src/i18n/locales/de/settings.json | 19 ++ webview-ui/src/i18n/locales/en/settings.json | 19 ++ webview-ui/src/i18n/locales/es/settings.json | 19 ++ webview-ui/src/i18n/locales/fr/settings.json | 19 ++ webview-ui/src/i18n/locales/hi/settings.json | 19 ++ webview-ui/src/i18n/locales/id/settings.json | 19 ++ webview-ui/src/i18n/locales/it/settings.json | 19 ++ webview-ui/src/i18n/locales/ja/settings.json | 19 ++ webview-ui/src/i18n/locales/ko/settings.json | 19 ++ webview-ui/src/i18n/locales/nl/settings.json | 19 ++ webview-ui/src/i18n/locales/pl/settings.json | 19 ++ .../src/i18n/locales/pt-BR/settings.json | 19 ++ webview-ui/src/i18n/locales/ru/settings.json | 19 ++ webview-ui/src/i18n/locales/tr/settings.json | 19 ++ webview-ui/src/i18n/locales/vi/settings.json | 19 ++ .../src/i18n/locales/zh-CN/settings.json | 19 ++ .../src/i18n/locales/zh-TW/settings.json | 19 ++ .../src/utils/__tests__/validate.spec.ts | 31 ++ webview-ui/src/utils/validate.ts | 5 + 60 files changed, 2039 insertions(+), 13 deletions(-) create mode 100644 packages/types/src/__tests__/nanogpt.test.ts create mode 100644 packages/types/src/provider-settings/nanogpt.ts create mode 100644 packages/types/src/providers/nanogpt.ts create mode 100644 src/api/providers/__tests__/nanogpt.spec.ts create mode 100644 src/api/providers/fetchers/__tests__/nanogpt.spec.ts create mode 100644 src/api/providers/fetchers/nanogpt.ts create mode 100644 src/api/providers/nanogpt.ts create mode 100644 webview-ui/src/components/settings/providers/NanoGPT.tsx create mode 100644 webview-ui/src/components/settings/providers/__tests__/NanoGPT.spec.tsx diff --git a/apps/cli/src/lib/utils/__tests__/context-window.test.ts b/apps/cli/src/lib/utils/__tests__/context-window.test.ts index 8d33ef5e2b..4347292166 100644 --- a/apps/cli/src/lib/utils/__tests__/context-window.test.ts +++ b/apps/cli/src/lib/utils/__tests__/context-window.test.ts @@ -14,6 +14,7 @@ describe("getContextWindow", () => { [providerIdentifiers.vercelAiGateway, "vercelAiGatewayModelId"], [providerIdentifiers.opencodeGo, "opencodeGoModelId"], [providerIdentifiers.kenari, "kenariModelId"], + [providerIdentifiers.nanogpt, "nanoGptModelId"], [providerIdentifiers.zooGateway, "zooGatewayModelId"], ] as const)("uses the provider-specific model field for %s", (provider, modelField) => { const config = { apiProvider: provider, [modelField]: "selected-model" } as ProviderSettings diff --git a/apps/cli/src/lib/utils/context-window.ts b/apps/cli/src/lib/utils/context-window.ts index 1d6402c525..b78ab0e5b5 100644 --- a/apps/cli/src/lib/utils/context-window.ts +++ b/apps/cli/src/lib/utils/context-window.ts @@ -56,6 +56,8 @@ function getModelIdForProvider(config: ProviderSettings): string | undefined { return config.opencodeGoModelId case providerIdentifiers.kenari: return config.kenariModelId + case providerIdentifiers.nanogpt: + return config.nanoGptModelId case providerIdentifiers.zooGateway: return config.zooGatewayModelId case providerIdentifiers.anthropic: diff --git a/packages/types/src/__tests__/nanogpt.test.ts b/packages/types/src/__tests__/nanogpt.test.ts new file mode 100644 index 0000000000..50eacdd276 --- /dev/null +++ b/packages/types/src/__tests__/nanogpt.test.ts @@ -0,0 +1,67 @@ +import { + applyNanoGptRoutingPreference, + dynamicProviders, + getModelId, + getProviderDefaultModelId, + isSecretStateKey, + nanoGptDefaultModelId, + nanoGptDefaultRoutingPreference, + providerIdentifiers, + providerSettingsSchema, +} from "../index.js" + +describe("NanoGPT shared contract", () => { + it("registers the stable dynamic-provider identity and default model", () => { + expect(providerIdentifiers.nanogpt).toBe("nanogpt") + expect(dynamicProviders).toContain("nanogpt") + expect(getProviderDefaultModelId("nanogpt")).toBe(nanoGptDefaultModelId) + }) + + it("classifies the API key as secret and resolves missing routing to auto", () => { + expect(isSecretStateKey("nanoGptApiKey")).toBe(true) + const settings = providerSettingsSchema.parse({ apiProvider: "nanogpt", nanoGptModelId: "model" }) + expect(settings.nanoGptRoutingPreference ?? nanoGptDefaultRoutingPreference).toBe("auto") + expect(getModelId(settings)).toBe("model") + }) +}) + +describe("applyNanoGptRoutingPreference", () => { + it.each([ + ["auto", "model"], + ["fast", "model:fast"], + ["cheap", "model:cheap"], + ["latency", "model:latency"], + ["throughput", "model:throughput"], + ["tools", "model:tools"], + ["caching", "model"], + ] as const)("maps %s routing", (preference, expected) => { + expect(applyNanoGptRoutingPreference("model", preference)).toBe(expected) + }) + + it.each([ + "speed", + "fast", + "throughput", + "latency", + "price", + "cheap", + "floor", + "tools", + "caching", + "cache", + "cached", + ])("replaces the recognized %s routing alias", (alias) => { + expect(applyNanoGptRoutingPreference(`model:thinking:${alias}`, "cheap")).toBe("model:thinking:cheap") + expect(applyNanoGptRoutingPreference(`model:thinking:${alias}`, "auto")).toBe("model:thinking") + }) + + it("preserves legitimate identity suffixes", () => { + expect(applyNanoGptRoutingPreference("model:thinking", "fast")).toBe("model:thinking:fast") + expect(applyNanoGptRoutingPreference("model:thinking", "auto")).toBe("model:thinking") + }) + + it("normalizes multiple trailing routing suffixes to exactly one active preference", () => { + expect(applyNanoGptRoutingPreference("model:thinking:fast:cheap", "latency")).toBe("model:thinking:latency") + expect(applyNanoGptRoutingPreference("model:thinking:FAST:CACHED", "auto")).toBe("model:thinking") + }) +}) diff --git a/packages/types/src/__tests__/provider-identifiers.test.ts b/packages/types/src/__tests__/provider-identifiers.test.ts index 870ce77d78..29e55b31cf 100644 --- a/packages/types/src/__tests__/provider-identifiers.test.ts +++ b/packages/types/src/__tests__/provider-identifiers.test.ts @@ -32,6 +32,7 @@ const expectedProviderIdentifiers = [ "deepseek", "opencode-go", "kenari", + "nanogpt", "ollama", "lmstudio", "vscode-lm", @@ -106,6 +107,7 @@ describe("provider identifiers", () => { providerIdentifiers.moonshot, providerIdentifiers.opencodeGo, providerIdentifiers.kenari, + providerIdentifiers.nanogpt, providerIdentifiers.kimiCode, ]) expect(localProviders).toEqual([providerIdentifiers.ollama, providerIdentifiers.lmstudio]) diff --git a/packages/types/src/__tests__/provider-model-id.test.ts b/packages/types/src/__tests__/provider-model-id.test.ts index bec5425b54..7c404c1cd4 100644 --- a/packages/types/src/__tests__/provider-model-id.test.ts +++ b/packages/types/src/__tests__/provider-model-id.test.ts @@ -13,6 +13,7 @@ const expectedModelIdKeys = [ "vercelAiGatewayModelId", "opencodeGoModelId", "kenariModelId", + "nanoGptModelId", "zooGatewayModelId", ] as const diff --git a/packages/types/src/global-settings.ts b/packages/types/src/global-settings.ts index dc3ea072fd..bd440512ce 100644 --- a/packages/types/src/global-settings.ts +++ b/packages/types/src/global-settings.ts @@ -324,6 +324,7 @@ export const SECRET_STATE_KEYS = [ "vercelAiGatewayApiKey", "opencodeGoApiKey", "kenariApiKey", + "nanoGptApiKey", "basetenApiKey", ] as const diff --git a/packages/types/src/provider-identifiers.ts b/packages/types/src/provider-identifiers.ts index f231bc1ab1..fdf507bb6b 100644 --- a/packages/types/src/provider-identifiers.ts +++ b/packages/types/src/provider-identifiers.ts @@ -14,6 +14,7 @@ export const providerIdentifiers = { deepseek: "deepseek", opencodeGo: "opencode-go", kenari: "kenari", + nanogpt: "nanogpt", ollama: "ollama", lmstudio: "lmstudio", vscodeLm: "vscode-lm", diff --git a/packages/types/src/provider-settings.ts b/packages/types/src/provider-settings.ts index 240e34e152..4a432970c2 100644 --- a/packages/types/src/provider-settings.ts +++ b/packages/types/src/provider-settings.ts @@ -6,6 +6,10 @@ export { OPEN_AI_CODEX_SERVICE_TIER_KEY, kimiCodeAuthMethodSchema, type KimiCodeAuthMethod, + nanoGptDefaultRoutingPreference, + nanoGptRoutingPreferences, + nanoGptRoutingPreferenceSchema, + type NanoGptRoutingPreference, zaiApiLineSchema, type ZaiApiLine, } from "./provider-settings/index.js" @@ -67,6 +71,7 @@ export const dynamicProviders = [ providerIdentifiers.moonshot, providerIdentifiers.opencodeGo, providerIdentifiers.kenari, + providerIdentifiers.nanogpt, providerIdentifiers.kimiCode, ] as const @@ -280,6 +285,7 @@ export const modelIdKeys = [ "vercelAiGatewayModelId", "opencodeGoModelId", "kenariModelId", + "nanoGptModelId", "zooGatewayModelId", ] as const satisfies readonly ModelIdKey[] @@ -508,6 +514,7 @@ export const MODELS_BY_PROVIDER: Record< }, [providerIdentifiers.opencodeGo]: { id: providerIdentifiers.opencodeGo, label: "Opencode Go", models: [] }, [providerIdentifiers.kenari]: { id: providerIdentifiers.kenari, label: "Kenari", models: [] }, + [providerIdentifiers.nanogpt]: { id: providerIdentifiers.nanogpt, label: "NanoGPT", models: [] }, [providerIdentifiers.zooGateway]: { id: providerIdentifiers.zooGateway, label: "Zoo Gateway", models: [] }, // Local providers; models discovered from localhost endpoints. diff --git a/packages/types/src/provider-settings/index.ts b/packages/types/src/provider-settings/index.ts index e97fbf5995..225b54fc29 100644 --- a/packages/types/src/provider-settings/index.ts +++ b/packages/types/src/provider-settings/index.ts @@ -30,6 +30,7 @@ import { qwenCodeProviderDefinition } from "./qwen-code.js" import { vercelAiGatewayProviderDefinition } from "./vercel-ai-gateway.js" import { opencodeGoProviderDefinition } from "./opencode-go.js" import { kenariProviderDefinition } from "./kenari.js" +import { nanoGptProviderDefinition } from "./nanogpt.js" import { zooGatewayProviderDefinition } from "./zoo-gateway.js" import { basetenProviderDefinition } from "./baseten.js" @@ -38,6 +39,12 @@ import type { ProviderDefinition } from "./common.js" export { OPEN_AI_CODEX_SERVICE_TIER_KEY } from "./openai-codex.js" export { kimiCodeAuthMethodSchema, type KimiCodeAuthMethod } from "./kimi-code.js" export { zaiApiLineSchema, type ZaiApiLine } from "./zai.js" +export { + nanoGptDefaultRoutingPreference, + nanoGptRoutingPreferences, + nanoGptRoutingPreferenceSchema, + type NanoGptRoutingPreference, +} from "./nanogpt.js" export type { ProviderDefinition } from "./common.js" export const providerDefinitionList = [ @@ -73,6 +80,7 @@ export const providerDefinitionList = [ vercelAiGatewayProviderDefinition, opencodeGoProviderDefinition, kenariProviderDefinition, + nanoGptProviderDefinition, zooGatewayProviderDefinition, basetenProviderDefinition, ] as const satisfies readonly ProviderDefinition[] diff --git a/packages/types/src/provider-settings/nanogpt.ts b/packages/types/src/provider-settings/nanogpt.ts new file mode 100644 index 0000000000..e1db6a237f --- /dev/null +++ b/packages/types/src/provider-settings/nanogpt.ts @@ -0,0 +1,24 @@ +import { z } from "zod" + +import { providerIdentifiers } from "../provider-identifiers.js" +import { baseProviderSettingsShape, createModelIdAccessor, createProviderDefinition } from "./common.js" + +const NANOGPT_MODEL_ID_FIELD = "nanoGptModelId" + +export const nanoGptRoutingPreferences = ["auto", "fast", "cheap", "latency", "throughput", "tools", "caching"] as const + +export const nanoGptRoutingPreferenceSchema = z.enum(nanoGptRoutingPreferences) +export type NanoGptRoutingPreference = z.infer +export const nanoGptDefaultRoutingPreference: NanoGptRoutingPreference = "auto" + +export const nanoGptProviderDefinition = createProviderDefinition({ + apiProvider: providerIdentifiers.nanogpt, + modelIdKey: NANOGPT_MODEL_ID_FIELD, + getModelId: createModelIdAccessor(NANOGPT_MODEL_ID_FIELD), + schema: { + ...baseProviderSettingsShape, + nanoGptApiKey: z.string().optional(), + [NANOGPT_MODEL_ID_FIELD]: z.string().optional(), + nanoGptRoutingPreference: nanoGptRoutingPreferenceSchema.optional(), + }, +}) diff --git a/packages/types/src/providers/index.ts b/packages/types/src/providers/index.ts index 5f7d1afda4..b26476eaed 100644 --- a/packages/types/src/providers/index.ts +++ b/packages/types/src/providers/index.ts @@ -25,6 +25,7 @@ export * from "./xai.js" export * from "./vercel-ai-gateway.js" export * from "./opencode-go.js" export * from "./kenari.js" +export * from "./nanogpt.js" export * from "./kimi-code.js" export * from "./zai.js" export * from "./minimax.js" @@ -54,6 +55,7 @@ import { xaiDefaultModelId } from "./xai.js" import { vercelAiGatewayDefaultModelId } from "./vercel-ai-gateway.js" import { opencodeGoDefaultModelId } from "./opencode-go.js" import { kenariDefaultModelId } from "./kenari.js" +import { nanoGptDefaultModelId } from "./nanogpt.js" import { kimiCodeDefaultModelId } from "./kimi-code.js" import { internationalZAiDefaultModelId, mainlandZAiDefaultModelId } from "./zai.js" import { minimaxDefaultModelId } from "./minimax.js" @@ -133,6 +135,8 @@ export function getProviderDefaultModelId( return opencodeGoDefaultModelId case providerIdentifiers.kenari: return kenariDefaultModelId + case providerIdentifiers.nanogpt: + return nanoGptDefaultModelId case providerIdentifiers.kimiCode: return kimiCodeDefaultModelId case providerIdentifiers.zooGateway: diff --git a/packages/types/src/providers/nanogpt.ts b/packages/types/src/providers/nanogpt.ts new file mode 100644 index 0000000000..1b0459ab24 --- /dev/null +++ b/packages/types/src/providers/nanogpt.ts @@ -0,0 +1,57 @@ +import type { ModelInfo } from "../model.js" +import type { NanoGptRoutingPreference } from "../provider-settings/nanogpt.js" + +export const NANOGPT_BASE_URL = "https://nano-gpt.com/api/v1" + +export const nanoGptDefaultModelId = "openai/gpt-5.6-sol" + +export const nanoGptDefaultModelInfo: ModelInfo = { + maxTokens: 128_000, + contextWindow: 1_050_000, + supportsImages: true, + supportsPromptCache: false, + inputPrice: 5, + outputPrice: 30, + description: "NanoGPT model. Available models and metadata are resolved dynamically from the detailed catalog.", +} + +const ROUTING_SUFFIXES = new Set([ + "speed", + "fast", + "throughput", + "latency", + "price", + "cheap", + "floor", + "tools", + "caching", + "cache", + "cached", +]) + +const ROUTING_SUFFIX_BY_PREFERENCE: Record, string> = { + fast: "fast", + cheap: "cheap", + latency: "latency", + throughput: "throughput", + tools: "tools", +} + +/** Applies one request-only NanoGPT routing suffix while preserving identity suffixes such as `:thinking`. */ +export function applyNanoGptRoutingPreference(modelId: string, preference: NanoGptRoutingPreference = "auto"): string { + let canonicalId = modelId + let separatorIndex = canonicalId.lastIndexOf(":") + let finalSuffix = separatorIndex >= 0 ? canonicalId.slice(separatorIndex + 1).toLowerCase() : "" + + // Normalize every trailing routing alias. This protects request identity when a + // previously-routed ID is routed again and prevents multiple active suffixes. + while (separatorIndex >= 0 && ROUTING_SUFFIXES.has(finalSuffix)) { + canonicalId = canonicalId.slice(0, separatorIndex) + separatorIndex = canonicalId.lastIndexOf(":") + finalSuffix = separatorIndex >= 0 ? canonicalId.slice(separatorIndex + 1).toLowerCase() : "" + } + + return preference === "auto" || preference === "caching" + ? canonicalId + : `${canonicalId}:${ROUTING_SUFFIX_BY_PREFERENCE[preference]}` +} diff --git a/src/api/__tests__/index.spec.ts b/src/api/__tests__/index.spec.ts index 3617c3cd6d..2fe940f53a 100644 --- a/src/api/__tests__/index.spec.ts +++ b/src/api/__tests__/index.spec.ts @@ -47,6 +47,7 @@ import { MimoHandler, MistralHandler, MoonshotHandler, + NanoGptHandler, OpenAiCodexHandler, OpenAiHandler, OpenAiNativeHandler, @@ -99,6 +100,7 @@ const expectedHandlers = { [providerIdentifiers.vercelAiGateway]: VercelAiGatewayHandler, [providerIdentifiers.opencodeGo]: OpencodeGoHandler, [providerIdentifiers.kenari]: KenariHandler, + [providerIdentifiers.nanogpt]: NanoGptHandler, [providerIdentifiers.zooGateway]: ZooGatewayHandler, [providerIdentifiers.minimax]: MiniMaxHandler, [providerIdentifiers.baseten]: BasetenHandler, diff --git a/src/api/index.ts b/src/api/index.ts index f48ab50c0e..8e7f20d66f 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -42,6 +42,7 @@ import { VercelAiGatewayHandler, OpencodeGoHandler, KenariHandler, + NanoGptHandler, ZooGatewayHandler, MiniMaxHandler, MimoHandler, @@ -224,6 +225,8 @@ export function buildApiHandler(configuration: ProviderSettings): ApiHandler { return new OpencodeGoHandler(options) case providerIdentifiers.kenari: return new KenariHandler(options) + case providerIdentifiers.nanogpt: + return new NanoGptHandler(options) case providerIdentifiers.zooGateway: return new ZooGatewayHandler(options) case providerIdentifiers.minimax: diff --git a/src/api/providers/__tests__/nanogpt.spec.ts b/src/api/providers/__tests__/nanogpt.spec.ts new file mode 100644 index 0000000000..878663f1e2 --- /dev/null +++ b/src/api/providers/__tests__/nanogpt.spec.ts @@ -0,0 +1,313 @@ +vi.mock("vscode", () => ({ + workspace: { getConfiguration: () => ({ get: (_key: string, defaultValue?: unknown) => defaultValue }) }, +})) + +import { Anthropic } from "@anthropic-ai/sdk" +import OpenAI from "openai" + +import { nanoGptDefaultModelId } from "@roo-code/types" + +import { buildApiHandler } from "../../index" +import { asyncStreamFrom, collectStream } from "../../../test-utils/stream" +import { NanoGptHandler } from "../nanogpt" +import { getModels } from "../fetchers/modelCache" + +vi.mock("openai") +vi.mock("../fetchers/modelCache", () => ({ + getModels: vi.fn().mockResolvedValue({ + "model:thinking": { + maxTokens: 128000, + contextWindow: 1050000, + supportsImages: true, + supportsPromptCache: false, + supportsReasoningEffort: ["low", "medium", "high"], + }, + }), + getModelsFromCache: vi.fn(), +})) + +const mockCreate = vi.fn() +vi.mocked(OpenAI).mockImplementation(function () { + return { chat: { completions: { create: mockCreate } } } as unknown as OpenAI +}) + +const messages: Anthropic.Messages.MessageParam[] = [{ role: "user", content: "Hello" }] + +describe("NanoGptHandler", () => { + beforeEach(() => { + vi.clearAllMocks() + vi.mocked(getModels).mockResolvedValue({ + "model:thinking": { + maxTokens: 128000, + contextWindow: 1050000, + supportsImages: true, + supportsPromptCache: false, + supportsReasoningEffort: ["low", "medium", "high"], + }, + }) + mockCreate.mockResolvedValue(asyncStreamFrom([])) + }) + + it("is constructed by the backend provider registry", () => { + expect(buildApiHandler({ apiProvider: "nanogpt" })).toBeInstanceOf(NanoGptHandler) + }) + + it("keeps the canonical model ID while applying request-only routing", async () => { + const handler = new NanoGptHandler({ nanoGptModelId: "model:thinking", nanoGptRoutingPreference: "fast" }) + await collectStream(handler.createMessage("system", messages)) + expect(handler.getModel().id).toBe("model:thinking") + expect(mockCreate).toHaveBeenCalledWith( + expect.objectContaining({ model: "model:thinking:fast" }), + expect.anything(), + ) + }) + + it.each([ + ["auto", "model:thinking"], + ["fast", "model:thinking:fast"], + ["cheap", "model:thinking:cheap"], + ["latency", "model:thinking:latency"], + ["throughput", "model:thinking:throughput"], + ["tools", "model:thinking:tools"], + ] as const)("sends %s routing", async (preference, expected) => { + const handler = new NanoGptHandler({ nanoGptModelId: "model:thinking", nanoGptRoutingPreference: preference }) + await collectStream(handler.createMessage("system", messages)) + expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({ model: expected }), expect.anything()) + }) + + it("requests cache-capable routing without changing the streaming model ID", async () => { + const handler = new NanoGptHandler({ + nanoGptModelId: "model:thinking", + nanoGptRoutingPreference: "caching", + }) + await collectStream(handler.createMessage("system", messages)) + expect(mockCreate).toHaveBeenCalledWith( + expect.objectContaining({ model: "model:thinking", caching: true, stream: true }), + expect.anything(), + ) + }) + + it("streams interleaved text, both reasoning variants, and parallel tool calls", async () => { + mockCreate.mockResolvedValue( + asyncStreamFrom([ + { choices: [{ delta: { content: "answer", reasoning: "modern" } }] }, + { choices: [{ delta: { reasoning_content: "legacy" } }] }, + { + choices: [ + { + delta: { + tool_calls: [ + { index: 0, id: "call-1", function: { name: "read_file", arguments: '{"path":' } }, + { + index: 1, + id: "call-2", + function: { name: "search_files", arguments: '{"query":' }, + }, + ], + }, + }, + ], + }, + ]), + ) + const chunks = await collectStream( + new NanoGptHandler({ nanoGptModelId: "model:thinking" }).createMessage("sys", messages), + ) + expect(chunks).toEqual([ + { type: "text", text: "answer" }, + { type: "reasoning", text: "modern" }, + { type: "reasoning", text: "legacy" }, + { type: "tool_call_partial", index: 0, id: "call-1", name: "read_file", arguments: '{"path":' }, + { type: "tool_call_partial", index: 1, id: "call-2", name: "search_files", arguments: '{"query":' }, + ]) + }) + + it("forwards native tools, choices, usage streaming, max_tokens, reasoning effort, and cancellation", async () => { + const signal = new AbortController().signal + const tools: OpenAI.Chat.ChatCompletionTool[] = [ + { type: "function", function: { name: "read_file", description: "Read", parameters: { type: "object" } } }, + ] + const handler = new NanoGptHandler({ + nanoGptModelId: "model:thinking", + modelTemperature: 0.7, + reasoningEffort: "high", + }) + await collectStream( + handler.createMessage("sys", messages, { + taskId: "task", + tools, + tool_choice: "required", + parallelToolCalls: false, + abortSignal: signal, + }), + ) + expect(mockCreate).toHaveBeenCalledWith( + expect.objectContaining({ + stream: true, + stream_options: { include_usage: true }, + max_tokens: 128000, + temperature: 0.7, + reasoning_effort: "high", + tools: [ + expect.objectContaining({ + type: "function", + function: expect.objectContaining({ name: "read_file", description: "Read" }), + }), + ], + tool_choice: "required", + parallel_tool_calls: false, + }), + { signal }, + ) + expect(mockCreate.mock.calls[0][0]).not.toHaveProperty("max_completion_tokens") + }) + + it("omits temperature when it was not explicitly configured", async () => { + await collectStream(new NanoGptHandler({ nanoGptModelId: "model:thinking" }).createMessage("sys", messages)) + expect(mockCreate.mock.calls[0][0]).not.toHaveProperty("temperature") + }) + + it("keeps unauthenticated catalog fetches public and preserves streaming error metadata while redacting", async () => { + const errorDetails = [{ "@type": "type.googleapis.com/google.rpc.RetryInfo", retryDelay: "10s" }] + mockCreate.mockRejectedValue( + Object.assign(new Error("upstream rejected secret-key"), { + status: 429, + code: "rate_limit_exceeded", + errorDetails, + }), + ) + const handler = new NanoGptHandler({ nanoGptApiKey: "secret-key", nanoGptModelId: "model:thinking" }) + await expect(collectStream(handler.createMessage("sys", messages))).rejects.toMatchObject({ + message: "NanoGPT streaming error: upstream rejected [REDACTED]", + status: 429, + code: "rate_limit_exceeded", + errorDetails, + }) + + vi.mocked(getModels).mockResolvedValue({}) + mockCreate.mockResolvedValue(asyncStreamFrom([])) + await collectStream(new NanoGptHandler({ nanoGptModelId: "model:thinking" }).createMessage("sys", messages)) + expect(getModels).toHaveBeenLastCalledWith(expect.objectContaining({ provider: "nanogpt", apiKey: undefined })) + }) + + it("maps usage with root-field precedence and no reasoning double count", async () => { + mockCreate.mockResolvedValue( + asyncStreamFrom([ + { + choices: [], + usage: { + prompt_tokens: 20, + completion_tokens: 10, + cache_read_input_tokens: 7, + cache_creation_input_tokens: 3, + prompt_tokens_details: { cached_tokens: 5 }, + completion_tokens_details: { reasoning_tokens: 4 }, + reasoning_tokens: 2, + }, + }, + ]), + ) + expect( + await collectStream( + new NanoGptHandler({ nanoGptModelId: "model:thinking" }).createMessage("sys", messages), + ), + ).toEqual([ + { + type: "usage", + inputTokens: 20, + outputTokens: 10, + cacheReadTokens: 7, + cacheWriteTokens: 3, + reasoningTokens: 4, + }, + ]) + }) + + it("falls back to nested cache reads and root reasoning tokens", async () => { + mockCreate.mockResolvedValue( + asyncStreamFrom([ + { + choices: [], + usage: { + prompt_tokens: 2, + completion_tokens: 1, + prompt_tokens_details: { cached_tokens: 1 }, + reasoning_tokens: 1, + }, + }, + ]), + ) + expect( + await collectStream( + new NanoGptHandler({ nanoGptModelId: "model:thinking" }).createMessage("sys", messages), + ), + ).toEqual([ + { + type: "usage", + inputTokens: 2, + outputTokens: 1, + cacheReadTokens: 1, + cacheWriteTokens: undefined, + reasoningTokens: 1, + }, + ]) + }) + + describe("completePrompt", () => { + it("requests cache-capable routing without changing the completion model ID", async () => { + mockCreate.mockResolvedValue({ choices: [{ message: { content: "response" } }] }) + const handler = new NanoGptHandler({ + nanoGptModelId: "model:thinking", + nanoGptRoutingPreference: "caching", + }) + await handler.completePrompt("prompt") + expect(mockCreate.mock.calls[0][0]).toMatchObject({ + model: "model:thinking", + caching: true, + stream: false, + }) + }) + + it("returns normal and empty content", async () => { + mockCreate.mockResolvedValueOnce({ choices: [{ message: { content: "response" } }] }) + const handler = new NanoGptHandler({ nanoGptModelId: "model:thinking" }) + expect(await handler.completePrompt("prompt")).toBe("response") + expect(mockCreate.mock.calls[0][0]).toMatchObject({ + model: "model:thinking", + stream: false, + max_tokens: 128000, + }) + + mockCreate.mockResolvedValueOnce({ choices: [{ message: { content: null } }] }) + expect(await handler.completePrompt("prompt")).toBe("") + }) + + it("preserves completion error metadata without leaking the API key", async () => { + const errorDetails = [{ "@type": "type.googleapis.com/google.rpc.RetryInfo", retryDelay: "20s" }] + mockCreate.mockRejectedValue( + Object.assign(new Error("upstream rejected secret-key"), { + status: 429, + code: "rate_limit_exceeded", + errorDetails, + }), + ) + const handler = new NanoGptHandler({ nanoGptApiKey: "secret-key", nanoGptModelId: "model:thinking" }) + await expect(handler.completePrompt("prompt")).rejects.toMatchObject({ + message: "NanoGPT completion error: upstream rejected [REDACTED]", + status: 429, + code: "rate_limit_exceeded", + errorDetails, + }) + }) + }) + + it("uses the documented fallback model", async () => { + vi.mocked(getModels).mockResolvedValue({}) + const handler = new NanoGptHandler({}) + await collectStream(handler.createMessage("sys", messages)) + expect(mockCreate).toHaveBeenCalledWith( + expect.objectContaining({ model: nanoGptDefaultModelId }), + expect.anything(), + ) + }) +}) diff --git a/src/api/providers/fetchers/__tests__/modelCache.spec.ts b/src/api/providers/fetchers/__tests__/modelCache.spec.ts index 512cbdb9c6..108aa1827b 100644 --- a/src/api/providers/fetchers/__tests__/modelCache.spec.ts +++ b/src/api/providers/fetchers/__tests__/modelCache.spec.ts @@ -45,6 +45,7 @@ vi.mock("../litellm") vi.mock("../openrouter") vi.mock("../requesty") vi.mock("../kenari") +vi.mock("../nanogpt") vi.mock("../moonshot") vi.mock("../zoo-gateway") @@ -70,6 +71,7 @@ import { getLiteLLMModels } from "../litellm" import { getOpenRouterModels } from "../openrouter" import { getRequestyModels } from "../requesty" import { getKenariModels } from "../kenari" +import { getNanoGptModels } from "../nanogpt" import { getMoonshotModels } from "../moonshot" import { getZooGatewayModels } from "../zoo-gateway" @@ -77,6 +79,7 @@ const mockGetLiteLLMModels = getLiteLLMModels as Mock const mockGetOpenRouterModels = getOpenRouterModels as Mock const mockGetRequestyModels = getRequestyModels as Mock const mockGetKenariModels = getKenariModels as Mock +const mockGetNanoGptModels = getNanoGptModels as Mock const mockGetMoonshotModels = getMoonshotModels as Mock const mockGetZooGatewayModels = getZooGatewayModels as Mock @@ -197,6 +200,22 @@ describe("getModels with new GetModelsOptions", () => { expect(result).toEqual(mockModels) }) + it("dispatches NanoGPT with an optional API key", async () => { + const mockModels = { + "openai/gpt-5.6-sol": { + maxTokens: 128000, + contextWindow: 1050000, + supportsPromptCache: false, + }, + } + mockGetNanoGptModels.mockResolvedValue(mockModels) + + const result = await getModels({ provider: providerIdentifiers.nanogpt, apiKey: "nanogpt-key" }) + + expect(mockGetNanoGptModels).toHaveBeenCalledWith("nanogpt-key") + expect(result).toEqual(mockModels) + }) + it("handles errors and re-throws them", async () => { const expectedError = new Error("LiteLLM connection failed") mockGetLiteLLMModels.mockRejectedValue(expectedError) @@ -1079,6 +1098,31 @@ describe("key-scoped cache key derivation", () => { }) }) +describe("NanoGPT key-scoped cache isolation", () => { + const nanoGptModels = { + "openai/gpt-5.6-sol": { maxTokens: 128000, contextWindow: 1050000, supportsPromptCache: false }, + } + + beforeEach(() => { + vi.clearAllMocks() + mockGetNanoGptModels.mockResolvedValue(nanoGptModels) + }) + + it("separates public, key A, and key B cache identities without exposing raw keys", async () => { + const mockCache = vi.mocked(new (vi.mocked(NodeCache))()) + mockCache.get.mockReturnValue(undefined) + + await getModels({ provider: providerIdentifiers.nanogpt }) + await getModels({ provider: providerIdentifiers.nanogpt, apiKey: "nano-key-a" }) + await getModels({ provider: providerIdentifiers.nanogpt, apiKey: "nano-key-b" }) + + const cacheKeys = mockCache.set.mock.calls.map(([key]) => key as string) + expect(new Set(cacheKeys).size).toBe(3) + expect(cacheKeys).toContain("nanogpt") + expect(cacheKeys.every((key) => !key.includes("nano-key-a") && !key.includes("nano-key-b"))).toBe(true) + }) +}) + describe("compound cache key derivation across scoping dimensions", () => { // Exercises every branch of getCacheKey via the public getModels() entry point. // litellm is url-scoped AND key-scoped; openrouter is neither, so it hits the bare diff --git a/src/api/providers/fetchers/__tests__/nanogpt.spec.ts b/src/api/providers/fetchers/__tests__/nanogpt.spec.ts new file mode 100644 index 0000000000..e4673f5a1b --- /dev/null +++ b/src/api/providers/fetchers/__tests__/nanogpt.spec.ts @@ -0,0 +1,192 @@ +import axios from "axios" + +import { NANOGPT_BASE_URL, nanoGptDefaultModelInfo } from "@roo-code/types" + +import { getNanoGptModels, parseNanoGptModel } from "../nanogpt" + +vi.mock("axios") + +describe("NanoGPT model fetcher", () => { + beforeEach(() => vi.clearAllMocks()) + + it("requests the detailed catalog with optional Bearer authorization", async () => { + vi.mocked(axios.get).mockResolvedValue({ data: { data: [] } }) + await getNanoGptModels("key-a") + expect(axios.get).toHaveBeenCalledWith(`${NANOGPT_BASE_URL}/models?detailed=true`, { + headers: { Authorization: "Bearer key-a" }, + timeout: 10_000, + }) + }) + + it("supports unauthenticated catalog requests", async () => { + vi.mocked(axios.get).mockResolvedValue({ data: { data: [] } }) + await getNanoGptModels() + expect(axios.get).toHaveBeenCalledWith(`${NANOGPT_BASE_URL}/models?detailed=true`, { + headers: undefined, + timeout: 10_000, + }) + }) + + it("maps detailed metadata and exact per-million pricing for multiple models", async () => { + vi.mocked(axios.get).mockResolvedValue({ + data: { + unknown_top_level: true, + data: [ + { + id: "vision-model", + name: "Vision Model", + description: "Detailed description", + context_length: 1_050_000, + max_output_tokens: 128_000, + capabilities: { vision: true, tool_calling: true, unknown: "allowed" }, + pricing: { + prompt: 2.5, + completion: 10, + cacheReadInputPer1kTokens: 0.001, + cacheWriteInputPer1kTokens: 0.002, + unknown: 1, + }, + unknown: "allowed", + }, + { id: "text-model", capabilities: { vision: false } }, + ], + }, + }) + + const models = await getNanoGptModels() + expect(Object.keys(models)).toEqual(["vision-model", "text-model"]) + expect(models["vision-model"]).toEqual({ + contextWindow: 1_050_000, + maxTokens: 128_000, + supportsPromptCache: false, + supportsImages: true, + displayName: "Vision Model", + description: "Detailed description", + inputPrice: 2.5, + outputPrice: 10, + cacheReadsPrice: 1, + cacheWritesPrice: 2, + }) + expect(models["text-model"].supportsImages).toBe(false) + }) + + it("skips malformed records and models explicitly lacking tool calling", async () => { + vi.mocked(axios.get).mockResolvedValue({ + data: { + data: [ + { id: "eligible" }, + { missing: "id" }, + { id: "chat-only", capabilities: { tool_calling: false } }, + ], + }, + }) + const warning = vi.spyOn(console, "warn").mockImplementation(() => undefined) + expect(await getNanoGptModels()).toEqual({ + eligible: { + contextWindow: nanoGptDefaultModelInfo.contextWindow, + maxTokens: nanoGptDefaultModelInfo.maxTokens, + supportsPromptCache: false, + }, + }) + expect(warning).toHaveBeenCalledOnce() + warning.mockRestore() + }) + + it("keeps models with null token metadata and preserves reasoning capability", async () => { + vi.mocked(axios.get).mockResolvedValue({ + data: { + data: [ + { + id: "reasoning-model", + context_length: null, + max_output_tokens: null, + capabilities: { reasoning: true }, + }, + { id: "non-reasoning-model", capabilities: { reasoning: false } }, + ], + }, + }) + + const models = await getNanoGptModels() + expect(models["reasoning-model"]).toEqual({ + contextWindow: nanoGptDefaultModelInfo.contextWindow, + maxTokens: nanoGptDefaultModelInfo.maxTokens, + supportsPromptCache: false, + supportsReasoningEffort: ["low", "medium", "high"], + }) + expect(models["non-reasoning-model"].supportsReasoningEffort).toBe(false) + }) + + it("preserves exact reasoning efforts and falls back when the catalog omits them", () => { + expect( + parseNanoGptModel({ + id: "high-only", + capabilities: { reasoning: true }, + reasoning_efforts: ["high"], + }).supportsReasoningEffort, + ).toEqual(["high"]) + + const extendedEfforts = ["none", "minimal", "low", "medium", "high", "xhigh", "max"] as const + expect( + parseNanoGptModel({ + id: "extended-reasoning", + capabilities: { reasoning: true }, + reasoning_efforts: [...extendedEfforts], + }).supportsReasoningEffort, + ).toEqual(extendedEfforts) + + expect( + parseNanoGptModel({ id: "fallback-reasoning", capabilities: { reasoning: true } }).supportsReasoningEffort, + ).toEqual(["low", "medium", "high"]) + }) + + it.each([{ data: null }, [], null])("returns no models for invalid top-level data %#", async (data) => { + vi.mocked(axios.get).mockResolvedValue({ data }) + const warning = vi.spyOn(console, "warn").mockImplementation(() => undefined) + expect(await getNanoGptModels()).toEqual({}) + warning.mockRestore() + }) + + it.each([new Error("network unavailable"), "network unavailable"])( + "returns no models on network failure", + async (error) => { + vi.mocked(axios.get).mockRejectedValue(error) + const consoleError = vi.spyOn(console, "error").mockImplementation(() => undefined) + expect(await getNanoGptModels()).toEqual({}) + consoleError.mockRestore() + }, + ) + + it("rejects negative numeric metadata without leaking the API key in errors", async () => { + vi.mocked(axios.get) + .mockResolvedValueOnce({ + data: { + data: [ + { id: "valid-free", pricing: { prompt: 0, completion: 0 } }, + { id: "invalid-price", pricing: { prompt: -1 } }, + ], + }, + }) + .mockRejectedValueOnce(new Error("upstream rejected secret-key")) + const warning = vi.spyOn(console, "warn").mockImplementation(() => undefined) + const consoleError = vi.spyOn(console, "error").mockImplementation(() => undefined) + + expect(await getNanoGptModels("secret-key")).toEqual({ + "valid-free": expect.objectContaining({ inputPrice: 0, outputPrice: 0 }), + }) + expect(await getNanoGptModels("secret-key")).toEqual({}) + expect(consoleError).toHaveBeenLastCalledWith("Error fetching NanoGPT models: upstream rejected [REDACTED]") + + warning.mockRestore() + consoleError.mockRestore() + }) + + it("does not invent absent optional metadata", () => { + const info = parseNanoGptModel({ id: "minimal" }) + expect(info).toEqual({ + contextWindow: nanoGptDefaultModelInfo.contextWindow, + maxTokens: nanoGptDefaultModelInfo.maxTokens, + supportsPromptCache: false, + }) + }) +}) diff --git a/src/api/providers/fetchers/modelCache.ts b/src/api/providers/fetchers/modelCache.ts index 6ef68864c1..50dbe12f6e 100644 --- a/src/api/providers/fetchers/modelCache.ts +++ b/src/api/providers/fetchers/modelCache.ts @@ -21,6 +21,7 @@ import { getOpenRouterModels } from "./openrouter" import { getVercelAiGatewayModels } from "./vercel-ai-gateway" import { getOpencodeGoModels } from "./opencode-go" import { getKenariModels } from "./kenari" +import { getNanoGptModels } from "./nanogpt" import { getRequestyModels } from "./requesty" import { getUnboundModels } from "./unbound" import { getLiteLLMModels } from "./litellm" @@ -95,6 +96,7 @@ const KEY_SCOPED_PROVIDERS: ReadonlySet = new Set([ providerIdentifiers.moonshot, // Per-key model visibility (api.moonshot.ai vs api.moonshot.cn) providerIdentifiers.zooGateway, // Per-session-token account identity providerIdentifiers.kimiCode, // Per-session-token account identity + providerIdentifiers.nanogpt, // Public catalog can still vary by API-key allowlist ]) // Providers whose model lists are scoped to the signed-in user (e.g. per-account @@ -253,6 +255,9 @@ async function fetchModelsFromProvider(options: GetModelsOptions): Promise { provider: providerIdentifiers.vercelAiGateway, options: { provider: providerIdentifiers.vercelAiGateway }, }, + { + provider: providerIdentifiers.nanogpt, + options: { provider: providerIdentifiers.nanogpt }, + }, ] // Refresh each provider in background (fire and forget) diff --git a/src/api/providers/fetchers/nanogpt.ts b/src/api/providers/fetchers/nanogpt.ts new file mode 100644 index 0000000000..407f2ca85a --- /dev/null +++ b/src/api/providers/fetchers/nanogpt.ts @@ -0,0 +1,103 @@ +import axios from "axios" +import { z } from "zod" + +import { NANOGPT_BASE_URL, nanoGptDefaultModelInfo, type ModelInfo, type ModelRecord } from "@roo-code/types" + +const nanoGptReasoningEfforts: NonNullable = ["low", "medium", "high"] +const nanoGptReasoningEffortSchema = z.enum(["none", "minimal", "low", "medium", "high", "xhigh", "max"]) + +const nanoGptPricingSchema = z.object({ + prompt: z.number().nonnegative().optional(), + completion: z.number().nonnegative().optional(), + cacheReadInputPer1kTokens: z.number().nonnegative().optional(), + cacheWriteInputPer1kTokens: z.number().nonnegative().optional(), +}) + +const nanoGptModelSchema = z.object({ + id: z.string().min(1), + name: z.string().optional(), + description: z.string().optional(), + context_length: z.number().positive().nullish(), + max_output_tokens: z.number().positive().nullish(), + reasoning_efforts: z.array(nanoGptReasoningEffortSchema).optional(), + capabilities: z + .object({ + vision: z.boolean().optional(), + tool_calling: z.boolean().optional(), + reasoning: z.boolean().optional(), + }) + .optional(), + pricing: nanoGptPricingSchema.optional(), +}) + +export type NanoGptModel = z.infer + +function getSafeErrorMessage(error: unknown, apiKey?: string): string { + const message = error instanceof Error ? error.message : String(error) + return apiKey ? message.replaceAll(apiKey, "[REDACTED]") : message +} + +const nanoGptModelsResponseSchema = z.object({ + data: z.array(z.unknown()), +}) + +export const parseNanoGptModel = (model: NanoGptModel): ModelInfo => ({ + contextWindow: model.context_length ?? nanoGptDefaultModelInfo.contextWindow, + maxTokens: model.max_output_tokens ?? nanoGptDefaultModelInfo.maxTokens, + supportsPromptCache: false, + ...(model.capabilities?.vision !== undefined ? { supportsImages: model.capabilities.vision } : {}), + ...(model.capabilities?.reasoning !== undefined + ? { + supportsReasoningEffort: model.capabilities.reasoning + ? (model.reasoning_efforts ?? [...nanoGptReasoningEfforts]) + : false, + } + : {}), + ...(model.name !== undefined ? { displayName: model.name } : {}), + ...(model.description !== undefined ? { description: model.description } : {}), + ...(model.pricing?.prompt !== undefined ? { inputPrice: model.pricing.prompt } : {}), + ...(model.pricing?.completion !== undefined ? { outputPrice: model.pricing.completion } : {}), + ...(model.pricing?.cacheReadInputPer1kTokens !== undefined + ? { cacheReadsPrice: model.pricing.cacheReadInputPer1kTokens * 1_000 } + : {}), + ...(model.pricing?.cacheWriteInputPer1kTokens !== undefined + ? { cacheWritesPrice: model.pricing.cacheWriteInputPer1kTokens * 1_000 } + : {}), +}) + +/** Fetches NanoGPT's public detailed catalog, optionally scoped by a Bearer key. */ +export async function getNanoGptModels(apiKey?: string): Promise { + try { + const response = await axios.get(`${NANOGPT_BASE_URL}/models?detailed=true`, { + headers: apiKey ? { Authorization: `Bearer ${apiKey}` } : undefined, + timeout: 10_000, + }) + const responseResult = nanoGptModelsResponseSchema.safeParse(response.data) + if (!responseResult.success) { + console.warn("NanoGPT models response did not match the expected top-level schema") + return {} + } + + const models: ModelRecord = {} + for (const rawModel of responseResult.data.data) { + const modelResult = nanoGptModelSchema.safeParse(rawModel) + if (!modelResult.success) { + console.warn("Skipping invalid NanoGPT model entry") + continue + } + + // NanoGPT can route to non-agentic models. An explicit false is authoritative; + // an omitted capability remains unknown and therefore eligible. + if (modelResult.data.capabilities?.tool_calling === false) { + continue + } + + models[modelResult.data.id] = parseNanoGptModel(modelResult.data) + } + + return models + } catch (error) { + console.error(`Error fetching NanoGPT models: ${getSafeErrorMessage(error, apiKey)}`) + return {} + } +} diff --git a/src/api/providers/index.ts b/src/api/providers/index.ts index 5bdd7c8deb..37fea799a5 100644 --- a/src/api/providers/index.ts +++ b/src/api/providers/index.ts @@ -29,6 +29,7 @@ export { FriendliHandler } from "./friendli" export { VercelAiGatewayHandler } from "./vercel-ai-gateway" export { OpencodeGoHandler } from "./opencode-go" export { KenariHandler } from "./kenari" +export { NanoGptHandler } from "./nanogpt" export { ZooGatewayHandler } from "./zoo-gateway" export { MiniMaxHandler } from "./minimax" export { MimoHandler } from "./mimo" diff --git a/src/api/providers/nanogpt.ts b/src/api/providers/nanogpt.ts new file mode 100644 index 0000000000..73ce199d23 --- /dev/null +++ b/src/api/providers/nanogpt.ts @@ -0,0 +1,175 @@ +import { Anthropic } from "@anthropic-ai/sdk" +import OpenAI from "openai" + +import { + applyNanoGptRoutingPreference, + NANOGPT_BASE_URL, + nanoGptDefaultModelId, + nanoGptDefaultModelInfo, + type NanoGptRoutingPreference, +} from "@roo-code/types" + +import type { ApiHandlerOptions } from "../../shared/api" + +import type { ApiStream, ApiStreamUsageChunk } from "../transform/stream" +import { convertToOpenAiMessages } from "../transform/openai-format" +import type { ApiHandlerCreateMessageMetadata, CompletePromptOptions, SingleCompletionHandler } from "../index" +import { RouterProvider } from "./router-provider" +import { handleProviderError } from "./utils/error-handler" +import { extractReasoningFromDelta } from "./utils/extract-reasoning" + +type NanoGptUsage = OpenAI.CompletionUsage & { + cache_read_input_tokens?: number + cache_creation_input_tokens?: number + reasoning_tokens?: number +} + +type NanoGptCachingRequest = { caching?: true } + +const OPENAI_REASONING_EFFORTS = ["low", "medium", "high"] as const +type OpenAiReasoningEffort = (typeof OPENAI_REASONING_EFFORTS)[number] + +function getReasoningEffort(options: ApiHandlerOptions, supported: unknown): OpenAiReasoningEffort | undefined { + const effort = options.reasoningEffort + const selectedEffort = OPENAI_REASONING_EFFORTS.find((candidate) => candidate === effort) + if (!selectedEffort) { + return undefined + } + + if (supported === true || (Array.isArray(supported) && supported.includes(selectedEffort))) { + return selectedEffort + } + + return undefined +} + +function mapNanoGptUsage(usage: NanoGptUsage): ApiStreamUsageChunk { + return { + type: "usage", + inputTokens: usage.prompt_tokens ?? 0, + outputTokens: usage.completion_tokens ?? 0, + cacheReadTokens: usage.cache_read_input_tokens ?? usage.prompt_tokens_details?.cached_tokens, + cacheWriteTokens: usage.cache_creation_input_tokens, + reasoningTokens: usage.completion_tokens_details?.reasoning_tokens ?? usage.reasoning_tokens, + } +} + +export class NanoGptHandler extends RouterProvider implements SingleCompletionHandler { + constructor(options: ApiHandlerOptions) { + super({ + options, + name: "nanogpt", + baseURL: NANOGPT_BASE_URL, + apiKey: options.nanoGptApiKey, + modelId: options.nanoGptModelId, + defaultModelId: nanoGptDefaultModelId, + defaultModelInfo: nanoGptDefaultModelInfo, + }) + } + + private getRequestModelId(canonicalModelId: string): string { + return applyNanoGptRoutingPreference( + canonicalModelId, + this.options.nanoGptRoutingPreference as NanoGptRoutingPreference | undefined, + ) + } + + private createSafeError(operation: string, error: unknown): Error { + return handleProviderError(error, "NanoGPT", { + messagePrefix: operation, + messageTransformer: (message) => + this.options.nanoGptApiKey + ? `NanoGPT ${operation} error: ${message.replaceAll(this.options.nanoGptApiKey, "[REDACTED]")}` + : `NanoGPT ${operation} error: ${message}`, + }) + } + + override async *createMessage( + systemPrompt: string, + messages: Anthropic.Messages.MessageParam[], + metadata?: ApiHandlerCreateMessageMetadata, + ): ApiStream { + const { id: canonicalModelId, info } = await this.fetchModel() + const body: OpenAI.Chat.Completions.ChatCompletionCreateParamsStreaming & NanoGptCachingRequest = { + model: this.getRequestModelId(canonicalModelId), + messages: [{ role: "system", content: systemPrompt }, ...convertToOpenAiMessages(messages)], + stream: true, + stream_options: { include_usage: true }, + max_tokens: info.maxTokens ?? undefined, + tools: this.convertToolsForOpenAI(metadata?.tools), + tool_choice: metadata?.tool_choice, + parallel_tool_calls: metadata?.parallelToolCalls ?? true, + ...(this.options.nanoGptRoutingPreference === "caching" ? { caching: true } : {}), + } + + if (this.options.modelTemperature !== undefined && this.supportsTemperature(canonicalModelId)) { + body.temperature = this.options.modelTemperature + } + + const reasoningEffort = getReasoningEffort(this.options, info.supportsReasoningEffort) + if (reasoningEffort) { + body.reasoning_effort = reasoningEffort + } + + try { + const completion = await this.client.chat.completions.create(body, { signal: metadata?.abortSignal }) + for await (const chunk of completion) { + const delta = chunk.choices[0]?.delta + if (delta?.content) { + yield { type: "text", text: delta.content } + } + + const reasoning = extractReasoningFromDelta(delta) + if (reasoning) { + yield { type: "reasoning", text: reasoning } + } + + for (const toolCall of delta?.tool_calls ?? []) { + yield { + type: "tool_call_partial", + index: toolCall.index, + id: toolCall.id, + name: toolCall.function?.name, + arguments: toolCall.function?.arguments, + } + } + + if (chunk.usage) { + yield mapNanoGptUsage(chunk.usage as NanoGptUsage) + } + } + } catch (error) { + throw this.createSafeError("streaming", error) + } + } + + async completePrompt(prompt: string, options?: CompletePromptOptions): Promise { + const { id: canonicalModelId, info } = await this.fetchModel() + const body: OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming & NanoGptCachingRequest = { + model: this.getRequestModelId(canonicalModelId), + messages: [{ role: "user", content: prompt }], + stream: false, + max_tokens: info.maxTokens ?? undefined, + ...(this.options.nanoGptRoutingPreference === "caching" ? { caching: true } : {}), + } + + if (this.options.modelTemperature !== undefined && this.supportsTemperature(canonicalModelId)) { + body.temperature = this.options.modelTemperature + } + + const reasoningEffort = getReasoningEffort(this.options, info.supportsReasoningEffort) + if (reasoningEffort) { + body.reasoning_effort = reasoningEffort + } + + try { + const response = await this.client.chat.completions.create(body, { + signal: options?.abortSignal, + timeout: options?.timeoutMs, + }) + return response.choices[0]?.message.content ?? "" + } catch (error) { + throw this.createSafeError("completion", error) + } + } +} diff --git a/src/api/providers/router-provider.ts b/src/api/providers/router-provider.ts index cbdd49e58b..9e29be7bda 100644 --- a/src/api/providers/router-provider.ts +++ b/src/api/providers/router-provider.ts @@ -26,17 +26,10 @@ export abstract class RouterProvider extends BaseProvider { protected readonly modelId?: string protected readonly defaultModelId: string protected readonly defaultModelInfo: ModelInfo + protected readonly apiKey?: string protected readonly client: OpenAI - constructor({ - options, - name, - baseURL, - apiKey = "not-provided", - modelId, - defaultModelId, - defaultModelInfo, - }: RouterProviderOptions) { + constructor({ options, name, baseURL, apiKey, modelId, defaultModelId, defaultModelInfo }: RouterProviderOptions) { super() this.options = options @@ -44,10 +37,11 @@ export abstract class RouterProvider extends BaseProvider { this.modelId = modelId this.defaultModelId = defaultModelId this.defaultModelInfo = defaultModelInfo + this.apiKey = apiKey this.client = new OpenAI({ baseURL, - apiKey, + apiKey: apiKey ?? "not-provided", defaultHeaders: { ...DEFAULT_HEADERS, ...(options.openAiHeaders || {}), @@ -66,7 +60,7 @@ export abstract class RouterProvider extends BaseProvider { if (!this.modelFetchPromise) { this.modelFetchPromise = getModels({ provider: this.name, - apiKey: this.client.apiKey, + apiKey: this.apiKey, baseUrl: this.client.baseURL, }) .then((models) => { @@ -105,7 +99,7 @@ export abstract class RouterProvider extends BaseProvider { const cachedModels = getModelsFromCache({ provider: this.name, baseUrl: this.client.baseURL, - apiKey: this.client.apiKey, + apiKey: this.apiKey, }) if (cachedModels?.[id]) { // Also populate instance models for future calls diff --git a/src/core/config/__tests__/ContextProxy.spec.ts b/src/core/config/__tests__/ContextProxy.spec.ts index 551591b0ed..d4cae48177 100644 --- a/src/core/config/__tests__/ContextProxy.spec.ts +++ b/src/core/config/__tests__/ContextProxy.spec.ts @@ -308,6 +308,25 @@ describe("ContextProxy", () => { }) describe("setProviderSettings", () => { + it("stores and returns the complete NanoGPT configuration across secret and global state", async () => { + await proxy.setProviderSettings({ + apiProvider: "nanogpt", + nanoGptApiKey: "nanogpt-secret", + nanoGptModelId: "openai/model", + nanoGptRoutingPreference: "throughput", + }) + + expect(mockSecrets.store).toHaveBeenCalledWith("nanoGptApiKey", "nanogpt-secret") + expect(mockGlobalState.update).toHaveBeenCalledWith("nanoGptModelId", "openai/model") + expect(mockGlobalState.update).toHaveBeenCalledWith("nanoGptRoutingPreference", "throughput") + expect(proxy.getProviderSettings()).toMatchObject({ + apiProvider: "nanogpt", + nanoGptApiKey: "nanogpt-secret", + nanoGptModelId: "openai/model", + nanoGptRoutingPreference: "throughput", + }) + }) + it("should clear old API configuration values and set new ones", async () => { // Set up initial API configuration values await proxy.updateGlobalState("apiModelId", "old-model") diff --git a/src/core/webview/__tests__/ClineProvider.spec.ts b/src/core/webview/__tests__/ClineProvider.spec.ts index 00f848bec4..6167158ccc 100644 --- a/src/core/webview/__tests__/ClineProvider.spec.ts +++ b/src/core/webview/__tests__/ClineProvider.spec.ts @@ -1011,6 +1011,28 @@ describe("ClineProvider", () => { expect(state).toHaveProperty("writeDelayMs") }) + test("getState and getStateToPostToWebview return the complete NanoGPT configuration", async () => { + await provider.resolveWebviewView(mockWebviewView) + await provider.contextProxy.setProviderSettings({ + apiProvider: "nanogpt", + nanoGptApiKey: "nanogpt-secret", + nanoGptModelId: "openai/model", + nanoGptRoutingPreference: "latency", + }) + + const state = await provider.getState() + const postedState = await provider.getStateToPostToWebview() + const expectedConfiguration = { + apiProvider: "nanogpt", + nanoGptApiKey: "nanogpt-secret", + nanoGptModelId: "openai/model", + nanoGptRoutingPreference: "latency", + } + + expect(state.apiConfiguration).toMatchObject(expectedConfiguration) + expect(postedState.apiConfiguration).toMatchObject(expectedConfiguration) + }) + test("getState returns the saved destructive command guard setting", async () => { await provider.contextProxy.setValue("destructiveCommandGuardEnabled", true) @@ -3200,6 +3222,8 @@ describe("ClineProvider - Router Models", () => { expect(getModels).toHaveBeenCalledWith(expect.objectContaining({ provider: "opencode-go" })) // Kenari's /models endpoint is public, so it is fetched like the other no-auth routers. expect(getModels).toHaveBeenCalledWith(expect.objectContaining({ provider: "kenari" })) + // NanoGPT's detailed catalog is public and may be scoped by an optional key. + expect(getModels).toHaveBeenCalledWith({ provider: "nanogpt", apiKey: undefined }) // Verify response was sent expect(mockPostMessage).toHaveBeenCalledWith({ @@ -3218,6 +3242,7 @@ describe("ClineProvider - Router Models", () => { moonshot: {}, "opencode-go": mockModels, kenari: mockModels, + nanogpt: mockModels, "kimi-code": {}, }, values: undefined, @@ -3252,6 +3277,7 @@ describe("ClineProvider - Router Models", () => { .mockRejectedValueOnce(new Error("LiteLLM connection failed")) // litellm fail .mockResolvedValueOnce(mockModels) // opencode-go (public endpoint) .mockResolvedValueOnce(mockModels) // kenari (public endpoint) + .mockResolvedValueOnce(mockModels) // nanogpt (public endpoint) await messageHandler({ type: "requestRouterModels" }) @@ -3272,6 +3298,7 @@ describe("ClineProvider - Router Models", () => { moonshot: {}, "opencode-go": mockModels, kenari: mockModels, + nanogpt: mockModels, "kimi-code": {}, }, values: undefined, @@ -3372,6 +3399,7 @@ describe("ClineProvider - Router Models", () => { moonshot: {}, "opencode-go": mockModels, kenari: mockModels, + nanogpt: mockModels, "kimi-code": {}, }, values: undefined, diff --git a/src/core/webview/__tests__/webviewMessageHandler.spec.ts b/src/core/webview/__tests__/webviewMessageHandler.spec.ts index a3b76aa8b2..bc92522790 100644 --- a/src/core/webview/__tests__/webviewMessageHandler.spec.ts +++ b/src/core/webview/__tests__/webviewMessageHandler.spec.ts @@ -485,6 +485,8 @@ describe("webviewMessageHandler - requestRouterModels", () => { expect(mockGetModels).toHaveBeenCalledWith(expect.objectContaining({ provider: "opencode-go" })) // Kenari's /models endpoint is public, so it is fetched like the other no-auth routers. expect(mockGetModels).toHaveBeenCalledWith(expect.objectContaining({ provider: "kenari" })) + // NanoGPT's detailed catalog is public and may optionally be scoped by a key. + expect(mockGetModels).toHaveBeenCalledWith({ provider: "nanogpt", apiKey: undefined }) // Verify response was sent expect(mockClineProvider.postMessageToWebview).toHaveBeenCalledWith({ @@ -503,6 +505,7 @@ describe("webviewMessageHandler - requestRouterModels", () => { moonshot: {}, "opencode-go": mockModels, kenari: mockModels, + nanogpt: mockModels, "kimi-code": {}, }, values: undefined, @@ -606,6 +609,53 @@ describe("webviewMessageHandler - requestRouterModels", () => { }) }) + it("fetches NanoGPT publicly without an API key", async () => { + mockClineProvider.getState = vi.fn().mockResolvedValue({ apiConfiguration: {} }) + mockGetModels.mockResolvedValue({ + "openai/gpt-5.6-sol": { maxTokens: 128000, contextWindow: 1050000, supportsPromptCache: false }, + }) + + await webviewMessageHandler(mockClineProvider, { + type: "requestRouterModels", + values: { provider: "nanogpt" }, + }) + + expect(mockGetModels).toHaveBeenCalledWith({ provider: "nanogpt", apiKey: undefined }) + expect(mockFlushModels).not.toHaveBeenCalled() + }) + + it("prefers an unsaved NanoGPT key and refreshes the matching key-scoped cache", async () => { + mockClineProvider.getState = vi.fn().mockResolvedValue({ + apiConfiguration: { nanoGptApiKey: "saved-key" }, + }) + mockGetModels.mockResolvedValue({ + "openai/gpt-5.6-sol": { maxTokens: 128000, contextWindow: 1050000, supportsPromptCache: false }, + }) + + await webviewMessageHandler(mockClineProvider, { + type: "requestRouterModels", + values: { provider: "nanogpt", nanoGptApiKey: "unsaved-key" }, + }) + + expect(mockFlushModels).toHaveBeenCalledWith({ provider: "nanogpt", apiKey: "unsaved-key" }, true) + expect(mockGetModels).toHaveBeenCalledWith({ provider: "nanogpt", apiKey: "unsaved-key" }) + }) + + it("uses the saved NanoGPT key for manual refresh", async () => { + mockClineProvider.getState = vi.fn().mockResolvedValue({ + apiConfiguration: { nanoGptApiKey: "saved-key" }, + }) + mockGetModels.mockResolvedValue({}) + + await webviewMessageHandler(mockClineProvider, { + type: "requestRouterModels", + values: { provider: "nanogpt", refresh: true }, + }) + + expect(mockFlushModels).toHaveBeenCalledWith({ provider: "nanogpt", apiKey: "saved-key" }, true) + expect(mockGetModels).toHaveBeenCalledWith({ provider: "nanogpt", apiKey: "saved-key" }) + }) + it("handles LiteLLM models with values from message when config is missing", async () => { mockClineProvider.getState = vi.fn().mockResolvedValue({ apiConfiguration: { @@ -691,6 +741,7 @@ describe("webviewMessageHandler - requestRouterModels", () => { moonshot: {}, "opencode-go": mockModels, kenari: mockModels, + nanogpt: mockModels, "kimi-code": {}, }, values: undefined, @@ -716,6 +767,8 @@ describe("webviewMessageHandler - requestRouterModels", () => { .mockResolvedValueOnce(mockModels) // zoo-gateway .mockRejectedValueOnce(new Error("LiteLLM connection failed")) // litellm .mockResolvedValueOnce(mockModels) // opencode-go + .mockResolvedValueOnce(mockModels) // kenari + .mockResolvedValueOnce(mockModels) // nanogpt await webviewMessageHandler(mockClineProvider, { type: "requestRouterModels", @@ -753,6 +806,7 @@ describe("webviewMessageHandler - requestRouterModels", () => { moonshot: {}, "opencode-go": mockModels, kenari: mockModels, + nanogpt: mockModels, "kimi-code": {}, }, values: undefined, diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index 5a28ce12d0..f0fc33501f 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -1076,6 +1076,7 @@ export const webviewMessageHandler = async ( moonshot: {}, "opencode-go": {}, kenari: {}, + nanogpt: {}, "kimi-code": {}, } @@ -1219,6 +1220,19 @@ export const webviewMessageHandler = async ( options: { provider: "kenari", apiKey: kenariApiKey }, }) + // NanoGPT's detailed catalog is public, while an optional key can expose a + // different allowlist. Prefer an explicitly supplied unsaved key and use the + // same key-scoped options for refresh and retrieval. + const nanoGptApiKey = message?.values?.nanoGptApiKey ?? apiConfiguration.nanoGptApiKey + if (message?.values?.nanoGptApiKey !== undefined) { + await flushModels({ provider: "nanogpt", apiKey: nanoGptApiKey }, true) + } + + candidates.push({ + key: "nanogpt", + options: { provider: "nanogpt", apiKey: nanoGptApiKey }, + }) + if (!providerFilter || providerFilter === "kimi-code") { const { kimiCodeOAuthManager } = await import("../../integrations/kimi-code/oauth") const kimiCodeAuthMethod = diff --git a/src/shared/api.ts b/src/shared/api.ts index 056612f9f9..1787e15e88 100644 --- a/src/shared/api.ts +++ b/src/shared/api.ts @@ -189,6 +189,7 @@ const dynamicProviderExtras = { moonshot: {} as { apiKey?: string; baseUrl?: string }, "opencode-go": {} as { apiKey?: string }, kenari: {} as { apiKey?: string }, + nanogpt: {} as { apiKey?: string }, "kimi-code": {} as { apiKey?: string }, } as const satisfies Record diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx index be7dad7542..f3375abfaf 100644 --- a/webview-ui/src/components/settings/ApiOptions.tsx +++ b/webview-ui/src/components/settings/ApiOptions.tsx @@ -77,6 +77,7 @@ import { VercelAiGateway, OpenCodeGo, Kenari, + NanoGPT, ZooGateway, MiniMax, Mimo, @@ -677,6 +678,17 @@ const ApiOptions = ({ /> )} + {selectedProvider === providerIdentifiers.nanogpt && ( + + )} + {selectedProvider === providerIdentifiers.zooGateway && ( { VercelAiGateway: provider("provider-vercel-ai-gateway"), OpenCodeGo: provider("provider-opencode-go"), Kenari: provider("provider-kenari"), + NanoGPT: provider("provider-nanogpt"), ZooGateway: provider("provider-zoo-gateway"), MiniMax: provider("provider-minimax"), Mimo: provider("provider-mimo"), @@ -350,6 +351,7 @@ describe("ApiOptions interactions", () => { providerIdentifiers.vercelAiGateway, providerIdentifiers.opencodeGo, providerIdentifiers.kenari, + providerIdentifiers.nanogpt, providerIdentifiers.zooGateway, providerIdentifiers.fireworks, providerIdentifiers.friendli, diff --git a/webview-ui/src/components/settings/__tests__/ApiOptions.spec.tsx b/webview-ui/src/components/settings/__tests__/ApiOptions.spec.tsx index 86e7273d45..c625650845 100644 --- a/webview-ui/src/components/settings/__tests__/ApiOptions.spec.tsx +++ b/webview-ui/src/components/settings/__tests__/ApiOptions.spec.tsx @@ -420,6 +420,7 @@ describe("ApiOptions", () => { const optionTexts = Array.from(options).map((opt) => opt.textContent) expect(optionTexts).toContain("OpenAI") expect(optionTexts).toContain("Anthropic") + expect(optionTexts).toContain("NanoGPT") // Note: The mock doesn't implement search functionality, so we're just verifying // that the select element is rendered with the expected options diff --git a/webview-ui/src/components/settings/__tests__/SettingsView.unsaved-changes.spec.tsx b/webview-ui/src/components/settings/__tests__/SettingsView.unsaved-changes.spec.tsx index 20eb7543eb..11b7de066d 100644 --- a/webview-ui/src/components/settings/__tests__/SettingsView.unsaved-changes.spec.tsx +++ b/webview-ui/src/components/settings/__tests__/SettingsView.unsaved-changes.spec.tsx @@ -603,4 +603,110 @@ describe("SettingsView - Unsaved Changes Detection", () => { }), ) }) + + it("buffers and saves the complete NanoGPT provider configuration from cached state", async () => { + const liveApiConfiguration = { + apiProvider: "nanogpt" as const, + nanoGptApiKey: "original-key", + nanoGptModelId: "openai/original", + nanoGptRoutingPreference: "auto" as const, + } + ;(useExtensionState as ReturnType).mockReturnValue({ + ...defaultExtensionState, + apiConfiguration: liveApiConfiguration, + }) + vi.mocked(ApiOptions).mockImplementation(({ apiConfiguration, setApiConfigurationField }) => ( +

+ setApiConfigurationField("nanoGptApiKey", event.target.value)} + /> + setApiConfigurationField("nanoGptModelId", event.target.value)} + /> + +
+ )) + + renderWithExtensionState(, { queryClient }) + + expect(await screen.findByTestId("cached-nanogpt-key")).toHaveValue("original-key") + expect(screen.getByTestId("cached-nanogpt-model")).toHaveValue("openai/original") + expect(screen.getByTestId("cached-nanogpt-routing")).toHaveValue("auto") + + fireEvent.change(screen.getByTestId("cached-nanogpt-key"), { target: { value: "unsaved-key" } }) + fireEvent.change(screen.getByTestId("cached-nanogpt-model"), { target: { value: "openai/next" } }) + fireEvent.change(screen.getByTestId("cached-nanogpt-routing"), { target: { value: "tools" } }) + + expect(liveApiConfiguration).toEqual({ + apiProvider: "nanogpt", + nanoGptApiKey: "original-key", + nanoGptModelId: "openai/original", + nanoGptRoutingPreference: "auto", + }) + expect(postMessage).not.toHaveBeenCalledWith(expect.objectContaining({ type: "upsertApiConfiguration" })) + + fireEvent.click(screen.getByTestId("save-button")) + + expect(postMessage).toHaveBeenCalledWith({ + type: "upsertApiConfiguration", + text: "default", + apiConfiguration: { + apiProvider: "nanogpt", + nanoGptApiKey: "unsaved-key", + nanoGptModelId: "openai/next", + nanoGptRoutingPreference: "tools", + }, + }) + }) + + it("discards NanoGPT cached edits and restores the extension values", async () => { + const onDone = vi.fn() + ;(useExtensionState as ReturnType).mockReturnValue({ + ...defaultExtensionState, + apiConfiguration: { + apiProvider: "nanogpt", + nanoGptApiKey: "saved-key", + nanoGptModelId: "openai/saved", + nanoGptRoutingPreference: "cheap", + }, + }) + vi.mocked(ApiOptions).mockImplementation(({ apiConfiguration, setApiConfigurationField }) => ( + setApiConfigurationField("nanoGptApiKey", event.target.value)} + /> + )) + + renderWithExtensionState(, { queryClient }) + fireEvent.change(await screen.findByTestId("cached-nanogpt-key"), { target: { value: "discard-me" } }) + fireEvent.click(screen.getByText("settings:common.done")) + fireEvent.click(await screen.findByText("settings:unsavedChangesDialog.discardButton")) + + await waitFor(() => expect(screen.getByTestId("cached-nanogpt-key")).toHaveValue("saved-key")) + expect(onDone).toHaveBeenCalledOnce() + expect(postMessage).not.toHaveBeenCalledWith(expect.objectContaining({ type: "upsertApiConfiguration" })) + }) }) diff --git a/webview-ui/src/components/settings/constants.ts b/webview-ui/src/components/settings/constants.ts index 7e5e10db6b..8c51aca2fe 100644 --- a/webview-ui/src/components/settings/constants.ts +++ b/webview-ui/src/components/settings/constants.ts @@ -70,6 +70,7 @@ export const PROVIDERS: Array<{ value: string; label: string; proxy: boolean }> { value: providerIdentifiers.vercelAiGateway, label: "Vercel AI Gateway", proxy: false }, { value: providerIdentifiers.opencodeGo, label: "Opencode Go", proxy: false }, { value: providerIdentifiers.kenari, label: "Kenari", proxy: false }, + { value: providerIdentifiers.nanogpt, label: "NanoGPT", proxy: false }, { value: providerIdentifiers.zooGateway, label: "Zoo Gateway", proxy: false }, { value: providerIdentifiers.minimax, label: "MiniMax", proxy: false }, { value: providerIdentifiers.mimo, label: "Xiaomi MiMo", proxy: false }, diff --git a/webview-ui/src/components/settings/providers/NanoGPT.tsx b/webview-ui/src/components/settings/providers/NanoGPT.tsx new file mode 100644 index 0000000000..cc7b7a431f --- /dev/null +++ b/webview-ui/src/components/settings/providers/NanoGPT.tsx @@ -0,0 +1,141 @@ +import { useCallback, useEffect } from "react" +import { VSCodeLink, VSCodeTextField } from "@vscode/webview-ui-toolkit/react" + +import { + type NanoGptRoutingPreference, + type OrganizationAllowList, + type ProviderSettings, + type RouterModels, + nanoGptDefaultModelId, + nanoGptDefaultRoutingPreference, + nanoGptRoutingPreferences, +} from "@roo-code/types" + +import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink" +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@src/components/ui" +import { useAppTranslation } from "@src/i18n/TranslationContext" +import { vscode } from "@src/utils/vscode" + +import { ModelPicker } from "../ModelPicker" +import { inputEventTransform } from "../transforms" + +type NanoGPTProps = { + apiConfiguration: ProviderSettings + setApiConfigurationField: (field: K, value: ProviderSettings[K]) => void + routerModels?: RouterModels + organizationAllowList: OrganizationAllowList + modelValidationError?: string + simplifySettings?: boolean +} + +const routingOptionKeys: Record = { + auto: "automatic", + fast: "fastest", + cheap: "cheapest", + latency: "lowestLatency", + throughput: "highestThroughput", + tools: "toolCapable", + caching: "cacheCapable", +} + +export const NanoGPT = ({ + apiConfiguration, + setApiConfigurationField, + routerModels, + organizationAllowList, + modelValidationError, + simplifySettings, +}: NanoGPTProps) => { + const { t } = useAppTranslation() + const routingPreference = apiConfiguration.nanoGptRoutingPreference ?? nanoGptDefaultRoutingPreference + + const handleInputChange = useCallback( + ( + field: K, + transform: (event: E) => ProviderSettings[K] = inputEventTransform, + ) => + (event: E | Event) => { + setApiConfigurationField(field, transform(event as E)) + }, + [setApiConfigurationField], + ) + + useEffect(() => { + vscode.postMessage({ + type: "requestRouterModels", + values: { + provider: "nanogpt", + nanoGptApiKey: apiConfiguration.nanoGptApiKey, + }, + }) + }, [apiConfiguration.nanoGptApiKey]) + + return ( + <> + + + +
+ {t("settings:providers.apiKeyStorageNotice")} +
+ {!apiConfiguration.nanoGptApiKey && ( + + {t("settings:providers.nanoGpt.getApiKey")} + + )} + + + +
+ + +
+ {t("settings:providers.nanoGpt.automaticExplanation")} +
+
+ + {routingPreference !== nanoGptDefaultRoutingPreference && ( +
+

{t("settings:providers.nanoGpt.billingWarning")}

+ + {t("settings:providers.nanoGpt.routingDocs")} + +
+ )} + + ) +} diff --git a/webview-ui/src/components/settings/providers/__tests__/NanoGPT.spec.tsx b/webview-ui/src/components/settings/providers/__tests__/NanoGPT.spec.tsx new file mode 100644 index 0000000000..d2bf7b3c04 --- /dev/null +++ b/webview-ui/src/components/settings/providers/__tests__/NanoGPT.spec.tsx @@ -0,0 +1,181 @@ +import { fireEvent, render, screen } from "@testing-library/react" + +import { + type OrganizationAllowList, + type ProviderSettings, + type RouterModels, + nanoGptDefaultModelId, + nanoGptRoutingPreferences, +} from "@roo-code/types" + +import { NanoGPT } from "../NanoGPT" + +const { postMessageMock } = vi.hoisted(() => ({ postMessageMock: vi.fn() })) + +vi.mock("@src/utils/vscode", () => ({ vscode: { postMessage: postMessageMock } })) + +vi.mock("@src/i18n/TranslationContext", () => ({ + useAppTranslation: () => ({ t: (key: string) => key }), +})) + +vi.mock("@vscode/webview-ui-toolkit/react", () => ({ + VSCodeTextField: ({ + children, + value, + onInput, + type, + }: React.ComponentProps<"input"> & { children: React.ReactNode }) => ( +
+ {children} + +
+ ), + VSCodeLink: ({ children, href }: React.ComponentProps<"a">) => {children}, +})) + +vi.mock("@src/components/common/VSCodeButtonLink", () => ({ + VSCodeButtonLink: ({ children, href }: React.ComponentProps<"a">) => ( + + {children} + + ), +})) + +vi.mock("@src/components/ui", () => ({ + Select: ({ + children, + value, + onValueChange, + }: { + children: React.ReactNode + value: string + onValueChange: (value: string) => void + }) => ( + + ), + SelectContent: ({ children }: { children: React.ReactNode }) => <>{children}, + SelectItem: ({ children, value }: { children: React.ReactNode; value: string }) => ( + + ), + SelectTrigger: ({ children }: { children: React.ReactNode }) => <>{children}, + SelectValue: () => null, +})) + +vi.mock("../../ModelPicker", () => ({ + ModelPicker: ({ + defaultModelId, + models, + modelIdKey, + serviceName, + }: { + defaultModelId: string + models: object + modelIdKey: string + serviceName: string + }) => ( +
+ ), +})) + +describe("NanoGPT", () => { + const organizationAllowList: OrganizationAllowList = { allowAll: true, providers: {} } + const setApiConfigurationField = vi.fn() + const routerModels: RouterModels = { + openrouter: {}, + "vercel-ai-gateway": {}, + "zoo-gateway": {}, + litellm: {}, + requesty: {}, + unbound: {}, + poe: {}, + deepseek: {}, + moonshot: {}, + "opencode-go": {}, + kenari: {}, + nanogpt: { "openai/test": { contextWindow: 1, maxTokens: 1, supportsPromptCache: false } }, + "kimi-code": {}, + ollama: {}, + lmstudio: {}, + } + + const renderComponent = (apiConfiguration: ProviderSettings = {}) => + render( + , + ) + + beforeEach(() => vi.clearAllMocks()) + + it("renders the secret key input, CTA, dynamic model picker, routing copy, and links", () => { + renderComponent({ nanoGptRoutingPreference: "fast" }) + + expect(screen.getByTestId("nanogpt-api-key")).toHaveAttribute("type", "password") + expect(screen.getByText("settings:providers.nanoGpt.apiKey")).toBeInTheDocument() + expect(screen.getByTestId("nanogpt-get-key")).toHaveAttribute("href", "https://nano-gpt.com/api") + expect(screen.getByText("settings:providers.nanoGpt.getApiKey")).toBeInTheDocument() + expect(screen.getByTestId("model-picker")).toHaveAttribute("data-default-model-id", nanoGptDefaultModelId) + expect(screen.getByTestId("model-picker")).toHaveAttribute("data-model-id-key", "nanoGptModelId") + expect(screen.getByTestId("model-picker")).toHaveAttribute("data-model-count", "1") + expect(screen.getByText("settings:providers.nanoGpt.automaticExplanation")).toBeInTheDocument() + expect(screen.getByText("settings:providers.nanoGpt.billingWarning")).toBeInTheDocument() + expect(screen.getByText("settings:providers.nanoGpt.routingDocs")).toHaveAttribute( + "href", + "https://docs.nano-gpt.com/api-reference/miscellaneous/provider-selection", + ) + }) + + it("defaults routing to automatic and renders every routing option", () => { + renderComponent() + + expect(screen.getByTestId("routing-select")).toHaveValue("auto") + expect(screen.getAllByRole("option").map((option) => option.getAttribute("value"))).toEqual([ + ...nanoGptRoutingPreferences, + ]) + expect(screen.queryByText("settings:providers.nanoGpt.billingWarning")).not.toBeInTheDocument() + expect(screen.queryByText("settings:providers.nanoGpt.routingDocs")).not.toBeInTheDocument() + }) + + it("updates the cached key and routing preference with exact values", () => { + renderComponent({ nanoGptApiKey: "", nanoGptRoutingPreference: "fast" }) + + fireEvent.input(screen.getByTestId("nanogpt-api-key"), { target: { value: "new-secret" } }) + fireEvent.change(screen.getByTestId("routing-select"), { target: { value: "tools" } }) + + expect(setApiConfigurationField).toHaveBeenCalledWith("nanoGptApiKey", "new-secret") + expect(setApiConfigurationField).toHaveBeenCalledWith("nanoGptRoutingPreference", "tools") + }) + + it("refreshes models with the unsaved cached key whenever it changes", () => { + const { rerender } = renderComponent({ nanoGptApiKey: "first-key" }) + expect(postMessageMock).toHaveBeenLastCalledWith({ + type: "requestRouterModels", + values: { provider: "nanogpt", nanoGptApiKey: "first-key" }, + }) + + rerender( + , + ) + + expect(postMessageMock).toHaveBeenLastCalledWith({ + type: "requestRouterModels", + values: { provider: "nanogpt", nanoGptApiKey: "unsaved-key" }, + }) + }) +}) diff --git a/webview-ui/src/components/settings/providers/index.ts b/webview-ui/src/components/settings/providers/index.ts index 8d725efed2..12ea4cd786 100644 --- a/webview-ui/src/components/settings/providers/index.ts +++ b/webview-ui/src/components/settings/providers/index.ts @@ -26,6 +26,7 @@ export { Friendli } from "./Friendli" export { VercelAiGateway } from "./VercelAiGateway" export { OpenCodeGo } from "./OpenCodeGo" export { Kenari } from "./Kenari" +export { NanoGPT } from "./NanoGPT" export { ZooGateway } from "./ZooGateway" export { MiniMax } from "./MiniMax" export { Mimo } from "./Mimo" diff --git a/webview-ui/src/components/settings/utils/__tests__/providerModelConfig.spec.ts b/webview-ui/src/components/settings/utils/__tests__/providerModelConfig.spec.ts index 868bdac319..e19df545e5 100644 --- a/webview-ui/src/components/settings/utils/__tests__/providerModelConfig.spec.ts +++ b/webview-ui/src/components/settings/utils/__tests__/providerModelConfig.spec.ts @@ -1,10 +1,16 @@ -import { anthropicDefaultModelId, mainlandZAiDefaultModelId, providerIdentifiers } from "@roo-code/types" +import { + anthropicDefaultModelId, + mainlandZAiDefaultModelId, + nanoGptDefaultModelId, + providerIdentifiers, +} from "@roo-code/types" import { PROVIDER_SERVICE_CONFIG, PROVIDER_DEFAULT_MODEL_IDS, getProviderServiceConfig, getProviderModelConfig, + getProviderDocsSlug, getDefaultModelIdForProvider, getStaticModelsForProvider, isStaticModelProvider, @@ -168,6 +174,19 @@ describe("providerModelConfig", () => { const config = getProviderModelConfig(providerIdentifiers.anthropic) expect(config).toEqual({ field: "apiModelId", default: anthropicDefaultModelId }) }) + + it("returns NanoGPT's dynamic model field and fallback", () => { + expect(getProviderModelConfig(providerIdentifiers.nanogpt)).toEqual({ + field: "nanoGptModelId", + default: nanoGptDefaultModelId, + }) + }) + }) + + describe("getProviderDocsSlug", () => { + it("uses NanoGPT's provider identifier as its external documentation slug", () => { + expect(getProviderDocsSlug(providerIdentifiers.nanogpt)).toBe("nanogpt") + }) }) describe("getStaticModelsForProvider", () => { diff --git a/webview-ui/src/components/settings/utils/providerModelConfig.ts b/webview-ui/src/components/settings/utils/providerModelConfig.ts index 5e18944951..7230e4cbe4 100644 --- a/webview-ui/src/components/settings/utils/providerModelConfig.ts +++ b/webview-ui/src/components/settings/utils/providerModelConfig.ts @@ -29,6 +29,7 @@ import { vercelAiGatewayDefaultModelId, opencodeGoDefaultModelId, kenariDefaultModelId, + nanoGptDefaultModelId, zooGatewayDefaultModelId, zaiApiLineConfigs, getZAiModels, @@ -144,6 +145,7 @@ const PROVIDER_MODEL_CONFIG: Partial> }, [providerIdentifiers.opencodeGo]: { field: "opencodeGoModelId", default: opencodeGoDefaultModelId }, [providerIdentifiers.kenari]: { field: "kenariModelId", default: kenariDefaultModelId }, + [providerIdentifiers.nanogpt]: { field: "nanoGptModelId", default: nanoGptDefaultModelId }, [providerIdentifiers.zooGateway]: { field: "zooGatewayModelId", default: zooGatewayDefaultModelId }, [providerIdentifiers.openai]: { field: "openAiModelId" }, [providerIdentifiers.ollama]: { field: "ollamaModelId" }, diff --git a/webview-ui/src/components/ui/hooks/__tests__/useSelectedModel.spec.ts b/webview-ui/src/components/ui/hooks/__tests__/useSelectedModel.spec.ts index 1619270457..dbc52e390b 100644 --- a/webview-ui/src/components/ui/hooks/__tests__/useSelectedModel.spec.ts +++ b/webview-ui/src/components/ui/hooks/__tests__/useSelectedModel.spec.ts @@ -15,6 +15,8 @@ import { litellmDefaultModelInfo, kenariDefaultModelId, kenariDefaultModelInfo, + nanoGptDefaultModelId, + nanoGptDefaultModelInfo, openAiModelInfoSaneDefaults, minimaxDefaultModelId, minimaxModels, @@ -1038,6 +1040,48 @@ describe("useSelectedModel", () => { }) }) + describe("nanogpt provider", () => { + it("uses dynamic metadata for the configured NanoGPT model", () => { + const dynamicInfo: ModelInfo = { + maxTokens: 16_384, + contextWindow: 256_000, + supportsPromptCache: false, + description: "Dynamic NanoGPT model", + } + mockUseRouterModels.mockReturnValue(createRouterModelsResult({ nanogpt: { "openai/custom": dynamicInfo } })) + mockUseOpenRouterModelProviders.mockReturnValue(createOpenRouterModelProvidersResult({})) + + const { result } = renderHook( + () => + useSelectedModel({ + apiProvider: providerIdentifiers.nanogpt, + nanoGptModelId: "openai/custom", + }), + { wrapper: createWrapper() }, + ) + + expect(result.current.id).toBe("openai/custom") + expect(result.current.info).toEqual(dynamicInfo) + }) + + it("uses NanoGPT's shared fallback when its dynamic catalog is empty", () => { + mockUseRouterModels.mockReturnValue(createRouterModelsResult({ nanogpt: {} })) + mockUseOpenRouterModelProviders.mockReturnValue(createOpenRouterModelProvidersResult({})) + + const { result } = renderHook( + () => + useSelectedModel({ + apiProvider: providerIdentifiers.nanogpt, + nanoGptModelId: "missing-model", + }), + { wrapper: createWrapper() }, + ) + + expect(result.current.id).toBe(nanoGptDefaultModelId) + expect(result.current.info).toEqual(nanoGptDefaultModelInfo) + }) + }) + describe("openai provider", () => { beforeEach(() => { mockUseRouterModels.mockReturnValue({ diff --git a/webview-ui/src/components/ui/hooks/useSelectedModel.ts b/webview-ui/src/components/ui/hooks/useSelectedModel.ts index d73edf57f9..b7ad9e87e5 100644 --- a/webview-ui/src/components/ui/hooks/useSelectedModel.ts +++ b/webview-ui/src/components/ui/hooks/useSelectedModel.ts @@ -31,6 +31,7 @@ import { lMStudioDefaultModelInfo, opencodeGoDefaultModelInfo, kenariDefaultModelInfo, + nanoGptDefaultModelInfo, BEDROCK_1M_CONTEXT_MODEL_IDS, VERTEX_1M_CONTEXT_MODEL_IDS, isDynamicProvider, @@ -434,6 +435,15 @@ function getSelectedModel({ const info = routerModels[providerIdentifiers.kenari]?.[id] ?? kenariDefaultModelInfo return { id, info } } + case providerIdentifiers.nanogpt: { + const id = getValidatedModelId( + apiConfiguration.nanoGptModelId, + routerModels[providerIdentifiers.nanogpt], + defaultModelId, + ) + const info = routerModels[providerIdentifiers.nanogpt]?.[id] ?? nanoGptDefaultModelInfo + return { id, info } + } case providerIdentifiers.zooGateway: { const id = getValidatedModelId( apiConfiguration.zooGatewayModelId, diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index 73827b1ec1..fa5cc11d65 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -388,6 +388,25 @@ "getOpencodeGoApiKey": "Obtenir clau API de Opencode Go", "kenariApiKey": "Clau API de Kenari", "getKenariApiKey": "Obtenir clau API de Kenari", + "nanoGpt": { + "provider": "NanoGPT", + "apiKey": "Clau API de NanoGPT", + "getApiKey": "Obtenir clau API de NanoGPT", + "model": "Model", + "routingPreference": "Preferència d'encaminament", + "routingOptions": { + "automatic": "Automàtica", + "fastest": "Més ràpida", + "cheapest": "Més econòmica", + "lowestLatency": "Latència més baixa", + "highestThroughput": "Rendiment més alt", + "toolCapable": "Compatible amb eines", + "cacheCapable": "Compatible amb memòria cau" + }, + "automaticExplanation": "L'opció Automàtica no aplica cap sufix d'encaminament.", + "billingWarning": "Les preferències d'encaminament avançades poden utilitzar encaminament de pagament per ús i poden quedar fora de la cobertura de la subscripció, segons les regles de facturació actuals de NanoGPT.", + "routingDocs": "Consulta els detalls d'encaminament i facturació de NanoGPT" + }, "apiKeyStorageNotice": "Les claus API s'emmagatzemen de forma segura a l'Emmagatzematge Secret de VSCode", "openAiCodexRateLimits": { "title": "Usage Limits for Codex{{planLabel}}", diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index 8078037525..2cb83f7893 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -388,6 +388,25 @@ "getOpencodeGoApiKey": "Opencode Go API-Schlüssel erhalten", "kenariApiKey": "Kenari API-Schlüssel", "getKenariApiKey": "Kenari API-Schlüssel erhalten", + "nanoGpt": { + "provider": "NanoGPT", + "apiKey": "NanoGPT API-Schlüssel", + "getApiKey": "NanoGPT API-Schlüssel erhalten", + "model": "Modell", + "routingPreference": "Routing-Präferenz", + "routingOptions": { + "automatic": "Automatisch", + "fastest": "Am schnellsten", + "cheapest": "Am günstigsten", + "lowestLatency": "Niedrigste Latenz", + "highestThroughput": "Höchster Durchsatz", + "toolCapable": "Tool-fähig", + "cacheCapable": "Cache-fähig" + }, + "automaticExplanation": "Automatisch wendet kein Routing-Suffix an.", + "billingWarning": "Erweiterte Routing-Präferenzen können Pay-as-you-go-Routing verwenden und je nach den aktuellen Abrechnungsregeln von NanoGPT die Abdeckung deines Abos umgehen.", + "routingDocs": "Routing- und Abrechnungsdetails von NanoGPT anzeigen" + }, "apiKeyStorageNotice": "API-Schlüssel werden sicher im VSCode Secret Storage gespeichert", "openAiCodexRateLimits": { "title": "Usage Limits for Codex{{planLabel}}", diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index 14a7476a75..a5967792a1 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -468,6 +468,25 @@ "getOpencodeGoApiKey": "Get Opencode Go API Key", "kenariApiKey": "Kenari API Key", "getKenariApiKey": "Get Kenari API Key", + "nanoGpt": { + "provider": "NanoGPT", + "apiKey": "NanoGPT API Key", + "getApiKey": "Get NanoGPT API Key", + "model": "Model", + "routingPreference": "Routing Preference", + "routingOptions": { + "automatic": "Automatic", + "fastest": "Fastest", + "cheapest": "Cheapest", + "lowestLatency": "Lowest latency", + "highestThroughput": "Highest throughput", + "toolCapable": "Tool-capable", + "cacheCapable": "Cache-capable" + }, + "automaticExplanation": "Automatic applies no routing suffix.", + "billingWarning": "Advanced routing preferences may use pay-as-you-go routing and may bypass subscription coverage, depending on NanoGPT's current billing rules.", + "routingDocs": "View NanoGPT routing and billing details" + }, "apiKeyStorageNotice": "API keys are stored securely in VSCode's Secret Storage", "openAiCodexRateLimits": { "title": "Usage Limits for Codex{{planLabel}}", diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index e629e43b50..305a8dd5d7 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -388,6 +388,25 @@ "getOpencodeGoApiKey": "Obtener clave API de Opencode Go", "kenariApiKey": "Clave API de Kenari", "getKenariApiKey": "Obtener clave API de Kenari", + "nanoGpt": { + "provider": "NanoGPT", + "apiKey": "Clave API de NanoGPT", + "getApiKey": "Obtener clave API de NanoGPT", + "model": "Modelo", + "routingPreference": "Preferencia de enrutamiento", + "routingOptions": { + "automatic": "Automática", + "fastest": "Más rápida", + "cheapest": "Más barata", + "lowestLatency": "Menor latencia", + "highestThroughput": "Mayor rendimiento", + "toolCapable": "Compatible con herramientas", + "cacheCapable": "Compatible con caché" + }, + "automaticExplanation": "Automática no aplica ningún sufijo de enrutamiento.", + "billingWarning": "Las preferencias de enrutamiento avanzadas pueden usar enrutamiento de pago por uso y pueden omitir la cobertura de la suscripción, según las reglas de facturación actuales de NanoGPT.", + "routingDocs": "Ver detalles de enrutamiento y facturación de NanoGPT" + }, "apiKeyStorageNotice": "Las claves API se almacenan de forma segura en el Almacenamiento Secreto de VSCode", "openAiCodexRateLimits": { "title": "Usage Limits for Codex{{planLabel}}", diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index 6048e2274c..d5728833dd 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -388,6 +388,25 @@ "getOpencodeGoApiKey": "Obtenir la clé API Opencode Go", "kenariApiKey": "Clé API Kenari", "getKenariApiKey": "Obtenir la clé API Kenari", + "nanoGpt": { + "provider": "NanoGPT", + "apiKey": "Clé API NanoGPT", + "getApiKey": "Obtenir une clé API NanoGPT", + "model": "Modèle", + "routingPreference": "Préférence de routage", + "routingOptions": { + "automatic": "Automatique", + "fastest": "Le plus rapide", + "cheapest": "Le moins cher", + "lowestLatency": "Latence la plus faible", + "highestThroughput": "Débit le plus élevé", + "toolCapable": "Compatible avec les outils", + "cacheCapable": "Compatible avec le cache" + }, + "automaticExplanation": "Automatique n'applique aucun suffixe de routage.", + "billingWarning": "Les préférences de routage avancées peuvent utiliser une facturation à l'usage et peuvent contourner la couverture de l'abonnement, selon les règles de facturation actuelles de NanoGPT.", + "routingDocs": "Voir les détails de routage et de facturation de NanoGPT" + }, "apiKeyStorageNotice": "Les clés API sont stockées en toute sécurité dans le stockage sécurisé de VSCode", "openAiCodexRateLimits": { "title": "Usage Limits for Codex{{planLabel}}", diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index 28d0b8699b..3fce97a378 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -388,6 +388,25 @@ "getOpencodeGoApiKey": "Opencode Go API कुंजी प्राप्त करें", "kenariApiKey": "Kenari API कुंजी", "getKenariApiKey": "Kenari API कुंजी प्राप्त करें", + "nanoGpt": { + "provider": "NanoGPT", + "apiKey": "NanoGPT API कुंजी", + "getApiKey": "NanoGPT API कुंजी प्राप्त करें", + "model": "मॉडल", + "routingPreference": "रूटिंग प्राथमिकता", + "routingOptions": { + "automatic": "स्वचालित", + "fastest": "सबसे तेज़", + "cheapest": "सबसे सस्ता", + "lowestLatency": "सबसे कम विलंबता", + "highestThroughput": "सबसे अधिक थ्रूपुट", + "toolCapable": "टूल-सक्षम", + "cacheCapable": "कैश-सक्षम" + }, + "automaticExplanation": "स्वचालित कोई रूटिंग प्रत्यय लागू नहीं करता।", + "billingWarning": "NanoGPT के मौजूदा बिलिंग नियमों के आधार पर उन्नत रूटिंग प्राथमिकताएँ भुगतान-प्रति-उपयोग रूटिंग का उपयोग कर सकती हैं और सदस्यता कवरेज को छोड़ सकती हैं।", + "routingDocs": "NanoGPT रूटिंग और बिलिंग विवरण देखें" + }, "apiKeyStorageNotice": "API कुंजियाँ VSCode के सुरक्षित स्टोरेज में सुरक्षित रूप से संग्रहीत हैं", "openAiCodexRateLimits": { "title": "Usage Limits for Codex{{planLabel}}", diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json index bf049395c4..bcdd0ae76d 100644 --- a/webview-ui/src/i18n/locales/id/settings.json +++ b/webview-ui/src/i18n/locales/id/settings.json @@ -388,6 +388,25 @@ "getOpencodeGoApiKey": "Dapatkan Opencode Go API Key", "kenariApiKey": "Kenari API Key", "getKenariApiKey": "Dapatkan Kenari API Key", + "nanoGpt": { + "provider": "NanoGPT", + "apiKey": "NanoGPT API Key", + "getApiKey": "Dapatkan NanoGPT API Key", + "model": "Model", + "routingPreference": "Preferensi Routing", + "routingOptions": { + "automatic": "Otomatis", + "fastest": "Tercepat", + "cheapest": "Termurah", + "lowestLatency": "Latensi terendah", + "highestThroughput": "Throughput tertinggi", + "toolCapable": "Mendukung tool", + "cacheCapable": "Mendukung cache" + }, + "automaticExplanation": "Otomatis tidak menerapkan akhiran routing.", + "billingWarning": "Preferensi routing lanjutan dapat menggunakan routing bayar sesuai pemakaian dan dapat melewati cakupan langganan, tergantung aturan penagihan NanoGPT saat ini.", + "routingDocs": "Lihat detail routing dan penagihan NanoGPT" + }, "apiKeyStorageNotice": "API key disimpan dengan aman di Secret Storage VSCode", "openAiCodexRateLimits": { "title": "Usage Limits for Codex{{planLabel}}", diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index 577a74a77a..b22fb4c652 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -388,6 +388,25 @@ "getOpencodeGoApiKey": "Ottieni chiave API Opencode Go", "kenariApiKey": "Chiave API Kenari", "getKenariApiKey": "Ottieni chiave API Kenari", + "nanoGpt": { + "provider": "NanoGPT", + "apiKey": "Chiave API NanoGPT", + "getApiKey": "Ottieni chiave API NanoGPT", + "model": "Modello", + "routingPreference": "Preferenza di routing", + "routingOptions": { + "automatic": "Automatica", + "fastest": "Più veloce", + "cheapest": "Più economica", + "lowestLatency": "Latenza più bassa", + "highestThroughput": "Throughput più alto", + "toolCapable": "Compatibile con gli strumenti", + "cacheCapable": "Compatibile con la cache" + }, + "automaticExplanation": "Automatica non applica alcun suffisso di routing.", + "billingWarning": "Le preferenze di routing avanzate possono usare il routing a consumo e possono escludere la copertura dell'abbonamento, in base alle regole di fatturazione attuali di NanoGPT.", + "routingDocs": "Visualizza i dettagli di routing e fatturazione di NanoGPT" + }, "apiKeyStorageNotice": "Le chiavi API sono memorizzate in modo sicuro nell'Archivio Segreto di VSCode", "openAiCodexRateLimits": { "title": "Usage Limits for Codex{{planLabel}}", diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index 1113ac32a6..bbdc5c8e8a 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -388,6 +388,25 @@ "getOpencodeGoApiKey": "Opencode Go APIキーを取得", "kenariApiKey": "Kenari APIキー", "getKenariApiKey": "Kenari APIキーを取得", + "nanoGpt": { + "provider": "NanoGPT", + "apiKey": "NanoGPT APIキー", + "getApiKey": "NanoGPT APIキーを取得", + "model": "モデル", + "routingPreference": "ルーティング設定", + "routingOptions": { + "automatic": "自動", + "fastest": "最速", + "cheapest": "最安", + "lowestLatency": "最低レイテンシ", + "highestThroughput": "最高スループット", + "toolCapable": "ツール対応", + "cacheCapable": "キャッシュ対応" + }, + "automaticExplanation": "自動ではルーティングサフィックスを適用しません。", + "billingWarning": "高度なルーティング設定では従量課金ルーティングが使用され、NanoGPTの現在の請求ルールによってはサブスクリプションの対象外になる場合があります。", + "routingDocs": "NanoGPTのルーティングと請求の詳細を表示" + }, "apiKeyStorageNotice": "APIキーはVSCodeのシークレットストレージに安全に保存されます", "openAiCodexRateLimits": { "title": "Usage Limits for Codex{{planLabel}}", diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index 27e8493bd4..c2062a5335 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -388,6 +388,25 @@ "getOpencodeGoApiKey": "Opencode Go API 키 받기", "kenariApiKey": "Kenari API 키", "getKenariApiKey": "Kenari API 키 받기", + "nanoGpt": { + "provider": "NanoGPT", + "apiKey": "NanoGPT API 키", + "getApiKey": "NanoGPT API 키 받기", + "model": "모델", + "routingPreference": "라우팅 기본 설정", + "routingOptions": { + "automatic": "자동", + "fastest": "가장 빠름", + "cheapest": "가장 저렴함", + "lowestLatency": "최저 지연 시간", + "highestThroughput": "최고 처리량", + "toolCapable": "도구 지원", + "cacheCapable": "캐시 지원" + }, + "automaticExplanation": "자동은 라우팅 접미사를 적용하지 않습니다.", + "billingWarning": "고급 라우팅 기본 설정은 사용량 기반 라우팅을 사용할 수 있으며 NanoGPT의 현재 결제 규칙에 따라 구독 범위를 벗어날 수 있습니다.", + "routingDocs": "NanoGPT 라우팅 및 결제 세부 정보 보기" + }, "apiKeyStorageNotice": "API 키는 VSCode의 보안 저장소에 안전하게 저장됩니다", "openAiCodexRateLimits": { "title": "Usage Limits for Codex{{planLabel}}", diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json index 394cdd48f2..cf148f5617 100644 --- a/webview-ui/src/i18n/locales/nl/settings.json +++ b/webview-ui/src/i18n/locales/nl/settings.json @@ -388,6 +388,25 @@ "getOpencodeGoApiKey": "Opencode Go API-sleutel ophalen", "kenariApiKey": "Kenari API-sleutel", "getKenariApiKey": "Kenari API-sleutel ophalen", + "nanoGpt": { + "provider": "NanoGPT", + "apiKey": "NanoGPT API-sleutel", + "getApiKey": "NanoGPT API-sleutel ophalen", + "model": "Model", + "routingPreference": "Routeringsvoorkeur", + "routingOptions": { + "automatic": "Automatisch", + "fastest": "Snelste", + "cheapest": "Goedkoopste", + "lowestLatency": "Laagste latentie", + "highestThroughput": "Hoogste doorvoer", + "toolCapable": "Geschikt voor tools", + "cacheCapable": "Geschikt voor cache" + }, + "automaticExplanation": "Automatisch past geen routeringsachtervoegsel toe.", + "billingWarning": "Geavanceerde routeringsvoorkeuren kunnen betalen-per-gebruik-routering gebruiken en kunnen, afhankelijk van de huidige factureringsregels van NanoGPT, buiten je abonnement vallen.", + "routingDocs": "Routerings- en factureringsdetails van NanoGPT bekijken" + }, "apiKeyStorageNotice": "API-sleutels worden veilig opgeslagen in de geheime opslag van VSCode", "openAiCodexRateLimits": { "title": "Usage Limits for Codex{{planLabel}}", diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index 864e4ffde1..ace780f529 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -388,6 +388,25 @@ "getOpencodeGoApiKey": "Uzyskaj klucz API Opencode Go", "kenariApiKey": "Klucz API Kenari", "getKenariApiKey": "Uzyskaj klucz API Kenari", + "nanoGpt": { + "provider": "NanoGPT", + "apiKey": "Klucz API NanoGPT", + "getApiKey": "Uzyskaj klucz API NanoGPT", + "model": "Model", + "routingPreference": "Preferencja routingu", + "routingOptions": { + "automatic": "Automatyczny", + "fastest": "Najszybszy", + "cheapest": "Najtańszy", + "lowestLatency": "Najniższe opóźnienie", + "highestThroughput": "Najwyższa przepustowość", + "toolCapable": "Obsługa narzędzi", + "cacheCapable": "Obsługa pamięci podręcznej" + }, + "automaticExplanation": "Automatyczny nie dodaje sufiksu routingu.", + "billingWarning": "Zaawansowane preferencje routingu mogą używać rozliczeń za użycie i mogą omijać zakres subskrypcji, zależnie od aktualnych zasad rozliczeń NanoGPT.", + "routingDocs": "Zobacz szczegóły routingu i rozliczeń NanoGPT" + }, "apiKeyStorageNotice": "Klucze API są bezpiecznie przechowywane w Tajnym Magazynie VSCode", "openAiCodexRateLimits": { "title": "Usage Limits for Codex{{planLabel}}", diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index a1948a0218..446aa8ac02 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -388,6 +388,25 @@ "getOpencodeGoApiKey": "Obter chave API do Opencode Go", "kenariApiKey": "Chave API do Kenari", "getKenariApiKey": "Obter chave API do Kenari", + "nanoGpt": { + "provider": "NanoGPT", + "apiKey": "Chave API do NanoGPT", + "getApiKey": "Obter chave API do NanoGPT", + "model": "Modelo", + "routingPreference": "Preferência de roteamento", + "routingOptions": { + "automatic": "Automática", + "fastest": "Mais rápida", + "cheapest": "Mais barata", + "lowestLatency": "Menor latência", + "highestThroughput": "Maior throughput", + "toolCapable": "Compatível com ferramentas", + "cacheCapable": "Compatível com cache" + }, + "automaticExplanation": "Automática não aplica nenhum sufixo de roteamento.", + "billingWarning": "Preferências de roteamento avançadas podem usar cobrança por uso e podem ignorar a cobertura da assinatura, dependendo das regras de cobrança atuais do NanoGPT.", + "routingDocs": "Ver detalhes de roteamento e cobrança do NanoGPT" + }, "apiKeyStorageNotice": "As chaves de API são armazenadas com segurança no Armazenamento Secreto do VSCode", "openAiCodexRateLimits": { "title": "Usage Limits for Codex{{planLabel}}", diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index f36fe62539..f2719ad06e 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -388,6 +388,25 @@ "getOpencodeGoApiKey": "Получить ключ API Opencode Go", "kenariApiKey": "Ключ API Kenari", "getKenariApiKey": "Получить ключ API Kenari", + "nanoGpt": { + "provider": "NanoGPT", + "apiKey": "Ключ API NanoGPT", + "getApiKey": "Получить ключ API NanoGPT", + "model": "Модель", + "routingPreference": "Предпочтение маршрутизации", + "routingOptions": { + "automatic": "Автоматически", + "fastest": "Самая быстрая", + "cheapest": "Самая дешёвая", + "lowestLatency": "Минимальная задержка", + "highestThroughput": "Максимальная пропускная способность", + "toolCapable": "С поддержкой инструментов", + "cacheCapable": "С поддержкой кеша" + }, + "automaticExplanation": "Автоматический режим не применяет суффикс маршрутизации.", + "billingWarning": "Расширенные предпочтения маршрутизации могут использовать оплату по факту использования и могут обходить покрытие подписки в зависимости от текущих правил оплаты NanoGPT.", + "routingDocs": "Подробнее о маршрутизации и оплате NanoGPT" + }, "apiKeyStorageNotice": "API-ключи хранятся безопасно в Secret Storage VSCode", "openAiCodexRateLimits": { "title": "Usage Limits for Codex{{planLabel}}", diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index 9099677679..08374b6d20 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -388,6 +388,25 @@ "getOpencodeGoApiKey": "Opencode Go API Anahtarı Al", "kenariApiKey": "Kenari API Anahtarı", "getKenariApiKey": "Kenari API Anahtarı Al", + "nanoGpt": { + "provider": "NanoGPT", + "apiKey": "NanoGPT API Anahtarı", + "getApiKey": "NanoGPT API Anahtarı Al", + "model": "Model", + "routingPreference": "Yönlendirme Tercihi", + "routingOptions": { + "automatic": "Otomatik", + "fastest": "En hızlı", + "cheapest": "En ucuz", + "lowestLatency": "En düşük gecikme", + "highestThroughput": "En yüksek verim", + "toolCapable": "Araç destekli", + "cacheCapable": "Önbellek destekli" + }, + "automaticExplanation": "Otomatik, yönlendirme son eki uygulamaz.", + "billingWarning": "Gelişmiş yönlendirme tercihleri kullanıma göre ödeme yönlendirmesini kullanabilir ve NanoGPT'nin güncel faturalandırma kurallarına bağlı olarak abonelik kapsamını atlayabilir.", + "routingDocs": "NanoGPT yönlendirme ve faturalandırma ayrıntılarını görüntüle" + }, "apiKeyStorageNotice": "API anahtarları VSCode'un Gizli Depolamasında güvenli bir şekilde saklanır", "openAiCodexRateLimits": { "title": "Usage Limits for Codex{{planLabel}}", diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index c66b236165..a8611ca687 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -388,6 +388,25 @@ "getOpencodeGoApiKey": "Lấy khóa API Opencode Go", "kenariApiKey": "Khóa API Kenari", "getKenariApiKey": "Lấy khóa API Kenari", + "nanoGpt": { + "provider": "NanoGPT", + "apiKey": "Khóa API NanoGPT", + "getApiKey": "Lấy khóa API NanoGPT", + "model": "Mô hình", + "routingPreference": "Tùy chọn định tuyến", + "routingOptions": { + "automatic": "Tự động", + "fastest": "Nhanh nhất", + "cheapest": "Rẻ nhất", + "lowestLatency": "Độ trễ thấp nhất", + "highestThroughput": "Thông lượng cao nhất", + "toolCapable": "Hỗ trợ công cụ", + "cacheCapable": "Hỗ trợ bộ nhớ đệm" + }, + "automaticExplanation": "Tự động không áp dụng hậu tố định tuyến.", + "billingWarning": "Tùy chọn định tuyến nâng cao có thể sử dụng định tuyến trả theo mức dùng và có thể không thuộc phạm vi gói đăng ký, tùy theo quy tắc thanh toán hiện tại của NanoGPT.", + "routingDocs": "Xem chi tiết định tuyến và thanh toán NanoGPT" + }, "apiKeyStorageNotice": "Khóa API được lưu trữ an toàn trong Bộ lưu trữ bí mật của VSCode", "openAiCodexRateLimits": { "title": "Usage Limits for Codex{{planLabel}}", diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index 22742e0e0e..9f3913e872 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -388,6 +388,25 @@ "getOpencodeGoApiKey": "获取 Opencode Go API 密钥", "kenariApiKey": "Kenari API 密钥", "getKenariApiKey": "获取 Kenari API 密钥", + "nanoGpt": { + "provider": "NanoGPT", + "apiKey": "NanoGPT API 密钥", + "getApiKey": "获取 NanoGPT API 密钥", + "model": "模型", + "routingPreference": "路由偏好", + "routingOptions": { + "automatic": "自动", + "fastest": "最快", + "cheapest": "最便宜", + "lowestLatency": "最低延迟", + "highestThroughput": "最高吞吐量", + "toolCapable": "支持工具", + "cacheCapable": "支持缓存" + }, + "automaticExplanation": "自动模式不应用路由后缀。", + "billingWarning": "高级路由偏好可能使用按用量付费路由,并且根据 NanoGPT 当前的计费规则,可能不在订阅范围内。", + "routingDocs": "查看 NanoGPT 路由和计费详情" + }, "apiKeyStorageNotice": "API 密钥安全存储在 VSCode 的密钥存储中", "openAiCodexRateLimits": { "title": "Usage Limits for Codex{{planLabel}}", diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index 4255a2e697..80d0d18735 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -415,6 +415,25 @@ "getOpencodeGoApiKey": "取得 Opencode Go API 金鑰", "kenariApiKey": "Kenari API 金鑰", "getKenariApiKey": "取得 Kenari API 金鑰", + "nanoGpt": { + "provider": "NanoGPT", + "apiKey": "NanoGPT API 金鑰", + "getApiKey": "取得 NanoGPT API 金鑰", + "model": "模型", + "routingPreference": "路由偏好", + "routingOptions": { + "automatic": "自動", + "fastest": "最快", + "cheapest": "最便宜", + "lowestLatency": "最低延遲", + "highestThroughput": "最高吞吐量", + "toolCapable": "支援工具", + "cacheCapable": "支援快取" + }, + "automaticExplanation": "自動模式不套用路由後綴。", + "billingWarning": "進階路由偏好可能使用隨用隨付路由,並且根據 NanoGPT 目前的計費規則,可能不在訂閱涵蓋範圍內。", + "routingDocs": "查看 NanoGPT 路由與計費詳細資訊" + }, "apiKeyStorageNotice": "API 金鑰會安全地儲存在 VS Code 的 Secret Storage 中", "openAiCodexRateLimits": { "title": "Codex 用量限制{{planLabel}}", diff --git a/webview-ui/src/utils/__tests__/validate.spec.ts b/webview-ui/src/utils/__tests__/validate.spec.ts index 8e2e223977..6535e3ba61 100644 --- a/webview-ui/src/utils/__tests__/validate.spec.ts +++ b/webview-ui/src/utils/__tests__/validate.spec.ts @@ -58,6 +58,7 @@ describe("Model Validation Functions", () => { deepseek: {}, "opencode-go": {}, kenari: {}, + nanogpt: {}, "zoo-gateway": {}, "kimi-code": {}, moonshot: {}, @@ -295,6 +296,36 @@ describe("Model Validation Functions", () => { }) }) + describe("NanoGPT validation", () => { + it("returns an apiKey error when the NanoGPT API key is missing", () => { + const config: ProviderSettings = { + apiProvider: providerIdentifiers.nanogpt, + nanoGptModelId: "openai/model", + } + + expect(validateApiConfiguration(config, mockRouterModels)).toBe("settings:validation.apiKey") + }) + + it("returns a modelId error when the NanoGPT model is missing", () => { + const config: ProviderSettings = { + apiProvider: providerIdentifiers.nanogpt, + nanoGptApiKey: "valid-key", + } + + expect(validateApiConfiguration(config, mockRouterModels)).toBe("settings:validation.modelId") + }) + + it("accepts a NanoGPT API key and selected model", () => { + const config: ProviderSettings = { + apiProvider: providerIdentifiers.nanogpt, + nanoGptApiKey: "valid-key", + nanoGptModelId: "openai/model", + } + + expect(validateApiConfiguration(config, mockRouterModels)).toBeUndefined() + }) + }) + describe("Friendli validation", () => { it("returns an apiKey error when the Friendli API key is missing", () => { const config: ProviderSettings = { diff --git a/webview-ui/src/utils/validate.ts b/webview-ui/src/utils/validate.ts index e946906e10..4174e8f821 100644 --- a/webview-ui/src/utils/validate.ts +++ b/webview-ui/src/utils/validate.ts @@ -143,6 +143,11 @@ function validateModelsAndKeysProvided( return i18next.t("settings:validation.apiKey") } break + case providerIdentifiers.nanogpt: + if (!apiConfiguration.nanoGptApiKey) { + return i18next.t("settings:validation.apiKey") + } + break case providerIdentifiers.zooGateway: if (!apiConfiguration.zooSessionToken && !zooCodeIsAuthenticated) { return i18next.t("settings:validation.zooGatewaySignIn") From 732651f3a799f03791103a7d86378f7c577fbb93 Mon Sep 17 00:00:00 2001 From: Rafael Oliveira <70116258+Rafael-Silva-Oliveira@users.noreply.github.com> Date: Sat, 15 Aug 2026 00:12:18 +0000 Subject: [PATCH 12/66] fix(config): use zoo-code-settings.json for settings export/import (#1177) The settings export and import dialogs still defaulted to the legacy "roo-code-settings.json" filename, as did the autoImportSettingsPath example in the localized setting descriptions. Rename the default to "zoo-code-settings.json" to match the Zoo Code branding. This only changes the default filename suggested in the save/open dialogs; existing files with any name can still be imported. --- .../config/__tests__/importExport.spec.ts | 38 +++++++++---------- src/core/config/importExport.ts | 4 +- src/package.nls.ca.json | 2 +- src/package.nls.de.json | 2 +- src/package.nls.es.json | 2 +- src/package.nls.fr.json | 2 +- src/package.nls.hi.json | 2 +- src/package.nls.id.json | 2 +- src/package.nls.it.json | 2 +- src/package.nls.ja.json | 2 +- src/package.nls.json | 2 +- src/package.nls.ko.json | 2 +- src/package.nls.nl.json | 2 +- src/package.nls.pl.json | 2 +- src/package.nls.pt-BR.json | 2 +- src/package.nls.ru.json | 2 +- src/package.nls.tr.json | 2 +- src/package.nls.vi.json | 2 +- src/package.nls.zh-CN.json | 2 +- src/package.nls.zh-TW.json | 2 +- 20 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/core/config/__tests__/importExport.spec.ts b/src/core/config/__tests__/importExport.spec.ts index 94cbc934cf..78e6afca75 100644 --- a/src/core/config/__tests__/importExport.spec.ts +++ b/src/core/config/__tests__/importExport.spec.ts @@ -1363,7 +1363,7 @@ describe("importExport", () => { it("should export settings to the selected file location", async () => { ;(vscode.window.showSaveDialog as Mock).mockResolvedValue({ - fsPath: "/mock/path/roo-code-settings.json", + fsPath: "/mock/path/zoo-code-settings.json", }) const mockProviderProfiles = { @@ -1390,7 +1390,7 @@ describe("importExport", () => { expect(mockContextProxy.export).toHaveBeenCalled() expect(fs.mkdir).toHaveBeenCalledWith("/mock/path", { recursive: true }) - expect(safeWriteJson).toHaveBeenCalledWith("/mock/path/roo-code-settings.json", { + expect(safeWriteJson).toHaveBeenCalledWith("/mock/path/zoo-code-settings.json", { providerProfiles: mockProviderProfiles, globalSettings: mockGlobalSettings, }) @@ -1398,7 +1398,7 @@ describe("importExport", () => { it("should include globalSettings when allowedMaxRequests is null", async () => { ;(vscode.window.showSaveDialog as Mock).mockResolvedValue({ - fsPath: "/mock/path/roo-code-settings.json", + fsPath: "/mock/path/zoo-code-settings.json", }) const mockProviderProfiles = { @@ -1422,7 +1422,7 @@ describe("importExport", () => { contextProxy: mockContextProxy, }) - expect(safeWriteJson).toHaveBeenCalledWith("/mock/path/roo-code-settings.json", { + expect(safeWriteJson).toHaveBeenCalledWith("/mock/path/zoo-code-settings.json", { providerProfiles: mockProviderProfiles, globalSettings: mockGlobalSettings, }) @@ -1430,7 +1430,7 @@ describe("importExport", () => { it("should handle errors during the export process", async () => { ;(vscode.window.showSaveDialog as Mock).mockResolvedValue({ - fsPath: "/mock/path/roo-code-settings.json", + fsPath: "/mock/path/zoo-code-settings.json", }) mockProviderSettingsManager.export.mockResolvedValue({ @@ -1460,7 +1460,7 @@ describe("importExport", () => { it("should handle errors during directory creation", async () => { ;(vscode.window.showSaveDialog as Mock).mockResolvedValue({ - fsPath: "/mock/path/roo-code-settings.json", + fsPath: "/mock/path/zoo-code-settings.json", }) mockProviderSettingsManager.export.mockResolvedValue({ @@ -1497,13 +1497,13 @@ describe("importExport", () => { defaultUri: expect.anything(), }) - expect(vscode.Uri.file).toHaveBeenCalledWith(path.join("/mock/home", "Downloads", "roo-code-settings.json")) + expect(vscode.Uri.file).toHaveBeenCalledWith(path.join("/mock/home", "Downloads", "zoo-code-settings.json")) }) describe("codebase indexing export", () => { it("should export correct base URL for OpenAI Compatible provider", async () => { ;(vscode.window.showSaveDialog as Mock).mockResolvedValue({ - fsPath: "/mock/path/roo-code-settings.json", + fsPath: "/mock/path/zoo-code-settings.json", }) const mockProviderProfiles = { @@ -1545,7 +1545,7 @@ describe("importExport", () => { contextProxy: mockContextProxy, }) - expect(safeWriteJson).toHaveBeenCalledWith("/mock/path/roo-code-settings.json", { + expect(safeWriteJson).toHaveBeenCalledWith("/mock/path/zoo-code-settings.json", { providerProfiles: mockProviderProfiles, globalSettings: mockGlobalSettings, }) @@ -1553,7 +1553,7 @@ describe("importExport", () => { it("should export model dimension for OpenAI Compatible provider", async () => { ;(vscode.window.showSaveDialog as Mock).mockResolvedValue({ - fsPath: "/mock/path/roo-code-settings.json", + fsPath: "/mock/path/zoo-code-settings.json", }) const mockProviderProfiles = { @@ -1600,7 +1600,7 @@ describe("importExport", () => { it("should not mix settings between different providers", async () => { ;(vscode.window.showSaveDialog as Mock).mockResolvedValue({ - fsPath: "/mock/path/roo-code-settings.json", + fsPath: "/mock/path/zoo-code-settings.json", }) const mockProviderProfiles = { @@ -1660,7 +1660,7 @@ describe("importExport", () => { it("should handle missing provider-specific settings gracefully", async () => { ;(vscode.window.showSaveDialog as Mock).mockResolvedValue({ - fsPath: "/mock/path/roo-code-settings.json", + fsPath: "/mock/path/zoo-code-settings.json", }) const mockProviderProfiles = { @@ -1698,7 +1698,7 @@ describe("importExport", () => { }) // Should not throw an error and should preserve original settings - expect(safeWriteJson).toHaveBeenCalledWith("/mock/path/roo-code-settings.json", { + expect(safeWriteJson).toHaveBeenCalledWith("/mock/path/zoo-code-settings.json", { providerProfiles: mockProviderProfiles, globalSettings: mockGlobalSettings, // Should remain unchanged }) @@ -1706,7 +1706,7 @@ describe("importExport", () => { it("should maintain backward compatibility with existing exports", async () => { ;(vscode.window.showSaveDialog as Mock).mockResolvedValue({ - fsPath: "/mock/path/roo-code-settings.json", + fsPath: "/mock/path/zoo-code-settings.json", }) const mockProviderProfiles = { @@ -1741,7 +1741,7 @@ describe("importExport", () => { }) // Should not modify settings for non-openai-compatible providers - expect(safeWriteJson).toHaveBeenCalledWith("/mock/path/roo-code-settings.json", { + expect(safeWriteJson).toHaveBeenCalledWith("/mock/path/zoo-code-settings.json", { providerProfiles: mockProviderProfiles, globalSettings: mockGlobalSettings, // Should remain unchanged }) @@ -1749,7 +1749,7 @@ describe("importExport", () => { it("should handle missing current provider gracefully", async () => { ;(vscode.window.showSaveDialog as Mock).mockResolvedValue({ - fsPath: "/mock/path/roo-code-settings.json", + fsPath: "/mock/path/zoo-code-settings.json", }) const mockProviderProfiles = { @@ -1786,7 +1786,7 @@ describe("importExport", () => { }) // Should not throw an error and should preserve original settings - expect(safeWriteJson).toHaveBeenCalledWith("/mock/path/roo-code-settings.json", { + expect(safeWriteJson).toHaveBeenCalledWith("/mock/path/zoo-code-settings.json", { providerProfiles: mockProviderProfiles, globalSettings: mockGlobalSettings, // Should remain unchanged }) @@ -2459,7 +2459,7 @@ describe("importExport", () => { // when the OpenAI Compatible settings are stored in global state via contextProxy ;(vscode.window.showSaveDialog as Mock).mockResolvedValue({ - fsPath: "/mock/path/roo-code-settings.json", + fsPath: "/mock/path/zoo-code-settings.json", }) // Set up provider profiles - note that the OpenAI Compatible provider does NOT have @@ -2533,7 +2533,7 @@ describe("importExport", () => { // Using deepseek provider which uses apiModelId and has supportsReasoningBudget: false ;(vscode.window.showSaveDialog as Mock).mockResolvedValue({ - fsPath: "/mock/path/roo-code-settings.json", + fsPath: "/mock/path/zoo-code-settings.json", }) // Use a real ProviderSettingsManager instance to test the actual filtering logic diff --git a/src/core/config/importExport.ts b/src/core/config/importExport.ts index b5fd5fdf98..645187065b 100644 --- a/src/core/config/importExport.ts +++ b/src/core/config/importExport.ts @@ -270,7 +270,7 @@ export async function importSettingsFromPath( */ export const importSettings = async ({ providerSettingsManager, contextProxy, customModesManager }: ImportOptions) => { // Use the last export path as a sensible default, falling back to Downloads - const defaultUri = resolveDefaultSaveUri(contextProxy, "lastSettingsExportPath", "roo-code-settings.json", { + const defaultUri = resolveDefaultSaveUri(contextProxy, "lastSettingsExportPath", "zoo-code-settings.json", { useWorkspace: false, fallbackDir: path.join(os.homedir(), "Downloads"), }) @@ -310,7 +310,7 @@ export const importSettingsFromFile = async ( } export const exportSettings = async ({ providerSettingsManager, contextProxy }: ExportOptions) => { - const defaultUri = await resolveDefaultSaveUri(contextProxy, "lastSettingsExportPath", "roo-code-settings.json", { + const defaultUri = await resolveDefaultSaveUri(contextProxy, "lastSettingsExportPath", "zoo-code-settings.json", { useWorkspace: false, fallbackDir: path.join(os.homedir(), "Downloads"), }) diff --git a/src/package.nls.ca.json b/src/package.nls.ca.json index 6ddaf181b4..b1397adf71 100644 --- a/src/package.nls.ca.json +++ b/src/package.nls.ca.json @@ -36,7 +36,7 @@ "settings.vsCodeLmModelSelector.family.description": "La família del model de llenguatge (p. ex. gpt-4)", "settings.customStoragePath.description": "Ruta d'emmagatzematge personalitzada. Deixeu-la buida per utilitzar la ubicació predeterminada. Admet rutes absolutes (p. ex. 'D:\\ZooCodeStorage')", "settings.enableCodeActions.description": "Habilitar correccions ràpides de Zoo Code.", - "settings.autoImportSettingsPath.description": "Ruta a un fitxer de configuració de ZooCode per importar automàticament en iniciar l'extensió. Admet rutes absolutes i rutes relatives al directori d'inici (per exemple, '~/Documents/roo-code-settings.json'). Deixeu-ho en blanc per desactivar la importació automàtica.", + "settings.autoImportSettingsPath.description": "Ruta a un fitxer de configuració de ZooCode per importar automàticament en iniciar l'extensió. Admet rutes absolutes i rutes relatives al directori d'inici (per exemple, '~/Documents/zoo-code-settings.json'). Deixeu-ho en blanc per desactivar la importació automàtica.", "settings.maximumIndexedFilesForFileSearch.description": "Nombre màxim de fitxers per indexar per a la funció de cerca de fitxers @. Valors més alts proporcionen millors resultats de cerca en projectes grans però poden utilitzar més memòria. Per defecte: 10.000.", "settings.useAgentRules.description": "Activa la càrrega de fitxers AGENTS.md per a regles específiques de l'agent (vegeu https://agent-rules.org/)", "settings.apiRequestTimeout.description": "Temps d'espera de resposta API (segons, predeterminat: 600, rang: 1–3600). Es recomanen valors més alts per a proveïdors locals. Proveïdors no admesos: Amazon Bedrock, Google Gemini(directly or through the Vertex AI platform), Mistral, Moonshot, Ollama, Poe, VS Code LM API.", diff --git a/src/package.nls.de.json b/src/package.nls.de.json index 4c8eccb293..b4cd8440ab 100644 --- a/src/package.nls.de.json +++ b/src/package.nls.de.json @@ -36,7 +36,7 @@ "settings.vsCodeLmModelSelector.family.description": "Die Familie des Sprachmodells (z.B. gpt-4)", "settings.customStoragePath.description": "Benutzerdefinierter Speicherpfad. Leer lassen, um den Standardspeicherort zu verwenden. Unterstützt absolute Pfade (z.B. 'D:\\ZooCodeStorage')", "settings.enableCodeActions.description": "Zoo Code Schnelle Problembehebung aktivieren.", - "settings.autoImportSettingsPath.description": "Pfad zu einer ZooCode-Konfigurationsdatei, die beim Start der Erweiterung automatisch importiert wird. Unterstützt absolute Pfade und Pfade relativ zum Home-Verzeichnis (z.B. '~/Documents/roo-code-settings.json'). Leer lassen, um den automatischen Import zu deaktivieren.", + "settings.autoImportSettingsPath.description": "Pfad zu einer ZooCode-Konfigurationsdatei, die beim Start der Erweiterung automatisch importiert wird. Unterstützt absolute Pfade und Pfade relativ zum Home-Verzeichnis (z.B. '~/Documents/zoo-code-settings.json'). Leer lassen, um den automatischen Import zu deaktivieren.", "settings.maximumIndexedFilesForFileSearch.description": "Maximale Anzahl der zu indizierenden Dateien für die @-Dateisuchfunktion. Höhere Werte bieten bessere Suchergebnisse in großen Projekten, können aber mehr Speicher verbrauchen. Standard: 10.000.", "settings.useAgentRules.description": "Aktiviert das Laden von AGENTS.md-Dateien für agentenspezifische Regeln (siehe https://agent-rules.org/)", "settings.apiRequestTimeout.description": "API-Antwort-Timeout (Sekunden, Standard: 600, Bereich: 1–3600). Höhere Werte werden für lokale Anbieter empfohlen. Nicht unterstützte Anbieter: Amazon Bedrock, Google Gemini(directly or through the Vertex AI platform), Mistral, Moonshot, Ollama, Poe, VS Code LM API.", diff --git a/src/package.nls.es.json b/src/package.nls.es.json index 11a705880b..1d86a70980 100644 --- a/src/package.nls.es.json +++ b/src/package.nls.es.json @@ -36,7 +36,7 @@ "settings.vsCodeLmModelSelector.family.description": "La familia del modelo de lenguaje (ej. gpt-4)", "settings.customStoragePath.description": "Ruta de almacenamiento personalizada. Dejar vacío para usar la ubicación predeterminada. Admite rutas absolutas (ej. 'D:\\ZooCodeStorage')", "settings.enableCodeActions.description": "Habilitar correcciones rápidas de Zoo Code.", - "settings.autoImportSettingsPath.description": "Ruta a un archivo de configuración de ZooCode para importar automáticamente al iniciar la extensión. Admite rutas absolutas y rutas relativas al directorio de inicio (por ejemplo, '~/Documents/roo-code-settings.json'). Dejar vacío para desactivar la importación automática.", + "settings.autoImportSettingsPath.description": "Ruta a un archivo de configuración de ZooCode para importar automáticamente al iniciar la extensión. Admite rutas absolutas y rutas relativas al directorio de inicio (por ejemplo, '~/Documents/zoo-code-settings.json'). Dejar vacío para desactivar la importación automática.", "settings.maximumIndexedFilesForFileSearch.description": "Número máximo de archivos a indexar para la función de búsqueda de archivos @. Valores más altos proporcionan mejores resultados de búsqueda en proyectos grandes pero pueden usar más memoria. Por defecto: 10.000.", "settings.useAgentRules.description": "Habilita la carga de archivos AGENTS.md para reglas específicas del agente (ver https://agent-rules.org/)", "settings.apiRequestTimeout.description": "Tiempo de espera de respuesta API (segundos, predeterminado: 600, rango: 1–3600). Se recomiendan valores más altos para proveedores locales. Proveedores no compatibles: Amazon Bedrock, Google Gemini(directly or through the Vertex AI platform), Mistral, Moonshot, Ollama, Poe, VS Code LM API.", diff --git a/src/package.nls.fr.json b/src/package.nls.fr.json index 573350bc9a..85207df975 100644 --- a/src/package.nls.fr.json +++ b/src/package.nls.fr.json @@ -36,7 +36,7 @@ "settings.vsCodeLmModelSelector.family.description": "La famille du modèle de langage (ex: gpt-4)", "settings.customStoragePath.description": "Chemin de stockage personnalisé. Laisser vide pour utiliser l'emplacement par défaut. Prend en charge les chemins absolus (ex: 'D:\\ZooCodeStorage')", "settings.enableCodeActions.description": "Activer les correctifs rapides de Zoo Code.", - "settings.autoImportSettingsPath.description": "Chemin d'accès à un fichier de configuration ZooCode à importer automatiquement au démarrage de l'extension. Prend en charge les chemins absolus et les chemins relatifs au répertoire de base (par exemple, '~/Documents/roo-code-settings.json'). Laisser vide pour désactiver l'importation automatique.", + "settings.autoImportSettingsPath.description": "Chemin d'accès à un fichier de configuration ZooCode à importer automatiquement au démarrage de l'extension. Prend en charge les chemins absolus et les chemins relatifs au répertoire de base (par exemple, '~/Documents/zoo-code-settings.json'). Laisser vide pour désactiver l'importation automatique.", "settings.maximumIndexedFilesForFileSearch.description": "Nombre maximum de fichiers à indexer pour la fonctionnalité de recherche de fichiers @. Des valeurs plus élevées offrent de meilleurs résultats de recherche dans les grands projets mais peuvent consommer plus de mémoire. Par défaut : 10 000.", "settings.useAgentRules.description": "Activer le chargement des fichiers AGENTS.md pour les règles spécifiques à l'agent (voir https://agent-rules.org/)", "settings.apiRequestTimeout.description": "Délai d'attente des réponses API (secondes, défaut : 600, plage : 1–3600). Des valeurs plus élevées sont recommandées pour les fournisseurs locaux. Fournisseurs non pris en charge : Amazon Bedrock, Google Gemini(directly or through the Vertex AI platform), Mistral, Moonshot, Ollama, Poe, VS Code LM API.", diff --git a/src/package.nls.hi.json b/src/package.nls.hi.json index 8135af2ab3..f4f283bb65 100644 --- a/src/package.nls.hi.json +++ b/src/package.nls.hi.json @@ -36,7 +36,7 @@ "settings.vsCodeLmModelSelector.family.description": "भाषा मॉडल का परिवार (उदा. gpt-4)", "settings.customStoragePath.description": "कस्टम स्टोरेज पाथ। डिफ़ॉल्ट स्थान का उपयोग करने के लिए खाली छोड़ें। पूर्ण पथ का समर्थन करता है (उदा. 'D:\\ZooCodeStorage')", "settings.enableCodeActions.description": "Zoo Code त्वरित सुधार सक्षम करें", - "settings.autoImportSettingsPath.description": "ZooCode कॉन्फ़िगरेशन फ़ाइल का पथ जिसे एक्सटेंशन स्टार्टअप पर स्वचालित रूप से आयात किया जाएगा। होम डायरेक्टरी के सापेक्ष पूर्ण पथ और पथों का समर्थन करता है (उदाहरण के लिए '~/Documents/roo-code-settings.json')। ऑटो-इंपोर्ट को अक्षम करने के लिए खाली छोड़ दें।", + "settings.autoImportSettingsPath.description": "ZooCode कॉन्फ़िगरेशन फ़ाइल का पथ जिसे एक्सटेंशन स्टार्टअप पर स्वचालित रूप से आयात किया जाएगा। होम डायरेक्टरी के सापेक्ष पूर्ण पथ और पथों का समर्थन करता है (उदाहरण के लिए '~/Documents/zoo-code-settings.json')। ऑटो-इंपोर्ट को अक्षम करने के लिए खाली छोड़ दें।", "settings.maximumIndexedFilesForFileSearch.description": "@ फ़ाइल खोज सुविधा के लिए अनुक्रमित करने के लिए फ़ाइलों की अधिकतम संख्या। उच्च मान बड़ी परियोजनाओं में बेहतर खोज परिणाम प्रदान करते हैं लेकिन अधिक मेमोरी का उपयोग कर सकते हैं। डिफ़ॉल्ट: 10,000।", "settings.useAgentRules.description": "एजेंट-विशिष्ट नियमों के लिए AGENTS.md फ़ाइलों को लोड करना सक्षम करें (देखें https://agent-rules.org/)", "settings.apiRequestTimeout.description": "API प्रतिक्रिया टाइमआउट (सेकंड, डिफ़ॉल्ट: 600, रेंज: 1–3600)। स्थानीय प्रदाताओं के लिए उच्च मान अनुशंसित हैं। असमर्थित प्रदाता: Amazon Bedrock, Google Gemini(directly or through the Vertex AI platform), Mistral, Moonshot, Ollama, Poe, VS Code LM API।", diff --git a/src/package.nls.id.json b/src/package.nls.id.json index c5740ad00b..c49e54a34e 100644 --- a/src/package.nls.id.json +++ b/src/package.nls.id.json @@ -36,7 +36,7 @@ "settings.vsCodeLmModelSelector.family.description": "Keluarga dari model bahasa (misalnya gpt-4)", "settings.customStoragePath.description": "Path penyimpanan kustom. Biarkan kosong untuk menggunakan lokasi default. Mendukung path absolut (misalnya 'D:\\ZooCodeStorage')", "settings.enableCodeActions.description": "Aktifkan perbaikan cepat Zoo Code.", - "settings.autoImportSettingsPath.description": "Path ke file konfigurasi ZooCode untuk diimpor secara otomatis saat ekstensi dimulai. Mendukung path absolut dan path relatif terhadap direktori home (misalnya '~/Documents/roo-code-settings.json'). Biarkan kosong untuk menonaktifkan impor otomatis.", + "settings.autoImportSettingsPath.description": "Path ke file konfigurasi ZooCode untuk diimpor secara otomatis saat ekstensi dimulai. Mendukung path absolut dan path relatif terhadap direktori home (misalnya '~/Documents/zoo-code-settings.json'). Biarkan kosong untuk menonaktifkan impor otomatis.", "settings.maximumIndexedFilesForFileSearch.description": "Jumlah maksimum file yang akan diindeks untuk fitur pencarian file @. Nilai yang lebih besar memberikan hasil pencarian yang lebih baik di proyek besar tetapi mungkin menggunakan lebih banyak memori. Default: 10.000.", "settings.useAgentRules.description": "Aktifkan pemuatan file AGENTS.md untuk aturan khusus agen (lihat https://agent-rules.org/)", "settings.apiRequestTimeout.description": "Batas waktu respons API (detik, default: 600, rentang: 1–3600). Nilai lebih tinggi direkomendasikan untuk penyedia lokal. Penyedia tidak didukung: Amazon Bedrock, Google Gemini(directly or through the Vertex AI platform), Mistral, Moonshot, Ollama, Poe, VS Code LM API.", diff --git a/src/package.nls.it.json b/src/package.nls.it.json index ebf2167a99..2a4b95f954 100644 --- a/src/package.nls.it.json +++ b/src/package.nls.it.json @@ -36,7 +36,7 @@ "settings.vsCodeLmModelSelector.family.description": "La famiglia del modello linguistico (es. gpt-4)", "settings.customStoragePath.description": "Percorso di archiviazione personalizzato. Lasciare vuoto per utilizzare la posizione predefinita. Supporta percorsi assoluti (es. 'D:\\ZooCodeStorage')", "settings.enableCodeActions.description": "Abilita correzioni rapide di Zoo Code.", - "settings.autoImportSettingsPath.description": "Percorso di un file di configurazione di ZooCode da importare automaticamente all'avvio dell'estensione. Supporta percorsi assoluti e percorsi relativi alla directory home (ad es. '~/Documents/roo-code-settings.json'). Lasciare vuoto per disabilitare l'importazione automatica.", + "settings.autoImportSettingsPath.description": "Percorso di un file di configurazione di ZooCode da importare automaticamente all'avvio dell'estensione. Supporta percorsi assoluti e percorsi relativi alla directory home (ad es. '~/Documents/zoo-code-settings.json'). Lasciare vuoto per disabilitare l'importazione automatica.", "settings.maximumIndexedFilesForFileSearch.description": "Numero massimo di file da indicizzare per la funzionalità di ricerca file @. Valori più alti forniscono migliori risultati di ricerca in progetti grandi ma possono consumare più memoria. Predefinito: 10.000.", "settings.useAgentRules.description": "Abilita il caricamento dei file AGENTS.md per regole specifiche dell'agente (vedi https://agent-rules.org/)", "settings.apiRequestTimeout.description": "Timeout risposta API (secondi, predefinito: 600, intervallo: 1–3600). Valori più alti sono consigliati per provider locali. Provider non supportati: Amazon Bedrock, Google Gemini(directly or through the Vertex AI platform), Mistral, Moonshot, Ollama, Poe, VS Code LM API.", diff --git a/src/package.nls.ja.json b/src/package.nls.ja.json index f9daa4bb93..0f3f4a3cee 100644 --- a/src/package.nls.ja.json +++ b/src/package.nls.ja.json @@ -36,7 +36,7 @@ "settings.vsCodeLmModelSelector.family.description": "言語モデルのファミリー(例:gpt-4)", "settings.customStoragePath.description": "カスタムストレージパス。デフォルトの場所を使用する場合は空のままにします。絶対パスをサポートします(例:'D:\\ZooCodeStorage')", "settings.enableCodeActions.description": "Zoo Codeのクイック修正を有効にする。", - "settings.autoImportSettingsPath.description": "拡張機能の起動時に自動的にインポートするZooCode設定ファイルへのパス。絶対パスとホームディレクトリからの相対パスをサポートします(例:'~/Documents/roo-code-settings.json')。自動インポートを無効にするには、空のままにします。", + "settings.autoImportSettingsPath.description": "拡張機能の起動時に自動的にインポートするZooCode設定ファイルへのパス。絶対パスとホームディレクトリからの相対パスをサポートします(例:'~/Documents/zoo-code-settings.json')。自動インポートを無効にするには、空のままにします。", "settings.maximumIndexedFilesForFileSearch.description": "@ファイル検索機能のためにインデックス化するファイルの最大数。大きな値は大規模プロジェクトでより良い検索結果を提供しますが、より多くのメモリを使用する可能性があります。デフォルト: 10,000。", "settings.useAgentRules.description": "エージェント固有のルールのためにAGENTS.mdファイルの読み込みを有効にします(参照:https://agent-rules.org/)", "settings.apiRequestTimeout.description": "API応答タイムアウト(秒、デフォルト:600、範囲:1–3600)。ローカルプロバイダーには高い値を推奨します。非対応プロバイダー:Amazon Bedrock、Google Gemini(directly or through the Vertex AI platform)、Mistral、Moonshot、Ollama、Poe、VS Code LM API。", diff --git a/src/package.nls.json b/src/package.nls.json index 4fac644eab..fe10839819 100644 --- a/src/package.nls.json +++ b/src/package.nls.json @@ -36,7 +36,7 @@ "settings.vsCodeLmModelSelector.family.description": "The family of the language model (e.g. gpt-4)", "settings.customStoragePath.description": "Custom storage path. Leave empty to use the default location. Supports absolute paths (e.g. 'D:\\ZooCodeStorage')", "settings.enableCodeActions.description": "Enable Zoo Code quick fixes", - "settings.autoImportSettingsPath.description": "Path to a ZooCode configuration file to automatically import on extension startup. Supports absolute paths and paths relative to the home directory (e.g. '~/Documents/roo-code-settings.json'). Leave empty to disable auto-import.", + "settings.autoImportSettingsPath.description": "Path to a ZooCode configuration file to automatically import on extension startup. Supports absolute paths and paths relative to the home directory (e.g. '~/Documents/zoo-code-settings.json'). Leave empty to disable auto-import.", "settings.maximumIndexedFilesForFileSearch.description": "Maximum number of files to index for the @ file search feature. Higher values provide better search results in large projects but may use more memory. Default: 10,000.", "settings.useAgentRules.description": "Enable loading of AGENTS.md files for agent-specific rules (see https://agent-rules.org/)", "settings.apiRequestTimeout.description": "API response timeout (seconds, default: 600, range: 1–3600). Higher values are recommended for local providers. Unsupported providers: Amazon Bedrock, Google Gemini(directly or through the Vertex AI platform), Mistral, Moonshot, Ollama, Poe, VS Code LM API.", diff --git a/src/package.nls.ko.json b/src/package.nls.ko.json index a743902280..99a064cd6c 100644 --- a/src/package.nls.ko.json +++ b/src/package.nls.ko.json @@ -36,7 +36,7 @@ "settings.vsCodeLmModelSelector.family.description": "언어 모델 계열 (예: gpt-4)", "settings.customStoragePath.description": "사용자 지정 저장소 경로. 기본 위치를 사용하려면 비워두세요. 절대 경로를 지원합니다 (예: 'D:\\ZooCodeStorage')", "settings.enableCodeActions.description": "Zoo Code 빠른 수정 사용 설정", - "settings.autoImportSettingsPath.description": "확장 프로그램 시작 시 자동으로 가져올 ZooCode 구성 파일의 경로입니다. 절대 경로 및 홈 디렉토리에 대한 상대 경로를 지원합니다(예: '~/Documents/roo-code-settings.json'). 자동 가져오기를 비활성화하려면 비워 둡니다.", + "settings.autoImportSettingsPath.description": "확장 프로그램 시작 시 자동으로 가져올 ZooCode 구성 파일의 경로입니다. 절대 경로 및 홈 디렉토리에 대한 상대 경로를 지원합니다(예: '~/Documents/zoo-code-settings.json'). 자동 가져오기를 비활성화하려면 비워 둡니다.", "settings.maximumIndexedFilesForFileSearch.description": "@ 파일 검색 기능을 위해 인덱싱할 최대 파일 수입니다. 더 큰 값은 대형 프로젝트에서 더 나은 검색 결과를 제공하지만 더 많은 메모리를 사용할 수 있습니다. 기본값: 10,000.", "settings.useAgentRules.description": "에이전트별 규칙에 대한 AGENTS.md 파일 로드를 활성화합니다 (참조: https://agent-rules.org/)", "settings.apiRequestTimeout.description": "API 응답 대기 시간(초, 기본값: 600, 범위: 1~3600). 로컬 공급자에는 더 높은 값을 권장합니다. 지원되지 않는 공급자: Amazon Bedrock, Google Gemini(directly or through the Vertex AI platform), Mistral, Moonshot, Ollama, Poe, VS Code LM API.", diff --git a/src/package.nls.nl.json b/src/package.nls.nl.json index 72bc15f89a..27948f933a 100644 --- a/src/package.nls.nl.json +++ b/src/package.nls.nl.json @@ -36,7 +36,7 @@ "settings.vsCodeLmModelSelector.family.description": "De familie van het taalmodel (bijv. gpt-4)", "settings.customStoragePath.description": "Aangepast opslagpad. Laat leeg om de standaardlocatie te gebruiken. Ondersteunt absolute paden (bijv. 'D:\\ZooCodeStorage')", "settings.enableCodeActions.description": "Snelle correcties van Zoo Code inschakelen.", - "settings.autoImportSettingsPath.description": "Pad naar een ZooCode-configuratiebestand om automatisch te importeren bij het opstarten van de extensie. Ondersteunt absolute paden en paden ten opzichte van de thuismap (bijv. '~/Documents/roo-code-settings.json'). Laat leeg om automatisch importeren uit te schakelen.", + "settings.autoImportSettingsPath.description": "Pad naar een ZooCode-configuratiebestand om automatisch te importeren bij het opstarten van de extensie. Ondersteunt absolute paden en paden ten opzichte van de thuismap (bijv. '~/Documents/zoo-code-settings.json'). Laat leeg om automatisch importeren uit te schakelen.", "settings.maximumIndexedFilesForFileSearch.description": "Maximaal aantal bestanden om te indexeren voor de @ bestandszoekfunctie. Hogere waarden bieden betere zoekresultaten in grote projecten maar kunnen meer geheugen gebruiken. Standaard: 10.000.", "settings.useAgentRules.description": "Laden van AGENTS.md-bestanden voor agentspecifieke regels inschakelen (zie https://agent-rules.org/)", "settings.apiRequestTimeout.description": "API-respons time-out (seconden, standaard: 600, bereik: 1–3600). Hogere waarden worden aanbevolen voor lokale providers. Niet-ondersteunde providers: Amazon Bedrock, Google Gemini(directly or through the Vertex AI platform), Mistral, Moonshot, Ollama, Poe, VS Code LM API.", diff --git a/src/package.nls.pl.json b/src/package.nls.pl.json index 92fb97778b..8fb8b6eb83 100644 --- a/src/package.nls.pl.json +++ b/src/package.nls.pl.json @@ -36,7 +36,7 @@ "settings.vsCodeLmModelSelector.family.description": "Rodzina modelu językowego (np. gpt-4)", "settings.customStoragePath.description": "Niestandardowa ścieżka przechowywania. Pozostaw puste, aby użyć domyślnej lokalizacji. Obsługuje ścieżki bezwzględne (np. 'D:\\ZooCodeStorage')", "settings.enableCodeActions.description": "Włącz szybkie poprawki Zoo Code.", - "settings.autoImportSettingsPath.description": "Ścieżka do pliku konfiguracyjnego ZooCode, który ma być automatycznie importowany podczas uruchamiania rozszerzenia. Obsługuje ścieżki bezwzględne i ścieżki względne do katalogu domowego (np. '~/Documents/roo-code-settings.json'). Pozostaw puste, aby wyłączyć automatyczne importowanie.", + "settings.autoImportSettingsPath.description": "Ścieżka do pliku konfiguracyjnego ZooCode, który ma być automatycznie importowany podczas uruchamiania rozszerzenia. Obsługuje ścieżki bezwzględne i ścieżki względne do katalogu domowego (np. '~/Documents/zoo-code-settings.json'). Pozostaw puste, aby wyłączyć automatyczne importowanie.", "settings.maximumIndexedFilesForFileSearch.description": "Maksymalna liczba plików do indeksowania dla funkcji wyszukiwania plików @. Wyższe wartości zapewniają lepsze wyniki wyszukiwania w dużych projektach, ale mogą zużywać więcej pamięci. Domyślnie: 10 000.", "settings.useAgentRules.description": "Włącz wczytywanie plików AGENTS.md dla reguł specyficznych dla agenta (zobacz https://agent-rules.org/)", "settings.apiRequestTimeout.description": "Limit czasu odpowiedzi API (sekundy, domyślnie: 600, zakres: 1–3600). Wyższe wartości są zalecane dla lokalnych dostawców. Nieobsługiwani dostawcy: Amazon Bedrock, Google Gemini(directly or through the Vertex AI platform), Mistral, Moonshot, Ollama, Poe, VS Code LM API.", diff --git a/src/package.nls.pt-BR.json b/src/package.nls.pt-BR.json index 872af10e80..b4cae4644b 100644 --- a/src/package.nls.pt-BR.json +++ b/src/package.nls.pt-BR.json @@ -36,7 +36,7 @@ "settings.vsCodeLmModelSelector.family.description": "A família do modelo de linguagem (ex: gpt-4)", "settings.customStoragePath.description": "Caminho de armazenamento personalizado. Deixe vazio para usar o local padrão. Suporta caminhos absolutos (ex: 'D:\\ZooCodeStorage')", "settings.enableCodeActions.description": "Habilitar correções rápidas do Zoo Code.", - "settings.autoImportSettingsPath.description": "Caminho para um arquivo de configuração do ZooCode para importar automaticamente na inicialização da extensão. Suporta caminhos absolutos e caminhos relativos ao diretório inicial (por exemplo, '~/Documents/roo-code-settings.json'). Deixe em branco para desativar a importação automática.", + "settings.autoImportSettingsPath.description": "Caminho para um arquivo de configuração do ZooCode para importar automaticamente na inicialização da extensão. Suporta caminhos absolutos e caminhos relativos ao diretório inicial (por exemplo, '~/Documents/zoo-code-settings.json'). Deixe em branco para desativar a importação automática.", "settings.maximumIndexedFilesForFileSearch.description": "Número máximo de arquivos a indexar para a funcionalidade de busca de arquivos @. Valores maiores fornecem melhores resultados de busca em projetos grandes, mas podem consumir mais memória. Padrão: 10.000.", "settings.useAgentRules.description": "Habilita o carregamento de arquivos AGENTS.md para regras específicas do agente (consulte https://agent-rules.org/)", "settings.apiRequestTimeout.description": "Tempo limite de resposta da API (segundos, padrão: 600, intervalo: 1–3600). Valores mais altos são recomendados para provedores locais. Provedores não suportados: Amazon Bedrock, Google Gemini(directly or through the Vertex AI platform), Mistral, Moonshot, Ollama, Poe, VS Code LM API.", diff --git a/src/package.nls.ru.json b/src/package.nls.ru.json index cb38655945..0e61002848 100644 --- a/src/package.nls.ru.json +++ b/src/package.nls.ru.json @@ -36,7 +36,7 @@ "settings.vsCodeLmModelSelector.family.description": "Семейство языковой модели (например, gpt-4)", "settings.customStoragePath.description": "Пользовательский путь хранения. Оставьте пустым для использования пути по умолчанию. Поддерживает абсолютные пути (например, 'D:\\ZooCodeStorage')", "settings.enableCodeActions.description": "Включить быстрые исправления Zoo Code.", - "settings.autoImportSettingsPath.description": "Путь к файлу конфигурации ZooCode для автоматического импорта при запуске расширения. Поддерживает абсолютные пути и пути относительно домашнего каталога (например, '~/Documents/roo-code-settings.json'). Оставьте пустым, чтобы отключить автоматический импорт.", + "settings.autoImportSettingsPath.description": "Путь к файлу конфигурации ZooCode для автоматического импорта при запуске расширения. Поддерживает абсолютные пути и пути относительно домашнего каталога (например, '~/Documents/zoo-code-settings.json'). Оставьте пустым, чтобы отключить автоматический импорт.", "settings.maximumIndexedFilesForFileSearch.description": "Максимальное количество файлов для индексации при поиске файлов @. Большие значения обеспечивают лучшие результаты поиска в крупных проектах, но могут потреблять больше памяти. По умолчанию: 10 000.", "settings.useAgentRules.description": "Включить загрузку файлов AGENTS.md для специфичных для агента правил (см. https://agent-rules.org/)", "settings.apiRequestTimeout.description": "Тайм-аут ответа API (секунды, по умолчанию: 600, диапазон: 1–3600). Более высокие значения рекомендуются для локальных провайдеров. Неподдерживаемые провайдеры: Amazon Bedrock, Google Gemini(directly or through the Vertex AI platform), Mistral, Moonshot, Ollama, Poe, VS Code LM API.", diff --git a/src/package.nls.tr.json b/src/package.nls.tr.json index 7d995723ce..1842156d75 100644 --- a/src/package.nls.tr.json +++ b/src/package.nls.tr.json @@ -36,7 +36,7 @@ "settings.vsCodeLmModelSelector.family.description": "Dil modelinin ailesi (örn: gpt-4)", "settings.customStoragePath.description": "Özel depolama yolu. Varsayılan konumu kullanmak için boş bırakın. Mutlak yolları destekler (örn: 'D:\\ZooCodeStorage')", "settings.enableCodeActions.description": "Zoo Code hızlı düzeltmeleri etkinleştir.", - "settings.autoImportSettingsPath.description": "Uzantı başlangıcında otomatik olarak içe aktarılacak bir ZooCode yapılandırma dosyasının yolu. Mutlak yolları ve ana dizine göreli yolları destekler (ör. '~/Documents/roo-code-settings.json'). Otomatik içe aktarmayı devre dışı bırakmak için boş bırakın.", + "settings.autoImportSettingsPath.description": "Uzantı başlangıcında otomatik olarak içe aktarılacak bir ZooCode yapılandırma dosyasının yolu. Mutlak yolları ve ana dizine göreli yolları destekler (ör. '~/Documents/zoo-code-settings.json'). Otomatik içe aktarmayı devre dışı bırakmak için boş bırakın.", "settings.maximumIndexedFilesForFileSearch.description": "@ dosya arama özelliği için dizinlenecek maksimum dosya sayısı. Daha yüksek değerler büyük projelerde daha iyi arama sonuçları sağlar ancak daha fazla bellek kullanabilir. Varsayılan: 10.000.", "settings.useAgentRules.description": "Aracıya özgü kurallar için AGENTS.md dosyalarının yüklenmesini etkinleştirin (bkz. https://agent-rules.org/)", "settings.apiRequestTimeout.description": "API yanıt zaman aşımı (saniye, varsayılan: 600, aralık: 1–3600). Yerel sağlayıcılar için daha yüksek değerler önerilir. Desteklenmeyen sağlayıcılar: Amazon Bedrock, Google Gemini(directly or through the Vertex AI platform), Mistral, Moonshot, Ollama, Poe, VS Code LM API.", diff --git a/src/package.nls.vi.json b/src/package.nls.vi.json index b50e4db508..c846978793 100644 --- a/src/package.nls.vi.json +++ b/src/package.nls.vi.json @@ -36,7 +36,7 @@ "settings.vsCodeLmModelSelector.family.description": "Họ mô hình ngôn ngữ (ví dụ: gpt-4)", "settings.customStoragePath.description": "Đường dẫn lưu trữ tùy chỉnh. Để trống để sử dụng vị trí mặc định. Hỗ trợ đường dẫn tuyệt đối (ví dụ: 'D:\\ZooCodeStorage')", "settings.enableCodeActions.description": "Bật sửa lỗi nhanh Zoo Code.", - "settings.autoImportSettingsPath.description": "Đường dẫn đến tệp cấu hình ZooCode để tự động nhập khi khởi động tiện ích mở rộng. Hỗ trợ đường dẫn tuyệt đối và đường dẫn tương đối đến thư mục chính (ví dụ: '~/Documents/roo-code-settings.json'). Để trống để tắt tính năng tự động nhập.", + "settings.autoImportSettingsPath.description": "Đường dẫn đến tệp cấu hình ZooCode để tự động nhập khi khởi động tiện ích mở rộng. Hỗ trợ đường dẫn tuyệt đối và đường dẫn tương đối đến thư mục chính (ví dụ: '~/Documents/zoo-code-settings.json'). Để trống để tắt tính năng tự động nhập.", "settings.maximumIndexedFilesForFileSearch.description": "Số lượng tệp tối đa để lập chỉ mục cho tính năng tìm kiếm tệp @. Giá trị cao hơn cung cấp kết quả tìm kiếm tốt hơn trong các dự án lớn nhưng có thể sử dụng nhiều bộ nhớ hơn. Mặc định: 10.000.", "settings.useAgentRules.description": "Bật tải tệp AGENTS.md cho các quy tắc dành riêng cho tác nhân (xem https://agent-rules.org/)", "settings.apiRequestTimeout.description": "Thời gian chờ phản hồi API (giây, mặc định: 600, phạm vi: 1–3600). Nên dùng giá trị cao hơn cho các nhà cung cấp cục bộ. Nhà cung cấp không được hỗ trợ: Amazon Bedrock, Google Gemini(directly or through the Vertex AI platform), Mistral, Moonshot, Ollama, Poe, VS Code LM API.", diff --git a/src/package.nls.zh-CN.json b/src/package.nls.zh-CN.json index 0686d03a14..e2705e9e2f 100644 --- a/src/package.nls.zh-CN.json +++ b/src/package.nls.zh-CN.json @@ -36,7 +36,7 @@ "settings.vsCodeLmModelSelector.family.description": "语言模型的系列(例如:gpt-4)", "settings.customStoragePath.description": "自定义存储路径。留空以使用默认位置。支持绝对路径(例如:'D:\\ZooCodeStorage')", "settings.enableCodeActions.description": "启用 Zoo Code 快速修复", - "settings.autoImportSettingsPath.description": "ZooCode 配置文件的路径,用于在扩展启动时自动导入。支持绝对路径和相对于主目录的路径(例如 '~/Documents/roo-code-settings.json')。留空以禁用自动导入。", + "settings.autoImportSettingsPath.description": "ZooCode 配置文件的路径,用于在扩展启动时自动导入。支持绝对路径和相对于主目录的路径(例如 '~/Documents/zoo-code-settings.json')。留空以禁用自动导入。", "settings.maximumIndexedFilesForFileSearch.description": "为 @ 文件搜索功能建立索引时要索引的最大文件数。较大的值在大型项目中提供更好的搜索结果,但可能占用更多内存。默认值:10,000。", "settings.useAgentRules.description": "为特定于代理的规则启用 AGENTS.md 文件的加载(请参阅 https://agent-rules.org/)", "settings.apiRequestTimeout.description": "API 响应超时(秒,默认值:600,范围:1–3600)。建议本地提供商使用更高的值。不适用的提供商:Amazon Bedrock、Google Gemini(directly or through the Vertex AI platform)、Mistral、Moonshot、Ollama、Poe、VS Code LM API。", diff --git a/src/package.nls.zh-TW.json b/src/package.nls.zh-TW.json index 8005e0de7f..723d8d08ad 100644 --- a/src/package.nls.zh-TW.json +++ b/src/package.nls.zh-TW.json @@ -36,7 +36,7 @@ "settings.vsCodeLmModelSelector.family.description": "語言模型系列(例如:gpt-4)", "settings.customStoragePath.description": "自訂儲存路徑。留空以使用預設位置。支援絕對路徑(例如:'D:\\ZooCodeStorage')", "settings.enableCodeActions.description": "啟用 Zoo Code 快速修復。", - "settings.autoImportSettingsPath.description": "ZooCode 設定檔案的路徑,用於在擴充功能啟動時自動匯入。支援絕對路徑和相對於主目錄的路徑(例如 '~/Documents/roo-code-settings.json')。留空以停用自動匯入。", + "settings.autoImportSettingsPath.description": "ZooCode 設定檔案的路徑,用於在擴充功能啟動時自動匯入。支援絕對路徑和相對於主目錄的路徑(例如 '~/Documents/zoo-code-settings.json')。留空以停用自動匯入。", "settings.maximumIndexedFilesForFileSearch.description": "為 @ 檔案搜尋功能建立索引時要索引的最大檔案數。較大的值在大型專案中提供更好的搜尋結果,但可能佔用更多記憶體。預設值:10,000。", "settings.useAgentRules.description": "為特定於代理的規則啟用 AGENTS.md 檔案的載入(請參閱 https://agent-rules.org/)", "settings.apiRequestTimeout.description": "API 回應逾時(秒,預設值:600,範圍:1–3600)。建議本地提供商使用更高的值。不適用的提供商:Amazon Bedrock、Google Gemini(directly or through the Vertex AI platform)、Mistral、Moonshot、Ollama、Poe、VS Code LM API。", From e064cf0592cfc70735d86feff77f1265637697ae Mon Sep 17 00:00:00 2001 From: T Date: Sat, 15 Aug 2026 02:10:27 +0000 Subject: [PATCH 13/66] chore: prepare v3.78.0 release (#1249) --- CHANGELOG.md | 42 + README.md | 12 +- locales/ca/README.md | 12 +- locales/de/README.md | 12 +- locales/es/README.md | 12 +- locales/fr/README.md | 12 +- locales/hi/README.md | 12 +- locales/id/README.md | 12 +- locales/it/README.md | 12 +- locales/ja/README.md | 12 +- locales/ko/README.md | 12 +- locales/nl/README.md | 12 +- locales/pl/README.md | 12 +- locales/pt-BR/README.md | 12 +- locales/ru/README.md | 12 +- locales/tr/README.md | 12 +- locales/vi/README.md | 12 +- locales/zh-CN/README.md | 12 +- locales/zh-TW/README.md | 12 +- src/CHANGELOG.md | 3852 +++++++++++++++++ src/core/webview/ClineProvider.ts | 2 +- src/package.json | 2 +- .../chat/__tests__/Announcement.spec.tsx | 16 +- webview-ui/src/i18n/locales/ca/chat.json | 6 +- webview-ui/src/i18n/locales/de/chat.json | 6 +- webview-ui/src/i18n/locales/en/chat.json | 6 +- webview-ui/src/i18n/locales/es/chat.json | 6 +- webview-ui/src/i18n/locales/fr/chat.json | 6 +- webview-ui/src/i18n/locales/hi/chat.json | 6 +- webview-ui/src/i18n/locales/id/chat.json | 6 +- webview-ui/src/i18n/locales/it/chat.json | 6 +- webview-ui/src/i18n/locales/ja/chat.json | 6 +- webview-ui/src/i18n/locales/ko/chat.json | 6 +- webview-ui/src/i18n/locales/nl/chat.json | 6 +- webview-ui/src/i18n/locales/pl/chat.json | 6 +- webview-ui/src/i18n/locales/pt-BR/chat.json | 6 +- webview-ui/src/i18n/locales/ru/chat.json | 6 +- webview-ui/src/i18n/locales/tr/chat.json | 6 +- webview-ui/src/i18n/locales/vi/chat.json | 6 +- webview-ui/src/i18n/locales/zh-CN/chat.json | 6 +- webview-ui/src/i18n/locales/zh-TW/chat.json | 6 +- 41 files changed, 4066 insertions(+), 172 deletions(-) create mode 100644 src/CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md index f1abe84a66..72bfdbd415 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,47 @@ # Zoo Code Changelog +## [3.78.0] + +### Minor Changes + +- Add NanoGPT as a configurable provider with dynamic model discovery, streaming and prompt completions, and routing preferences for speed, price, latency, throughput, tool support, and caching (PR #1239 by @taltas) +- Add the new Gemini 3.7 Flash model to Google Gemini and Vertex AI with a 1M context window, multimodal input, prompt caching, and configurable reasoning (PR #1241 by @app/zoomote) +- Add the new GLM 5.3 model to Z AI coding plans and OpenCode Go with a 1M context window, prompt caching, and extended reasoning controls (PR #1244 by @app/zoomote) +- Add the new Qwen3.8 Max model to OpenCode Go with multimodal input, caching, streamed reasoning, and Anthropic Messages routing (PR #1245 by @app/zoomote) +- Fix Azure OpenAI resource endpoints and improve Azure-specific setup guidance in OpenAI Compatible settings (#1191 by @edelauna, PR #1192 by @app/zoomote) +- Preserve task-history titles when rapidly navigating away before a task's messages finish loading (#1180 by @edelauna, PR #1181 by @edelauna) +- Correct Kimi Code output-token defaults and honor model limits returned by the server (#1215 by @myk1yt, PR #1217 by @myk1yt) +- Update DeepSeek V4 Pro reasoning efforts and normalize medium, high, and extended reasoning mappings (#1235 by @WHMHammer, PR #1236 by @WHMHammer) +- Correct DeepSeek V4 pricing and expand provider coverage for the V4 Pro 0813 checkpoint (PR #1237 by @app/zoomote) +- Rename the default settings import/export file to `zoo-code-settings.json` throughout the extension (#1176 by @Rafael-Silva-Oliveira, PR #1177 by @Rafael-Silva-Oliveira) +- Add Destructive Command Guard support for Intel-based macOS systems (PR #1213 by @app/zoomote) +- Update `undici` to 6.28.0 to address security vulnerabilities (PR #1161 by @app/renovate) +- Update Mermaid to 11.16.1 to address a prototype-pollution vulnerability (PR #1193 by @app/renovate) +- Record tool usage centrally to prevent duplicate telemetry and sanitize raw tool names (PR #1073 by @edelauna) +- Canonicalize shared provider settings identifiers and add registry-alignment coverage (PR #1109 by @WebMad) +- Canonicalize provider identifiers across CLI configuration, environment mappings, and model selection (PR #1110 by @WebMad) +- Complete the webview migration to canonical provider identifiers across provider settings and routing (PR #1141 by @WebMad) +- Use canonical provider identifiers throughout API options and add focused interaction coverage (PR #1146 by @WebMad) +- Canonicalize provider model configuration identifiers and provider-specific settings behavior (PR #1147 by @WebMad) +- Migrate model-selection UI hooks to canonical provider identifiers (PR #1148 by @WebMad) +- Reuse the retired Roo provider identifier registry while preserving migration compatibility (PR #1166 by @WebMad) +- Introduce typed shared test utilities for API options, filesystem mocks, reset operations, VS Code doubles, and webview rendering (PR #1171 by @app/zoomote) +- Reuse shared API option factories across Requesty, OpenRouter, and Vercel AI Gateway provider tests (PR #1178 by @app/zoomote) +- Reuse the shared Responses client mock in X.AI provider tests (PR #1182 by @app/zoomote) +- Reuse shared VS Code context, URI, and reset helpers in custom-mode configuration tests (PR #1190 by @app/zoomote) +- Reuse shared reset helpers across code-index embedder tests (PR #1194 by @app/zoomote) +- Reuse shared config test helpers and remove obsolete lint suppressions (PR #1195 by @app/zoomote) +- Reuse shared webview render helpers across focused chat tests (PR #1196 by @app/zoomote) +- Reuse shared reset helpers across terminal integration tests (PR #1197 by @app/zoomote) +- Reuse shared VS Code and reset helpers in settings import/export tests (PR #1198 by @app/zoomote) +- Reuse shared reset helpers across additional code-index tests (PR #1199 by @app/zoomote) +- Complete another batch of shared reset-helper adoption in code-index tests (PR #1200 by @app/zoomote) +- Finish reset-helper adoption in Semble and terminal test suites (PR #1201 by @app/zoomote) +- Complete shared reset-helper adoption across provider tests (PR #1202 by @app/zoomote) +- Reuse shared webview render helpers across chat and settings tests (PR #1203 by @app/zoomote) +- Complete shared webview render-helper adoption in the remaining settings tests (PR #1204 by @app/zoomote) +- Merge the v3.76.0 release preparation branch into `main` (PR #1173 by @navedmerchant) + ## [3.76.0] ### Minor Changes diff --git a/README.md b/README.md index b9adb81960..b0bd6a083c 100644 --- a/README.md +++ b/README.md @@ -46,13 +46,13 @@ Zoo Code builds on the foundation created by Roo Code and continues to expand it - **More dependable terminal and editing workflows** — fixes for premature terminal completion, task-state races, context management, diff editing, and provider-specific tool use. - **More control over your workspace** — rules management, per-mode MCP restrictions, multi-root path controls, model reasoning options, and completion change review actions. -## What's New in v3.76.0 +## What's New in v3.78.0 -- **Run longer, uninterrupted tasks with Destructive Command Guard (DCG)** — DCG blocks dangerous commands while letting Zoo keep working without you continuously pressing approval buttons, backed by hardened managed-binary downloads and installation. -- **Better provider controls and reliability** — choose OpenAI Codex response speed, use updated DeepSeek configurations, and benefit from stronger isolation between provider-profile changes and running tasks. -- **Critical terminal execution fix** — Zoo now waits for terminal commands to finish before starting the next step, preventing overlapping work and premature model continuation. -- Smarter batching groups related tool approvals while keeping unrelated requests separate. -- Telemetry delivery and model-cache fetching are more resilient under failures and concurrent requests. +- **Three major new models have arrived** — use the brand-new Gemini 3.7 Flash, GLM 5.3, and Qwen3.8 Max models, plus updated DeepSeek V4 reasoning, pricing, and provider coverage. +- **Connect to NanoGPT** — use dynamic model discovery, streaming and prompt completions, and routing preferences for speed, price, latency, throughput, tool support, and caching. +- **More reliable providers and tasks** — fixes improve Azure OpenAI endpoint setup, Kimi Code output limits, task-history title preservation, and Zoo settings import/export. +- Destructive Command Guard now supports Intel-based Macs. +- Security updates address vulnerabilities in `undici` and Mermaid.
🌐 Available languages diff --git a/locales/ca/README.md b/locales/ca/README.md index 656679cc63..4cc35f4364 100644 --- a/locales/ca/README.md +++ b/locales/ca/README.md @@ -47,13 +47,13 @@ Zoo Code parteix de la base creada per Roo Code i continua ampliant-la amb: - **Fluxos de terminal i edició més fiables** — correccions per a la finalització prematura del terminal, les condicions de cursa en l'estat de les tasques, la gestió del context, l'edició de diff i l'ús d'eines específiques de cada proveïdor. - **Més control sobre el teu espai de treball** — gestió de regles, restriccions MCP per mode, controls de rutes multiarrel, opcions de raonament dels models i accions per revisar els canvis en completar una tasca. -## Novetats a la v3.76.0 +## Novetats a la v3.78.0 -- **Executa tasques més llargues i sense interrupcions amb Destructive Command Guard (DCG)** — DCG bloqueja les ordres perilloses mentre permet que Zoo continuï treballant sense que hagis de prémer contínuament botons d'aprovació, amb baixades i instal·lació reforçades del binari gestionat. -- **Millors controls i més fiabilitat dels proveïdors** — tria la velocitat de resposta d'OpenAI Codex, utilitza configuracions actualitzades de DeepSeek i gaudeix d'un aïllament més sòlid entre els canvis de perfil de proveïdor i les tasques en execució. -- **Correcció crítica de l'execució al terminal** — Zoo ara espera que les ordres del terminal acabin abans de començar el pas següent, cosa que evita treballs superposats i que el model continuï abans d'hora. -- L'agrupació més intel·ligent reuneix les aprovacions d'eines relacionades i manté separades les sol·licituds que no hi tenen relació. -- El lliurament de telemetria i l'obtenció de la memòria cau de models són més resistents davant d'errors i sol·licituds simultànies. +- **Han arribat tres grans models nous** — utilitza els nous Gemini 3.7 Flash, GLM 5.3 i Qwen3.8 Max, a més de millores en el raonament, els preus i la cobertura de proveïdors de DeepSeek V4. +- **Connecta't a NanoGPT** — utilitza el descobriment dinàmic de models, streaming i completions de prompts, i preferències d'encaminament per velocitat, preu, latència, rendiment, compatibilitat amb eines i memòria cau. +- **Proveïdors i tasques més fiables** — les correccions milloren la configuració dels endpoints d'Azure OpenAI, els límits de sortida de Kimi Code, la conservació dels títols de l'historial de tasques i la importació/exportació de configuració de Zoo. +- Destructive Command Guard ara és compatible amb els Mac basats en Intel. +- Les actualitzacions de seguretat solucionen vulnerabilitats a `undici` i Mermaid. ## Què pot fer Zoo Code per TU? diff --git a/locales/de/README.md b/locales/de/README.md index 033e3cf069..62626dd353 100644 --- a/locales/de/README.md +++ b/locales/de/README.md @@ -47,13 +47,13 @@ Zoo Code baut auf dem von Roo Code geschaffenen Fundament auf und erweitert es f - **Zuverlässigere Terminal- und Bearbeitungsabläufe** — Korrekturen für vorzeitige Terminalabschlüsse, Race Conditions beim Aufgabenstatus, Kontextverwaltung, diff-Bearbeitung und anbieterspezifische Tool-Nutzung. - **Mehr Kontrolle über deinen Workspace** — Regelverwaltung, MCP-Beschränkungen pro Modus, Pfadsteuerung für Multi-Root-Workspaces, Reasoning-Optionen für Modelle und Aktionen zur Prüfung von Änderungen nach Abschluss. -## Neu in v3.76.0 +## Neu in v3.78.0 -- **Längere, unterbrechungsfreie Aufgaben mit Destructive Command Guard (DCG)** — DCG blockiert gefährliche Befehle und lässt Zoo gleichzeitig weiterarbeiten, ohne dass du ständig Genehmigungen anklicken musst. Abgesicherte Downloads und Installationen der verwalteten Binärdatei sorgen dabei für zusätzliche Sicherheit. -- **Bessere Anbietersteuerung und Zuverlässigkeit** — wähle die Antwortgeschwindigkeit von OpenAI Codex, nutze aktualisierte DeepSeek-Konfigurationen und profitiere von einer stärkeren Isolierung zwischen Änderungen an Anbieterprofilen und laufenden Aufgaben. -- **Kritische Korrektur der Terminalausführung** — Zoo wartet jetzt, bis Terminalbefehle abgeschlossen sind, bevor der nächste Schritt beginnt. Dadurch werden sich überschneidende Arbeiten und ein vorzeitiges Fortfahren des Modells verhindert. -- Intelligentere Bündelung fasst Genehmigungen für zusammengehörige Tools zusammen und hält unabhängige Anfragen getrennt. -- Telemetrieübermittlung und das Abrufen des Modell-Caches sind bei Fehlern und gleichzeitigen Anfragen robuster. +- **Drei bedeutende neue Modelle sind da** — nutze die brandneuen Modelle Gemini 3.7 Flash, GLM 5.3 und Qwen3.8 Max sowie aktualisiertes Reasoning, Preise und Anbieterabdeckung für DeepSeek V4. +- **Verbinde dich mit NanoGPT** — nutze dynamische Modellerkennung, Streaming und Prompt-Vervollständigung sowie Routing-Einstellungen für Geschwindigkeit, Preis, Latenz, Durchsatz, Tool-Unterstützung und Caching. +- **Zuverlässigere Anbieter und Aufgaben** — Korrekturen verbessern die Einrichtung von Azure-OpenAI-Endpunkten, Kimi-Code-Ausgabelimits, die Beibehaltung von Titeln im Aufgabenverlauf sowie den Import und Export von Zoo-Einstellungen. +- Destructive Command Guard unterstützt jetzt Intel-basierte Macs. +- Sicherheitsupdates beheben Schwachstellen in `undici` und Mermaid. ## Was kann Zoo Code für DICH tun? diff --git a/locales/es/README.md b/locales/es/README.md index 13b5beb1bb..a7eabc790d 100644 --- a/locales/es/README.md +++ b/locales/es/README.md @@ -47,13 +47,13 @@ Zoo Code parte de los cimientos creados por Roo Code y continúa ampliándolos c - **Flujos de terminal y edición más fiables** — correcciones para la finalización prematura del terminal, las condiciones de carrera del estado de las tareas, la gestión del contexto, la edición de diff y el uso de herramientas específicas de cada proveedor. - **Más control sobre tu espacio de trabajo** — gestión de reglas, restricciones de MCP por modo, controles de rutas multirraíz, opciones de razonamiento de modelos y acciones para revisar los cambios al completar una tarea. -## Novedades de la v3.76.0 +## Novedades de la v3.78.0 -- **Ejecuta tareas más largas y sin interrupciones con Destructive Command Guard (DCG)** — DCG bloquea los comandos peligrosos mientras permite que Zoo siga trabajando sin que tengas que pulsar continuamente botones de aprobación, con descargas e instalación reforzadas del binario administrado. -- **Mejores controles y fiabilidad de los proveedores** — elige la velocidad de respuesta de OpenAI Codex, utiliza configuraciones actualizadas de DeepSeek y benefíciate de un aislamiento más sólido entre los cambios de perfiles de proveedor y las tareas en ejecución. -- **Corrección crítica de la ejecución en el terminal** — Zoo ahora espera a que los comandos del terminal terminen antes de iniciar el siguiente paso, lo que evita el trabajo superpuesto y que el modelo continúe antes de tiempo. -- La agrupación más inteligente reúne las aprobaciones de herramientas relacionadas y mantiene separadas las solicitudes que no tienen relación. -- La entrega de telemetría y la obtención de la caché de modelos son más resistentes ante fallos y solicitudes simultáneas. +- **Han llegado tres importantes modelos nuevos** — usa los flamantes Gemini 3.7 Flash, GLM 5.3 y Qwen3.8 Max, además de mejoras en el razonamiento, los precios y la cobertura de proveedores de DeepSeek V4. +- **Conéctate a NanoGPT** — usa descubrimiento dinámico de modelos, streaming y completado de prompts, y preferencias de enrutamiento por velocidad, precio, latencia, rendimiento, compatibilidad con herramientas y caché. +- **Proveedores y tareas más fiables** — las correcciones mejoran la configuración de endpoints de Azure OpenAI, los límites de salida de Kimi Code, la conservación de títulos del historial de tareas y la importación/exportación de ajustes de Zoo. +- Destructive Command Guard ahora es compatible con Macs basados en Intel. +- Las actualizaciones de seguridad corrigen vulnerabilidades en `undici` y Mermaid. ## ¿Qué puede hacer Zoo Code por TI? diff --git a/locales/fr/README.md b/locales/fr/README.md index bcc295e90e..b2bddceb55 100644 --- a/locales/fr/README.md +++ b/locales/fr/README.md @@ -47,13 +47,13 @@ Zoo Code s'appuie sur les fondations créées par Roo Code et continue de les en - **Des workflows de terminal et d'édition plus fiables** — correctifs pour les fins prématurées de commandes dans le terminal, les conditions de concurrence liées à l'état des tâches, la gestion du contexte, l'édition de diff et l'utilisation d'outils propres aux providers. - **Davantage de contrôle sur ton espace de travail** — gestion des règles, restrictions MCP par mode, contrôle des chemins multi-root, options de raisonnement des modèles et actions de vérification des modifications à la fin d'une tâche. -## Nouveautés de la v3.76.0 +## Nouveautés de la v3.78.0 -- **Exécute des tâches plus longues sans interruption avec Destructive Command Guard (DCG)** — DCG bloque les commandes dangereuses tout en laissant Zoo continuer à travailler sans que tu aies à cliquer constamment sur des boutons d'approbation, avec des téléchargements et une installation renforcés du binaire géré. -- **Meilleurs contrôles et fiabilité des providers** — choisis la vitesse de réponse d'OpenAI Codex, utilise les configurations DeepSeek mises à jour et profite d'une isolation renforcée entre les changements de profils de provider et les tâches en cours. -- **Correctif critique de l'exécution dans le terminal** — Zoo attend désormais que les commandes du terminal se terminent avant de commencer l'étape suivante, ce qui évite le chevauchement des opérations et la reprise prématurée du modèle. -- Un regroupement plus intelligent rassemble les approbations d'outils associés tout en séparant les demandes sans rapport. -- L'envoi de la télémétrie et la récupération du cache des modèles résistent mieux aux pannes et aux requêtes simultanées. +- **Trois nouveaux modèles majeurs sont arrivés** — utilise les tout nouveaux Gemini 3.7 Flash, GLM 5.3 et Qwen3.8 Max, ainsi que les améliorations du raisonnement, des tarifs et de la couverture des providers de DeepSeek V4. +- **Connecte-toi à NanoGPT** — profite de la découverte dynamique des modèles, du streaming et de la complétion des prompts, avec des préférences de routage pour la vitesse, le prix, la latence, le débit, la prise en charge des outils et le cache. +- **Providers et tâches plus fiables** — les correctifs améliorent la configuration des endpoints Azure OpenAI, les limites de sortie de Kimi Code, la conservation des titres dans l'historique des tâches et l'import/export des paramètres Zoo. +- Destructive Command Guard prend désormais en charge les Mac équipés d'un processeur Intel. +- Des mises à jour de sécurité corrigent des vulnérabilités dans `undici` et Mermaid. ## Que peut faire Zoo Code pour VOUS ? diff --git a/locales/hi/README.md b/locales/hi/README.md index 47ad3ae152..388ba7c525 100644 --- a/locales/hi/README.md +++ b/locales/hi/README.md @@ -46,13 +46,13 @@ Zoo Code, Roo Code की बनाई नींव पर आगे बढ़ - **ज़्यादा भरोसेमंद terminal और editing workflows** — terminal के समय से पहले पूरा होने, task-state race conditions, context management, diff editing और provider-specific tool use से जुड़ी समस्याओं के fixes। - **अपने workspace पर ज़्यादा control** — rules management, हर mode के लिए MCP restrictions, multi-root path controls, model reasoning options और completion changes की review actions। -## v3.76.0 में नया क्या है +## v3.78.0 में नया क्या है -- **Destructive Command Guard (DCG) के साथ लंबे और बिना रुकावट वाले tasks चलाओ** — DCG खतरनाक commands को block करता है और Zoo को लगातार approval buttons दबवाए बिना काम करते रहने देता है; managed binary downloads और installation को भी अधिक सुरक्षित बनाया गया है। -- **बेहतर provider controls और reliability** — OpenAI Codex की response speed चुनो, updated DeepSeek configurations इस्तेमाल करो और provider-profile changes व चल रहे tasks के बीच अधिक मज़बूत isolation का लाभ लो। -- **Terminal execution का अहम fix** — Zoo अब अगला step शुरू करने से पहले terminal commands के पूरा होने का इंतज़ार करता है, जिससे overlapping work और model का समय से पहले आगे बढ़ना रुकता है। -- Smarter batching संबंधित tool approvals को एक साथ रखती है और असंबंधित requests को अलग रखती है। -- Failures और concurrent requests के दौरान telemetry delivery और model-cache fetching अब अधिक भरोसेमंद हैं। +- **तीन बड़े नए models आ गए हैं** — बिल्कुल नए Gemini 3.7 Flash, GLM 5.3 और Qwen3.8 Max models का उपयोग करो, साथ ही DeepSeek V4 के updated reasoning, pricing और provider coverage का लाभ लो। +- **NanoGPT से connect करो** — dynamic model discovery, streaming और prompt completions के साथ speed, price, latency, throughput, tool support और caching के लिए routing preferences का उपयोग करो। +- **अधिक reliable providers और tasks** — fixes Azure OpenAI endpoint setup, Kimi Code output limits, task-history title preservation और Zoo settings import/export को बेहतर बनाते हैं। +- Destructive Command Guard अब Intel-आधारित Macs को support करता है। +- Security updates `undici` और Mermaid की vulnerabilities को ठीक करते हैं। ## Zoo Code आपके लिए क्या कर सकता है? diff --git a/locales/id/README.md b/locales/id/README.md index 772f64c1dd..794dc46dd1 100644 --- a/locales/id/README.md +++ b/locales/id/README.md @@ -46,13 +46,13 @@ Zoo Code dikembangkan di atas fondasi yang dibuat oleh Roo Code dan terus memper - **Workflow terminal dan pengeditan yang lebih andal** — perbaikan untuk terminal yang selesai terlalu dini, race condition status task, pengelolaan konteks, pengeditan diff, dan penggunaan tool khusus provider. - **Kontrol lebih besar atas workspace kamu** — pengelolaan rules, pembatasan MCP per mode, kontrol path multi-root, opsi reasoning model, dan tindakan untuk meninjau perubahan saat selesai. -## Yang Baru di v3.76.0 +## Yang Baru di v3.78.0 -- **Jalankan task yang lebih panjang tanpa gangguan dengan Destructive Command Guard (DCG)** — DCG memblokir perintah berbahaya sambil membiarkan Zoo terus bekerja tanpa kamu harus terus-menerus menekan tombol persetujuan, didukung download dan instalasi managed binary yang diperkuat. -- **Kontrol provider dan keandalan yang lebih baik** — pilih kecepatan respons OpenAI Codex, gunakan konfigurasi DeepSeek terbaru, dan dapatkan isolasi yang lebih kuat antara perubahan profil provider dan task yang sedang berjalan. -- **Perbaikan penting untuk eksekusi terminal** — Zoo kini menunggu perintah terminal selesai sebelum memulai langkah berikutnya, sehingga pekerjaan tidak saling tumpang tindih dan model tidak melanjutkan terlalu dini. -- Batching yang lebih cerdas mengelompokkan persetujuan tool terkait sambil tetap memisahkan permintaan yang tidak berkaitan. -- Pengiriman telemetri dan pengambilan cache model kini lebih tangguh saat terjadi kegagalan dan permintaan bersamaan. +- **Tiga model baru utama telah hadir** — gunakan model terbaru Gemini 3.7 Flash, GLM 5.3, dan Qwen3.8 Max, ditambah pembaruan reasoning, harga, dan cakupan provider DeepSeek V4. +- **Hubungkan ke NanoGPT** — gunakan penemuan model dinamis, streaming dan penyelesaian prompt, serta preferensi routing untuk kecepatan, harga, latensi, throughput, dukungan tool, dan caching. +- **Provider dan task yang lebih andal** — perbaikan meningkatkan pengaturan endpoint Azure OpenAI, batas output Kimi Code, penyimpanan judul riwayat task, serta impor/ekspor pengaturan Zoo. +- Destructive Command Guard kini mendukung Mac berbasis Intel. +- Pembaruan keamanan mengatasi kerentanan di `undici` dan Mermaid. ## Apa yang Bisa Zoo Code Lakukan Untuk ANDA? diff --git a/locales/it/README.md b/locales/it/README.md index c066da3456..7091aaca0c 100644 --- a/locales/it/README.md +++ b/locales/it/README.md @@ -47,13 +47,13 @@ Zoo Code parte dalle fondamenta create da Roo Code e continua ad ampliarle con: - **Workflow di terminale e modifica più affidabili** — correzioni per il completamento prematuro del terminale, le race condition dello stato delle attività, la gestione del contesto, la modifica dei diff e l'uso di strumenti specifici dei provider. - **Più controllo sul tuo workspace** — gestione delle regole, restrizioni MCP per modalità, controlli dei percorsi multi-root, opzioni di reasoning dei modelli e azioni per esaminare le modifiche al completamento. -## Novità in v3.76.0 +## Novità in v3.78.0 -- **Esegui attività più lunghe e senza interruzioni con Destructive Command Guard (DCG)** — DCG blocca i comandi pericolosi lasciando che Zoo continui a lavorare senza costringerti a premere continuamente i pulsanti di approvazione, con download e installazione rafforzati del binario gestito. -- **Controlli e affidabilità dei provider migliorati** — scegli la velocità di risposta di OpenAI Codex, usa le configurazioni DeepSeek aggiornate e approfitta di un isolamento più solido tra le modifiche ai profili provider e le attività in esecuzione. -- **Correzione critica dell'esecuzione nel terminale** — Zoo ora attende che i comandi del terminale terminino prima di iniziare il passaggio successivo, evitando sovrapposizioni di lavoro e la continuazione prematura del modello. -- Un raggruppamento più intelligente riunisce le approvazioni degli strumenti correlati mantenendo separate le richieste non correlate. -- L'invio della telemetria e il recupero della cache dei modelli sono più resilienti in caso di errori e richieste simultanee. +- **Sono arrivati tre importanti nuovi modelli** — usa i nuovissimi Gemini 3.7 Flash, GLM 5.3 e Qwen3.8 Max, oltre agli aggiornamenti di reasoning, prezzi e copertura dei provider per DeepSeek V4. +- **Connettiti a NanoGPT** — usa la scoperta dinamica dei modelli, streaming e completamenti dei prompt, con preferenze di routing per velocità, prezzo, latenza, throughput, supporto agli strumenti e caching. +- **Provider e task più affidabili** — le correzioni migliorano la configurazione degli endpoint Azure OpenAI, i limiti di output di Kimi Code, la conservazione dei titoli nella cronologia dei task e l'importazione/esportazione delle impostazioni Zoo. +- Destructive Command Guard ora supporta i Mac basati su Intel. +- Gli aggiornamenti di sicurezza risolvono vulnerabilità in `undici` e Mermaid. ## Cosa può fare Zoo Code per TE? diff --git a/locales/ja/README.md b/locales/ja/README.md index 36563af9af..bda6e078c2 100644 --- a/locales/ja/README.md +++ b/locales/ja/README.md @@ -46,13 +46,13 @@ Zoo Code は Roo Code が築いた基盤を引き継ぎ、次の機能で拡張 - **より信頼性の高いターミナルと編集ワークフロー** — ターミナルの早期完了、タスク状態の競合、コンテキスト管理、diff 編集、プロバイダー固有のツール利用に関する問題を修正。 - **ワークスペースをより細かく制御** — ルール管理、モードごとの MCP 制限、マルチルートのパス制御、モデルの reasoning オプション、完了時の変更レビュー操作を追加。 -## v3.76.0 の新機能 +## v3.78.0 の新機能 -- **Destructive Command Guard(DCG)で長時間のタスクを中断なく実行** — DCG が危険なコマンドをブロックし、承認ボタンを何度も押さなくても Zoo が作業を継続します。管理対象バイナリのダウンロードとインストールも強化されました。 -- **プロバイダーの制御性と信頼性を向上** — OpenAI Codex の応答速度を選択でき、更新された DeepSeek 設定を利用できます。プロバイダープロファイルの変更と実行中タスクの分離も強化されました。 -- **ターミナル実行の重要な修正** — Zoo はターミナルコマンドが完了するまで次のステップを開始しなくなり、作業の重複やモデルの早すぎる続行を防ぎます。 -- よりスマートなバッチ処理により、関連するツール承認をまとめながら、無関係なリクエストは分離します。 -- 障害発生時や同時リクエスト時でも、テレメトリ送信とモデルキャッシュ取得の安定性が向上しました。 +- **注目の新モデルが3つ登場** — 最新の Gemini 3.7 Flash、GLM 5.3、Qwen3.8 Max に加え、DeepSeek V4 の reasoning、価格、プロバイダー対応も更新されました。 +- **NanoGPT に接続** — 動的なモデル検出、ストリーミング、Prompt 補完に加え、速度、価格、レイテンシ、スループット、ツール対応、キャッシュに基づくルーティング設定を利用できます。 +- **プロバイダーとタスクの信頼性を向上** — Azure OpenAI エンドポイント設定、Kimi Code の出力上限、タスク履歴タイトルの保持、Zoo 設定のインポート/エクスポートを改善しました。 +- Destructive Command Guard が Intel 搭載 Mac に対応しました。 +- セキュリティアップデートにより `undici` と Mermaid の脆弱性を修正しました。 ## Zoo Codeがあなたのためにできること diff --git a/locales/ko/README.md b/locales/ko/README.md index 67e3547e2c..31d30f02c5 100644 --- a/locales/ko/README.md +++ b/locales/ko/README.md @@ -45,13 +45,13 @@ Zoo Code는 Roo Code가 만든 기반 위에서 다음 기능을 더하며 계 - **더 안정적인 터미널 및 편집 워크플로우** — 터미널 조기 완료, 작업 상태 경합, 컨텍스트 관리, diff 편집, 프로바이더별 도구 사용 문제를 수정. - **워크스페이스를 더 세밀하게 제어** — 규칙 관리, 모드별 MCP 제한, 멀티 루트 경로 제어, 모델 reasoning 옵션, 완료 시 변경 사항 검토 작업을 제공. -## v3.76.0의 새로운 기능 +## v3.78.0의 새로운 기능 -- **Destructive Command Guard(DCG)로 더 긴 작업을 중단 없이 실행** — DCG가 위험한 명령을 차단하는 동안 Zoo는 승인 버튼을 계속 누르지 않아도 작업을 이어가며, 관리형 바이너리의 다운로드와 설치도 강화됐어. -- **향상된 프로바이더 제어와 안정성** — OpenAI Codex 응답 속도를 선택하고, 업데이트된 DeepSeek 구성을 사용하며, 프로바이더 프로필 변경과 실행 중인 작업 사이의 더 강력한 격리를 활용할 수 있어. -- **중요한 터미널 실행 수정** — Zoo는 이제 터미널 명령이 끝날 때까지 기다린 후 다음 단계를 시작해서, 작업 중첩과 모델의 성급한 진행을 방지해. -- 더 스마트한 일괄 처리는 관련 도구 승인을 묶으면서 관련 없는 요청은 분리해. -- 장애와 동시 요청 상황에서도 텔레메트리 전송과 모델 캐시 가져오기가 더 안정적으로 동작해. +- **주요 신규 모델 3종이 출시되었습니다** — 완전히 새로운 Gemini 3.7 Flash, GLM 5.3, Qwen3.8 Max 모델과 업데이트된 DeepSeek V4 reasoning, 가격 및 프로바이더 지원을 사용해 보세요. +- **NanoGPT에 연결하세요** — 동적 모델 검색, 스트리밍 및 prompt completion과 함께 속도, 가격, 지연 시간, 처리량, 도구 지원, 캐싱을 기준으로 한 라우팅 설정을 사용할 수 있습니다. +- **더 안정적인 프로바이더와 작업** — Azure OpenAI endpoint 설정, Kimi Code 출력 제한, 작업 기록 제목 보존, Zoo 설정 가져오기/내보내기가 개선되었습니다. +- Destructive Command Guard가 이제 Intel 기반 Mac을 지원합니다. +- 보안 업데이트로 `undici`와 Mermaid의 취약점을 해결했습니다. ## Zoo Code가 당신을 위해 무엇을 할 수 있을까요? diff --git a/locales/nl/README.md b/locales/nl/README.md index a072400121..8af72a0103 100644 --- a/locales/nl/README.md +++ b/locales/nl/README.md @@ -47,13 +47,13 @@ Zoo Code bouwt voort op het fundament van Roo Code en breidt dit verder uit met: - **Betrouwbaardere terminal- en bewerkingsworkflows** — oplossingen voor voortijdige terminalvoltooiing, race conditions in taakstatussen, contextbeheer, diff-bewerking en providerspecifiek toolgebruik. - **Meer controle over je workspace** — regelbeheer, MCP-beperkingen per modus, padbeheer voor multi-root-workspaces, reasoning-opties voor modellen en acties om wijzigingen bij voltooiing te beoordelen. -## Nieuw in v3.76.0 +## Nieuw in v3.78.0 -- **Voer langere, ononderbroken taken uit met Destructive Command Guard (DCG)** — DCG blokkeert gevaarlijke opdrachten en laat Zoo ondertussen doorwerken zonder dat je steeds op goedkeuringsknoppen hoeft te drukken, ondersteund door beter beveiligde downloads en installatie van de beheerde binary. -- **Betere providerbediening en betrouwbaarheid** — kies de reactiesnelheid van OpenAI Codex, gebruik bijgewerkte DeepSeek-configuraties en profiteer van sterkere isolatie tussen wijzigingen aan providerprofielen en actieve taken. -- **Kritieke oplossing voor terminaluitvoering** — Zoo wacht nu tot terminalopdrachten zijn afgerond voordat de volgende stap begint, zodat werk niet overlapt en het model niet te vroeg doorgaat. -- Slimmere batching groepeert goedkeuringen voor gerelateerde tools en houdt niet-gerelateerde verzoeken gescheiden. -- Telemetrieverzending en het ophalen van de modelcache zijn beter bestand tegen fouten en gelijktijdige verzoeken. +- **Drie belangrijke nieuwe modellen zijn gearriveerd** — gebruik de gloednieuwe Gemini 3.7 Flash-, GLM 5.3- en Qwen3.8 Max-modellen, plus bijgewerkte reasoning, prijzen en providerondersteuning voor DeepSeek V4. +- **Maak verbinding met NanoGPT** — gebruik dynamische modeldetectie, streaming en promptaanvulling, plus routeringsvoorkeuren voor snelheid, prijs, latentie, doorvoer, toolondersteuning en caching. +- **Betrouwbaardere providers en taken** — oplossingen verbeteren de instelling van Azure OpenAI-endpoints, Kimi Code-uitvoerlimieten, het behouden van titels in de taakgeschiedenis en het importeren/exporteren van Zoo-instellingen. +- Destructive Command Guard ondersteunt nu Intel-gebaseerde Macs. +- Beveiligingsupdates verhelpen kwetsbaarheden in `undici` en Mermaid. ## Wat kan Zoo Code voor JOU doen? diff --git a/locales/pl/README.md b/locales/pl/README.md index 78e3ea9049..7a6133d4e9 100644 --- a/locales/pl/README.md +++ b/locales/pl/README.md @@ -45,13 +45,13 @@ Zoo Code rozwija fundament stworzony przez Roo Code i stale rozszerza go o: - **Bardziej niezawodne workflow terminala i edycji** — poprawki przedwczesnego kończenia poleceń terminala, race condition stanu zadań, zarządzania kontekstem, edycji diff i użycia narzędzi właściwych dla providerów. - **Większą kontrolę nad workspace** — zarządzanie regułami, ograniczenia MCP dla poszczególnych trybów, kontrolę ścieżek multi-root, opcje reasoning modeli i akcje przeglądu zmian po ukończeniu. -## Nowości w v3.76.0 +## Nowości w v3.78.0 -- **Uruchamiaj dłuższe, nieprzerywane zadania z Destructive Command Guard (DCG)** — DCG blokuje niebezpieczne polecenia, a Zoo może kontynuować pracę bez ciągłego klikania przycisków zatwierdzania. Pobieranie i instalacja zarządzanego pliku binarnego zostały dodatkowo zabezpieczone. -- **Lepsze sterowanie providerami i większa niezawodność** — wybieraj szybkość odpowiedzi OpenAI Codex, korzystaj ze zaktualizowanych konfiguracji DeepSeek i z mocniejszej izolacji między zmianami profili providerów a działającymi zadaniami. -- **Krytyczna poprawka wykonywania poleceń terminala** — Zoo czeka teraz na zakończenie poleceń terminala przed rozpoczęciem kolejnego kroku, co zapobiega nakładaniu się pracy i przedwczesnemu kontynuowaniu przez model. -- Inteligentniejsze grupowanie łączy zatwierdzenia powiązanych narzędzi, pozostawiając niepowiązane żądania osobno. -- Przesyłanie telemetrii i pobieranie pamięci podręcznej modeli są bardziej odporne na błędy i równoczesne żądania. +- **Pojawiły się trzy ważne nowe modele** — korzystaj z zupełnie nowych Gemini 3.7 Flash, GLM 5.3 i Qwen3.8 Max oraz zaktualizowanego reasoning, cen i obsługi providerów dla DeepSeek V4. +- **Połącz się z NanoGPT** — korzystaj z dynamicznego wykrywania modeli, streamingu i uzupełniania promptów oraz preferencji routingu według szybkości, ceny, opóźnienia, przepustowości, obsługi narzędzi i cache. +- **Bardziej niezawodni providerzy i zadania** — poprawki usprawniają konfigurację endpointów Azure OpenAI, limity wyjścia Kimi Code, zachowywanie tytułów historii zadań oraz import/eksport ustawień Zoo. +- Destructive Command Guard obsługuje teraz komputery Mac z procesorami Intel. +- Aktualizacje zabezpieczeń usuwają luki w `undici` i Mermaid. ## Co Zoo Code może zrobić dla CIEBIE? diff --git a/locales/pt-BR/README.md b/locales/pt-BR/README.md index d605af8551..dfdd18c4e8 100644 --- a/locales/pt-BR/README.md +++ b/locales/pt-BR/README.md @@ -47,13 +47,13 @@ O Zoo Code aproveita a base criada pelo Roo Code e continua ampliando-a com: - **Workflows de terminal e edição mais confiáveis** — correções para encerramento prematuro do terminal, race conditions no estado das tarefas, gerenciamento de contexto, edição de diff e uso de ferramentas específicas de cada provider. - **Mais controle sobre seu workspace** — gerenciamento de regras, restrições de MCP por modo, controles de caminhos multi-root, opções de reasoning dos modelos e ações para revisar alterações ao concluir uma tarefa. -## Novidades na v3.76.0 +## Novidades na v3.78.0 -- **Execute tarefas mais longas e sem interrupções com o Destructive Command Guard (DCG)** — o DCG bloqueia comandos perigosos enquanto permite que o Zoo continue trabalhando sem você precisar apertar botões de aprovação o tempo todo, com downloads e instalação reforçados do binário gerenciado. -- **Melhores controles e confiabilidade dos providers** — escolha a velocidade de resposta do OpenAI Codex, use configurações atualizadas do DeepSeek e conte com um isolamento mais forte entre alterações nos perfis de provider e tarefas em execução. -- **Correção crítica na execução do terminal** — agora o Zoo espera os comandos do terminal terminarem antes de iniciar a próxima etapa, evitando trabalho sobreposto e a continuação prematura do modelo. -- Um agrupamento mais inteligente reúne aprovações de ferramentas relacionadas e mantém solicitações não relacionadas separadas. -- O envio de telemetria e a busca do cache de modelos estão mais resilientes a falhas e solicitações simultâneas. +- **Três novos modelos importantes chegaram** — use os novíssimos Gemini 3.7 Flash, GLM 5.3 e Qwen3.8 Max, além das atualizações de reasoning, preços e cobertura de providers do DeepSeek V4. +- **Conecte-se ao NanoGPT** — use descoberta dinâmica de modelos, streaming e conclusão de prompts, com preferências de roteamento por velocidade, preço, latência, throughput, suporte a ferramentas e cache. +- **Providers e tarefas mais confiáveis** — as correções melhoram a configuração de endpoints do Azure OpenAI, os limites de saída do Kimi Code, a preservação de títulos no histórico de tarefas e a importação/exportação das configurações do Zoo. +- O Destructive Command Guard agora oferece suporte a Macs com processadores Intel. +- Atualizações de segurança corrigem vulnerabilidades no `undici` e no Mermaid. ## O que o Zoo Code pode fazer por VOCÊ? diff --git a/locales/ru/README.md b/locales/ru/README.md index d7ac72f622..e5e6d66198 100644 --- a/locales/ru/README.md +++ b/locales/ru/README.md @@ -47,13 +47,13 @@ Zoo Code развивает основу, созданную Roo Code, и про - **Более надёжные рабочие процессы в терминале и редакторе** — исправления преждевременного завершения команд, гонок состояния задач, управления контекстом, редактирования diff и использования инструментов отдельных провайдеров. - **Больше контроля над рабочей областью** — управление правилами, ограничения MCP для отдельных режимов, управление путями в многоуровневых рабочих областях, параметры reasoning моделей и действия для проверки изменений после завершения. -## Что нового в v3.76.0 +## Что нового в v3.78.0 -- **Выполняй более длительные задачи без перерывов с Destructive Command Guard (DCG)** — DCG блокирует опасные команды, позволяя Zoo продолжать работу без постоянного нажатия кнопок одобрения; загрузка и установка управляемого бинарного файла дополнительно защищены. -- **Улучшенное управление провайдерами и надёжность** — выбирай скорость ответа OpenAI Codex, используй обновлённые конфигурации DeepSeek и более строгую изоляцию изменений профилей провайдеров от выполняющихся задач. -- **Критическое исправление выполнения команд в терминале** — теперь Zoo ждёт завершения команд перед переходом к следующему шагу, предотвращая наложение работ и преждевременное продолжение модели. -- Более умная группировка объединяет одобрения связанных инструментов, сохраняя несвязанные запросы раздельными. -- Отправка телеметрии и получение кеша моделей стали устойчивее к сбоям и одновременным запросам. +- **Появились три важных новых модели** — используй совершенно новые Gemini 3.7 Flash, GLM 5.3 и Qwen3.8 Max, а также обновлённые reasoning, цены и поддержку провайдеров для DeepSeek V4. +- **Подключайся к NanoGPT** — используй динамическое обнаружение моделей, streaming и дополнение Prompt, а также настройки маршрутизации по скорости, цене, задержке, пропускной способности, поддержке инструментов и кешированию. +- **Более надёжные провайдеры и задачи** — исправления улучшают настройку endpoint Azure OpenAI, лимиты вывода Kimi Code, сохранение заголовков истории задач и импорт/экспорт настроек Zoo. +- Destructive Command Guard теперь поддерживает Mac на базе Intel. +- Обновления безопасности устраняют уязвимости в `undici` и Mermaid. ## Что Zoo Code может сделать для ВАС? diff --git a/locales/tr/README.md b/locales/tr/README.md index 537270b37d..5f90729546 100644 --- a/locales/tr/README.md +++ b/locales/tr/README.md @@ -47,13 +47,13 @@ Zoo Code, Roo Code'un oluşturduğu temel üzerine inşa ediliyor ve bu temeli - **Daha güvenilir terminal ve düzenleme iş akışları** — terminalin erken tamamlanması, görev durumu yarış koşulları, bağlam yönetimi, diff düzenleme ve sağlayıcıya özel araç kullanımı için düzeltmeler. - **Çalışma alanın üzerinde daha fazla kontrol** — kural yönetimi, mod başına MCP kısıtlamaları, çok köklü yol denetimleri, model reasoning seçenekleri ve tamamlanan değişiklikleri inceleme eylemleri. -## v3.76.0'daki Yenilikler +## v3.78.0'daki Yenilikler -- **Destructive Command Guard (DCG) ile daha uzun ve kesintisiz görevler çalıştır** — DCG tehlikeli komutları engellerken Zoo'nun sürekli onay düğmelerine basmana gerek kalmadan çalışmayı sürdürmesini sağlar; yönetilen ikili dosyanın indirilmesi ve kurulumu da güçlendirildi. -- **Daha iyi sağlayıcı denetimleri ve güvenilirlik** — OpenAI Codex yanıt hızını seç, güncellenmiş DeepSeek yapılandırmalarını kullan ve sağlayıcı profili değişiklikleriyle çalışan görevler arasındaki daha güçlü yalıtımdan yararlan. -- **Kritik terminal yürütme düzeltmesi** — Zoo artık sonraki adıma başlamadan önce terminal komutlarının bitmesini bekliyor; böylece işler çakışmıyor ve model erken devam etmiyor. -- Daha akıllı gruplama, ilişkili araç onaylarını bir araya getirirken ilgisiz istekleri ayrı tutuyor. -- Telemetri teslimi ve model önbelleğini getirme işlemleri, hatalar ve eş zamanlı istekler karşısında daha dayanıklı. +- **Üç önemli yeni model geldi** — yepyeni Gemini 3.7 Flash, GLM 5.3 ve Qwen3.8 Max modellerini, ayrıca güncellenmiş DeepSeek V4 reasoning, fiyatlandırma ve sağlayıcı kapsamını kullan. +- **NanoGPT'ye bağlan** — dinamik model keşfi, streaming ve Prompt tamamlama ile hız, fiyat, gecikme, throughput, araç desteği ve caching için yönlendirme tercihlerini kullan. +- **Daha güvenilir sağlayıcılar ve görevler** — düzeltmeler Azure OpenAI endpoint kurulumunu, Kimi Code çıktı sınırlarını, görev geçmişi başlıklarının korunmasını ve Zoo ayarlarının içe/dışa aktarımını iyileştiriyor. +- Destructive Command Guard artık Intel tabanlı Mac'leri destekliyor. +- Güvenlik güncellemeleri `undici` ve Mermaid'deki güvenlik açıklarını gideriyor. ## Zoo Code SİZİN İçin Ne Yapabilir? diff --git a/locales/vi/README.md b/locales/vi/README.md index 9ad3fed482..f2a95db23d 100644 --- a/locales/vi/README.md +++ b/locales/vi/README.md @@ -46,13 +46,13 @@ Zoo Code phát triển trên nền tảng do Roo Code tạo ra và tiếp tục - **Workflow terminal và chỉnh sửa đáng tin cậy hơn** — sửa lỗi terminal hoàn tất quá sớm, xung đột trạng thái tác vụ, quản lý ngữ cảnh, chỉnh sửa diff và sử dụng công cụ riêng của từng provider. - **Kiểm soát workspace tốt hơn** — quản lý quy tắc, giới hạn MCP theo từng chế độ, kiểm soát đường dẫn multi-root, tùy chọn reasoning của model và thao tác xem lại thay đổi khi hoàn tất. -## Điểm mới trong v3.76.0 +## Điểm mới trong v3.78.0 -- **Chạy tác vụ lâu hơn, không bị gián đoạn với Destructive Command Guard (DCG)** — DCG chặn các lệnh nguy hiểm trong khi vẫn để Zoo tiếp tục làm việc mà bạn không phải liên tục bấm nút phê duyệt, đồng thời tăng cường bảo mật cho việc tải xuống và cài đặt binary được quản lý. -- **Kiểm soát provider và độ tin cậy tốt hơn** — chọn tốc độ phản hồi của OpenAI Codex, dùng cấu hình DeepSeek đã cập nhật và hưởng lợi từ khả năng cách ly mạnh hơn giữa thay đổi hồ sơ provider với tác vụ đang chạy. -- **Bản sửa lỗi quan trọng cho việc chạy lệnh terminal** — Zoo giờ sẽ chờ lệnh terminal hoàn tất trước khi bắt đầu bước tiếp theo, ngăn công việc chồng chéo và model tiếp tục quá sớm. -- Cơ chế gom nhóm thông minh hơn sẽ nhóm các phê duyệt công cụ liên quan và giữ riêng những yêu cầu không liên quan. -- Việc gửi telemetry và tải cache model ổn định hơn khi có lỗi hoặc nhiều yêu cầu đồng thời. +- **Ba model mới quan trọng đã xuất hiện** — sử dụng các model hoàn toàn mới Gemini 3.7 Flash, GLM 5.3 và Qwen3.8 Max, cùng reasoning, giá và phạm vi provider được cập nhật cho DeepSeek V4. +- **Kết nối với NanoGPT** — sử dụng khám phá model động, streaming và hoàn thành Prompt, cùng tùy chọn định tuyến theo tốc độ, giá, độ trễ, throughput, hỗ trợ tool và caching. +- **Provider và task đáng tin cậy hơn** — các bản sửa lỗi cải thiện thiết lập endpoint Azure OpenAI, giới hạn đầu ra Kimi Code, giữ nguyên tiêu đề lịch sử task và nhập/xuất cài đặt Zoo. +- Destructive Command Guard hiện hỗ trợ máy Mac dùng chip Intel. +- Các bản cập nhật bảo mật khắc phục lỗ hổng trong `undici` và Mermaid. ## Zoo Code có thể làm gì cho BẠN? diff --git a/locales/zh-CN/README.md b/locales/zh-CN/README.md index 886b4123ff..4fba2e03de 100644 --- a/locales/zh-CN/README.md +++ b/locales/zh-CN/README.md @@ -43,13 +43,13 @@ Zoo Code 基于 Roo Code 打下的基础持续扩展,新增了: - **更可靠的终端和编辑工作流** — 修复终端过早完成、任务状态竞争、上下文管理、差异更新编辑和提供商专用工具调用等问题。 - **更全面的工作区控制** — 支持规则管理、按模式限制 MCP、多根工作区路径控制、模型推理选项和完成后的变更审查操作。 -## v3.76.0 新增内容 +## v3.78.0 新增内容 -- **通过 Destructive Command Guard (DCG) 长时间、不间断地运行任务** — DCG 会阻止危险命令,同时让 Zoo 继续工作,无需你反复点击批准按钮;托管二进制文件的下载和安装也经过了安全加固。 -- **更完善的提供商控制和可靠性** — 可选择 OpenAI Codex 响应速度、使用更新后的 DeepSeek 配置,并在提供商配置变更与运行中任务之间获得更强的隔离。 -- **重要的终端运行修复** — Zoo 现在会等待终端命令完成后再开始下一步,避免工作重叠和模型过早继续。 -- 更智能的批处理会合并相关工具的批准请求,同时将不相关的请求分开处理。 -- 遇到故障和并发请求时,遥测数据传输与模型缓存获取更加稳定可靠。 +- **三款重磅新模型现已推出** — 使用全新的 Gemini 3.7 Flash、GLM 5.3 和 Qwen3.8 Max 模型,以及更新后的 DeepSeek V4 推理、定价和提供商覆盖。 +- **连接 NanoGPT** — 使用动态模型发现、流式传输和 Prompt 补全,并按速度、价格、延迟、吞吐量、工具支持和缓存设置路由偏好。 +- **更可靠的提供商和任务** — 修复改进了 Azure OpenAI endpoint 设置、Kimi Code 输出限制、任务历史标题保留以及 Zoo 设置的导入/导出。 +- Destructive Command Guard 现在支持基于 Intel 的 Mac。 +- 安全更新修复了 `undici` 和 Mermaid 中的漏洞。 ## Zoo Code 能为您做什么? diff --git a/locales/zh-TW/README.md b/locales/zh-TW/README.md index c54bc3efc3..215a3886b6 100644 --- a/locales/zh-TW/README.md +++ b/locales/zh-TW/README.md @@ -43,13 +43,13 @@ Zoo Code 以 Roo Code 建立的基礎持續擴充,新增了: - **更可靠的終端機與編輯工作流程** — 修正終端機過早完成、工作狀態競爭、上下文管理、差異更新編輯和供應商專用工具使用等問題。 - **更完整的工作區控制** — 支援規則管理、依模式限制 MCP、多根工作區路徑控制、模型推理選項,以及完成後的變更檢閱操作。 -## v3.76.0 新功能 +## v3.78.0 新功能 -- **透過 Destructive Command Guard (DCG) 長時間、不間斷地執行工作** — DCG 會封鎖危險命令,同時讓 Zoo 繼續工作,不必一直按核准按鈕;受管理二進位檔的下載與安裝也經過安全強化。 -- **更完善的供應商控制與可靠性** — 可選擇 OpenAI Codex 回應速度、使用更新後的 DeepSeek 設定,並強化供應商設定檔變更與執行中工作之間的隔離。 -- **重要的終端機執行修正** — Zoo 現在會等待終端機命令完成後再開始下一步,避免工作重疊及模型過早繼續。 -- 更聰明的批次處理會合併相關工具的核准請求,同時將不相關的請求分開處理。 -- 發生錯誤或同時收到多個請求時,遙測資料傳送與模型快取擷取更加穩定可靠。 +- **三款重磅新模型現已推出** — 使用全新的 Gemini 3.7 Flash、GLM 5.3 和 Qwen3.8 Max 模型,以及更新後的 DeepSeek V4 推理、定價與供應商支援。 +- **連接 NanoGPT** — 使用動態模型探索、串流與 Prompt 補全,並依速度、價格、延遲、吞吐量、工具支援和快取設定路由偏好。 +- **更可靠的供應商與任務** — 修正改善了 Azure OpenAI endpoint 設定、Kimi Code 輸出限制、任務歷史標題保留,以及 Zoo 設定的匯入/匯出。 +- Destructive Command Guard 現在支援 Intel 架構的 Mac。 +- 安全性更新修正了 `undici` 與 Mermaid 中的漏洞。 ## Zoo Code 能為您做什麼? diff --git a/src/CHANGELOG.md b/src/CHANGELOG.md new file mode 100644 index 0000000000..72bfdbd415 --- /dev/null +++ b/src/CHANGELOG.md @@ -0,0 +1,3852 @@ +# Zoo Code Changelog + +## [3.78.0] + +### Minor Changes + +- Add NanoGPT as a configurable provider with dynamic model discovery, streaming and prompt completions, and routing preferences for speed, price, latency, throughput, tool support, and caching (PR #1239 by @taltas) +- Add the new Gemini 3.7 Flash model to Google Gemini and Vertex AI with a 1M context window, multimodal input, prompt caching, and configurable reasoning (PR #1241 by @app/zoomote) +- Add the new GLM 5.3 model to Z AI coding plans and OpenCode Go with a 1M context window, prompt caching, and extended reasoning controls (PR #1244 by @app/zoomote) +- Add the new Qwen3.8 Max model to OpenCode Go with multimodal input, caching, streamed reasoning, and Anthropic Messages routing (PR #1245 by @app/zoomote) +- Fix Azure OpenAI resource endpoints and improve Azure-specific setup guidance in OpenAI Compatible settings (#1191 by @edelauna, PR #1192 by @app/zoomote) +- Preserve task-history titles when rapidly navigating away before a task's messages finish loading (#1180 by @edelauna, PR #1181 by @edelauna) +- Correct Kimi Code output-token defaults and honor model limits returned by the server (#1215 by @myk1yt, PR #1217 by @myk1yt) +- Update DeepSeek V4 Pro reasoning efforts and normalize medium, high, and extended reasoning mappings (#1235 by @WHMHammer, PR #1236 by @WHMHammer) +- Correct DeepSeek V4 pricing and expand provider coverage for the V4 Pro 0813 checkpoint (PR #1237 by @app/zoomote) +- Rename the default settings import/export file to `zoo-code-settings.json` throughout the extension (#1176 by @Rafael-Silva-Oliveira, PR #1177 by @Rafael-Silva-Oliveira) +- Add Destructive Command Guard support for Intel-based macOS systems (PR #1213 by @app/zoomote) +- Update `undici` to 6.28.0 to address security vulnerabilities (PR #1161 by @app/renovate) +- Update Mermaid to 11.16.1 to address a prototype-pollution vulnerability (PR #1193 by @app/renovate) +- Record tool usage centrally to prevent duplicate telemetry and sanitize raw tool names (PR #1073 by @edelauna) +- Canonicalize shared provider settings identifiers and add registry-alignment coverage (PR #1109 by @WebMad) +- Canonicalize provider identifiers across CLI configuration, environment mappings, and model selection (PR #1110 by @WebMad) +- Complete the webview migration to canonical provider identifiers across provider settings and routing (PR #1141 by @WebMad) +- Use canonical provider identifiers throughout API options and add focused interaction coverage (PR #1146 by @WebMad) +- Canonicalize provider model configuration identifiers and provider-specific settings behavior (PR #1147 by @WebMad) +- Migrate model-selection UI hooks to canonical provider identifiers (PR #1148 by @WebMad) +- Reuse the retired Roo provider identifier registry while preserving migration compatibility (PR #1166 by @WebMad) +- Introduce typed shared test utilities for API options, filesystem mocks, reset operations, VS Code doubles, and webview rendering (PR #1171 by @app/zoomote) +- Reuse shared API option factories across Requesty, OpenRouter, and Vercel AI Gateway provider tests (PR #1178 by @app/zoomote) +- Reuse the shared Responses client mock in X.AI provider tests (PR #1182 by @app/zoomote) +- Reuse shared VS Code context, URI, and reset helpers in custom-mode configuration tests (PR #1190 by @app/zoomote) +- Reuse shared reset helpers across code-index embedder tests (PR #1194 by @app/zoomote) +- Reuse shared config test helpers and remove obsolete lint suppressions (PR #1195 by @app/zoomote) +- Reuse shared webview render helpers across focused chat tests (PR #1196 by @app/zoomote) +- Reuse shared reset helpers across terminal integration tests (PR #1197 by @app/zoomote) +- Reuse shared VS Code and reset helpers in settings import/export tests (PR #1198 by @app/zoomote) +- Reuse shared reset helpers across additional code-index tests (PR #1199 by @app/zoomote) +- Complete another batch of shared reset-helper adoption in code-index tests (PR #1200 by @app/zoomote) +- Finish reset-helper adoption in Semble and terminal test suites (PR #1201 by @app/zoomote) +- Complete shared reset-helper adoption across provider tests (PR #1202 by @app/zoomote) +- Reuse shared webview render helpers across chat and settings tests (PR #1203 by @app/zoomote) +- Complete shared webview render-helper adoption in the remaining settings tests (PR #1204 by @app/zoomote) +- Merge the v3.76.0 release preparation branch into `main` (PR #1173 by @navedmerchant) + +## [3.76.0] + +### Minor Changes + +- Add Destructive Command Guard as an opt-in safety layer that blocks dangerous terminal commands while allowing longer tasks to continue without repeated approvals (#1057 by @navedmerchant, PR #1061 by @navedmerchant) +- Streamline Destructive Command Guard approval handling so safe commands can continue with fewer interruptions (#1058 by @navedmerchant, PR #1062 by @navedmerchant) +- Harden Destructive Command Guard binary installation and platform handling (#1056 by @navedmerchant, PR #1060 by @navedmerchant) +- Strengthen shared managed-binary downloads, archive extraction, verification, and atomic installation (#1055 by @navedmerchant, PR #1059 by @navedmerchant) +- Fix Zoo starting the next step before a terminal command finishes (PR #1145 by @app/zoomote) +- Add an OpenAI Codex response-speed selector to provider settings (PR #1076 by @WebMad) +- Update DeepSeek model configurations and defaults (#1082 by @WHMHammer, PR #1083 by @WHMHammer) +- Isolate each task's provider configuration from changes to the currently focused provider state (PR #1085 by @edelauna) +- Isolate provider-profile mutations from running tasks to prevent mid-task configuration changes (PR #1087 by @edelauna) +- Group nearby, related tool approval requests while keeping unrelated requests separate (#1004 by @easonLiangWorldedtech, PR #1005 by @easonLiangWorldedtech) +- Add telemetry circuit breaking and drain pending events during shutdown for more reliable, bounded delivery (PR #1070 by @edelauna) +- Aggregate task-completion telemetry using incremental delta installments (PR #1071 by @edelauna) +- Deduplicate concurrent model-cache fetches and throttle telemetry for empty provider responses (PR #1072 by @edelauna) +- Fix Semble archive extraction on Windows by safely encoding the extraction command (#1167 by @navedmerchant, PR #1168 by @navedmerchant) +- Introduce shared provider-stream test utilities to reduce duplicated stream setup (PR #1086 by @app/zoomote) +- Reuse the shared webview query-client helper in tests (PR #1088 by @app/zoomote) +- Migrate Requesty provider tests to shared stream helpers (PR #1089 by @app/zoomote) +- Migrate Unbound provider tests to shared stream helpers (PR #1090 by @app/zoomote) +- Migrate OpenAI-family provider tests to shared stream helpers (PR #1091 by @app/zoomote) +- Migrate base OpenAI-compatible provider tests to shared stream helpers (PR #1092 by @app/zoomote) +- Migrate OpenAI provider tests to shared stream helpers (PR #1093 by @app/zoomote) +- Migrate Anthropic Vertex provider tests to shared stream helpers (PR #1094 by @app/zoomote) +- Migrate LiteLLM and Z.ai provider tests to shared stream helpers (PR #1095 by @app/zoomote) +- Migrate Friendli, OpenCode Go, and MiMo provider tests to shared stream helpers (PR #1102 by @app/zoomote) +- Migrate Qwen, LM Studio, and Fireworks provider tests to shared stream helpers (PR #1103 by @app/zoomote) +- Migrate Kenari, MiniMax, Vercel, and Mistral provider tests to shared stream helpers (PR #1105 by @app/zoomote) +- Finish the provider-stream test-helper rollout across the remaining provider suites (PR #1169 by @app/zoomote) +- Merge the v3.74.0 release preparation branch into `main` (PR #1081 by @taltas) + +## [3.74.0] + +### Minor Changes + +- Add Fast priority mode for OpenAI Codex, persisting the selection and sending it with requests (PR #1063 by @WebMad) +- Add higher reasoning-effort options for OpenAI-compatible models (#882 by @MINLEGO, PR #1051 by @ivanarifin) +- Fetch router-provider model metadata before making context-management decisions (PR #1053 by @JamesRobert20) +- Make Ollama model refreshes reliable, surface refresh errors, and use the base URL currently being edited (#877 by @navedmerchant, PR #878 by @navedmerchant) +- Fix Amazon Bedrock DNS resolution when using a corporate proxy (#905 by @LouisClt, PR #906 by @LouisClt) +- Add reasoning-parameter support to the Friendli provider (PR #886 by @Lee-Si-Yoon) +- Keep Save-managed settings in the local editing buffer until the user explicitly saves (#862 by @JunyongParkDev, PR #872 by @JunyongParkDev) +- Stop prompting about command output after short foreground commands have already completed (#1042 by @edelauna, PR #1043 by @app/zoomote) +- Keep Architect mode plans workspace-relative so creating `./plans` does not fail on read-only filesystem roots (#965 by @juneleung, PR #968 by @app/zoomote) +- Replace remaining user-facing Roo branding with Zoo branding (#551 by @proyectoauraorg, PR #971 by @rrewll) +- Introduce a semaphore-based task scheduler for controlled task execution (#358 by @edelauna, PR #1031 by @edelauna) +- Introduce `TaskRegistry` and migrate task-stack management to it (#367 by @edelauna, PR #1014 by @edelauna) +- Complete the API provider migration to canonical provider identifiers (#955 by @WebMad, PR #1012 by @WebMad) +- Use canonical provider identifiers for default model definitions (#954 by @WebMad, PR #991 by @WebMad) +- Use canonical provider identifiers for API model caches (#957 by @WebMad, PR #1020 by @WebMad) +- Use canonical provider identifiers in shared profile settings (#956 by @WebMad, PR #1019 by @WebMad) +- Use canonical provider identifiers throughout extension-core flows (#958 by @WebMad, PR #1022 by @WebMad) +- Use canonical provider identifiers throughout the webview (#959 by @WebMad, PR #1023 by @WebMad) +- Finish the repository-wide canonical provider identifier audit (#960 by @WebMad, PR #1030 by @WebMad) +- Centralize API service-tier types and helpers (PR #1040 by @WebMad) +- Support the platform-package layout introduced by `@vscode/ripgrep` 1.18 and later (#1024 by @saravanaraj0078-lab, PR #1032 by @edelauna) +- Update `shell-quote` to 1.9.0 to incorporate security fixes (PR #986 by @app/renovate) +- Update the development and build toolchain to Node.js 22.23.1 LTS (PR #743 by @app/renovate) +- Add a Playwright visual-regression harness for webview components (#515 by @edelauna, PR #526 by @edelauna) +- Enforce the no-floating-promises lint ratchet in `core/webview` (#949 by @edelauna, PR #950 by @morgan-coded) +- Harden the end-to-end workflow against transient VS Code binary download failures (#1044 by @edelauna, PR #1045 by @app/zoomote) +- Isolate mocked subtask fixtures to prevent flaky parent-resume tests (#1001 by @app/zoomote, PR #1002 by @app/zoomote) +- Prevent cancelled delayed mock streams from leaking between subtask end-to-end tests (PR #1074 by @app/zoomote) +- Merge the v3.72.0 release preparation branch into `main` (PR #1013 by @navedmerchant) + +## [3.72.0] + +### Minor Changes + +- Add the Moonshot provider with live model discovery, streaming, model metadata, and a model picker (PR #857 by @grizmin) +- Add the Kimi Code provider with OAuth device-flow authentication (PR #945 by @taltas) +- Add Claude Opus 5 support across all providers (PR #1010 by @app/zoomote) +- Add Kimi K3 to the Moonshot and OpenCode Go providers (#932 by @navedmerchant, PR #996 by @app/zoomote) +- Add Gemini 3.6 Flash model support (PR #975 by @app/zoomote) +- Add MiniMax-M3 model support (#888 by @RayWinter0816, PR #946 by @app/zoomote) +- Add a safe way to abandon interrupted subtasks by severing stale parent-child links and surfacing delegation status (#559 by @edelauna, PR #935 by @edelauna) +- Add Dart support to codebase indexing (#940 by @WebMad, PR #941 by @WebMad) +- Fix codebase indexing for plain-text files (#931 by @tool-buddy, PR #938 by @WebMad) +- Enable image input for DeepSeek V4 models (#964 by @grizmin, PR #963 by @grizmin) +- Fix ChatGPT OAuth requests for GPT-5.6 Luna being rejected by the Codex backend (PR #889 by @taltas) +- Preserve `reasoning_content` for known reasoning model families when using LiteLLM (#891 by @daewoongoh, PR #899 by @daewoongoh) +- Fix task-history cache invalidation races by routing `invalidate()` and `invalidateAll()` through the task-history lock (#698 by @edelauna, PR #912 by @morgan-coded) +- Fix Settings mode changes by synchronizing the local `cachedState` editing buffer (#914 by @easonLiangWorldedtech, PR #925 by @easonLiangWorldedtech) +- Dismiss the welcome screen after successful Zoo Gateway sign-in (#961 by @JohnCanty, PR #962 by @JamesRobert20) +- Add `CompletePromptOptions` to the `completePrompt` API so callers can configure prompt completion (#615 by @edelauna, PR #901 by @easonLiangWorldedtech) +- Centralize provider identifiers into canonical shared types (#951 by @WebMad, PR #952 by @WebMad) +- Refactor provider categories to use canonical provider identifiers (PR #989 by @WebMad) +- Remove obsolete MCP server-creation translations (#895 by @edelauna, PR #943 by @WebMad) +- Add regression coverage for resuming interrupted subtasks (#566 by @myk1yt, PR #911 by @edelauna) +- Upload coverage reports as GitHub Actions artifacts to simplify CI debugging (PR #939 by @app/zoomote) +- Update `esbuild-wasm` to v0.28.1 (PR #829 by @app/renovate) + +## [3.70.0] + +### Minor Changes + +- Add Kenari as a first-class provider, an Indonesian OpenAI-compatible AI gateway billed in Rupiah covering Claude, GPT, DeepSeek, GLM, Kimi and more (#792 by @doedja, PR #793 by @doedja) +- Add OpenAI GPT-5.6 family support (sol, terra, luna) across both OpenAI Codex and OpenAI Native provider paths (#871 by @xRaTcHeT302, PR #876 by @navedmerchant) +- Add Grok 4.5 support and fix a latent xAI reasoning-effort format bug affecting Grok 4 Mini (#866 by @navedmerchant, PR #867 by @navedmerchant) +- Surface the context-compaction button and context window progress bar in the collapsed task header so context pressure can be monitored and acted on without expanding it (#606 by @awschmeder, PR #680 by @awschmeder) +- Fix(terminal): fix output loss and premature task completion on cold terminals by reading command output only after shell execution actually starts (#800 by @juneleung, PR #834 by @edelauna) +- Fix(zoo-gateway): enable image attach for Zoo Gateway and Vercel AI Gateway models based on live vision-capability tags instead of a static allowlist (PR #897 by @JamesRobert20) +- Chore(deps): routine dependency updates (PRs #807-#828 by @app/renovate) + +## [3.68.0] + +### Minor Changes + +- Add Friendli provider with GLM-5.2 support for another hosted way to use the latest GLM model (#722 by @Lee-Si-Yoon, PR #721 by @Lee-Si-Yoon) +- Add native thinking/reasoning support for Ollama models to preserve reasoning output end-to-end (#831 by @navedmerchant, PR #832 by @navedmerchant) +- Fix(anthropic): honor custom `apiModelId` selections instead of silently defaulting to `claude-sonnet-4-5` (#418 by @tatianadenel-devops, #843 by @grizmin, PR #842 by @grizmin) +- Fix(ollama): correctly handle tool results and prevent premature context condensing (#847 by @navedmerchant, PR #848 by @navedmerchant) +- Improve Anthropic Vertex Claude content block handling for more reliable responses (#788 by @daewoongoh, PR #789 by @daewoongoh) +- Fix(task-lifecycle): preserve the parent-child link when a delegated subtask is interrupted (#560 by @edelauna, PR #787 by @edelauna) +- Refactor: remove the deprecated `openai-error-handler` shim and use the shared `error-handler` directly (#766 by @daewoongoh, PR #767 by @daewoongoh) +- Feat(nightly-publish): publish Open VSX pre-releases and skip nightly publish on release merges (#784 by @edelauna, PR #790 by @edelauna) +- Fix(ci): don't skip fork-PR label reconciliation on scheduled and manual runs (PR #234 by @app/roomote) +- Fix(label-pr-review-state): detect merge conflicts and label PRs with `has-conflicts` (PR #269 by @app/roomote) +- Chore(deps): update the `github/codeql-action` digest to `411c4c9` (PR #803 by @app/renovate) +- Chore(deps): update `@types/react` to `v18.3.31` (PR #805 by @app/renovate) +- Chore(deps): update `axios` to `v1.18.1` (PR #806 by @app/renovate) +- Chore: merge the v3.66.0 release preparation branch into `main` (PR #795 by @navedmerchant) + +## [3.66.0] + +### Minor Changes + +- Add Claude Sonnet 5 support across Anthropic, Bedrock, and Vertex providers (#777 by @navedmerchant, PR #778 by @navedmerchant) +- Upgrade Semble to v0.4.1 with flattened result parsing and localized status messages (#733 by @navedmerchant, PR #734 by @navedmerchant) +- Add task-lifecycle status transition guard and startup delegation reconciliation to prevent invalid task state transitions (#366 by @edelauna, PR #692 by @edelauna) +- Fix: LiteLLM cache key collision and silent fallback to a non-existent default model (#638 by @awschmeder, PR #647 by @awschmeder) +- Fix: reliable auto context condensing for the VS Code Language Model API (#714 by @simurg79, PR #710 by @simurg79) +- Fix(ThinkingBudget): support `xhigh` and all extended reasoning effort values (#713 by @6rz6, PR #774 by @edelauna) +- Fix(deepseek): round-trip `reasoning_content` in thinking mode to prevent 400 errors (#201 by @leosdad, PR #775 by @edelauna) +- Fix(gemini): base64-encode `thoughtSignature` bypass token to fix the Vertex AI empty-response loop (#536 by @edelauna, PR #776 by @edelauna) +- Fix: provider cache reset after settings import (#689 by @JunyongParkDev, PR #726 by @JunyongParkDev) +- Fix(delegation): atomically serialize `reopenParentFromDelegation` (#365 by @edelauna, PR #725 by @edelauna) +- Fix: shell default profile name type guard (#686 by @daewoongoh, PR #687 by @daewoongoh) +- chore(security): dependency-review, invisible-char detection, and least-privilege workflow permissions (#782 by @edelauna, PR #783 by @edelauna) +- chore: upgrade `@anthropic-ai/sdk` to 0.104.1 and `@anthropic-ai/vertex-sdk` to 0.17.1 (#438 by @p12tic, PR #600 by @p12tic) +- chore: enforce no-floating-promises in core/task/ (PR #253 by @0xMink) +- ci: improve PR label reconciliation with CI gating and event triggers (PR #228 by @app/roomote) +- fix(deps): update AI SDKs and providers (PR #744 by @app/renovate) +- chore(deps): update build, lint, and test tooling (PR #745 by @app/renovate) +- chore(deps): update dependency mermaid to v11.16.0 (PR #742 by @app/renovate) +- chore(deps): update dependency posthog-js to v1.393.5 (PR #746 by @app/renovate) +- chore(deps): update dependency ajv to v8.20.0 (PR #747 by @app/renovate) +- chore(deps): update dependency react-use to v17.6.1 (PR #740 by @app/renovate) +- chore(deps): update dependency reconnecting-eventsource to v1.6.5 (PR #741 by @app/renovate) +- chore(deps): update dependency pdf-parse to v1.1.4 (PR #739 by @app/renovate) +- chore(deps): update dependency ovsx to v0.10.12 (PR #738 by @app/renovate) +- chore(deps): update dependency only-allow to v1.2.2 (PR #737 by @app/renovate) + +## [3.64.0] + +### Minor Changes + +- Add Rules Management UI — new Rules tab in Settings to create, delete, and open global and workspace Zoo rules (#660 by @ivanarifin, PR #657 by @ivanarifin) +- Add completion change review actions — "See New Changes" and "Restore Changes" buttons after task completion let you inspect and undo changes from the latest prompt (#661 by @ivanarifin, PR #633 by @ivanarifin) +- Add kimi-k2p7-code model on Fireworks provider (PR #599 by @p12tic) +- feat: add abort signal core plumbing — threads AbortSignal through the API metadata layer for future provider-level cancellation (#434 by @easonLiangWorldedtech, PR #674 by @easonLiangWorldedtech) +- feat: add TaskSemaphore utility for parallel task coordination (#362 by @edelauna, PR #675 by @edelauna) +- feat(experiments): register PARALLEL_TOOL_EXECUTION feature flag (internal-only) (#363 by @edelauna, PR #678 by @edelauna) +- Add Roo Code history import to the About page (PR #141 by @roomote) +- Fix: configurable relaxed diff thresholds and diagnostics reduce "edit unsuccessful" errors (#452 by @DannyVarodBlueVine, PR #470 by @nigeldelviero) +- Fix: auto-closing edited files is now opt-in — the setting defaults to off (#719 by @edelauna, PR #720 by @edelauna) +- Fix(diff-view): make auto-closing edited files opt-in, fixing setting that could not be unchecked (#667 by @navedmerchant, PR #668 by @navedmerchant) +- Fix(delegation): serialize delegateParentAndOpenChild with atomicReadAndUpdate to prevent race conditions (#364 by @edelauna, #365 by @edelauna, PR #691 by @edelauna) +- Fix(ask_followup_question): report non-array follow_up suggestions as a type error (#511 by @nh2, PR #662 by @nh2) +- Fix: parse Gemma 4 `` reasoning tags alongside `` (#323 by @sagidM, PR #324 by @sagidM) +- docs(prompt): enhance apply_diff tool instructions to improve Gemini model success rate (#611 by @awschmeder, PR #619 by @awschmeder) +- chore(deps): update undici to v6.27.0 [security] (PR #659 by @renovate) +- chore(deps): update @types/node, @vscode/test-cli, execa, axios (PR #669, #670, #671, #673 by @renovate) +- test(mcp): fix McpHub Windows command wrapping test ordering (PR #632 by @HappyLiang12) +- fix(McpHub): resolve flaky McpHub.spec.ts tests after Vitest 4 upgrade (PR #666 by @edelauna) + +## [3.62.0] + +### Minor Changes + +- Add GLM-5.2 support — the latest GLM model is now available in your provider settings (#597 by @percy4, PR #608 by @MobCode100) +- Add OpenCode-Go native model parameters, Anthropic-format routing, and context-token fix for more reliable responses (#646 by @ykoneee, PR #652 by @navedmerchant) +- Add tool-writer mode to the Marketplace — a new specialized mode for writing and maintaining tool definitions (#603 by @RayCarro, PR #604 by @RayCarro) +- Add LiteLLM support for forwarding taskId as X-Zoo-Session-ID request header for better request tracing (#590 by @awschmeder, PR #591 by @awschmeder) +- Fix: Apply apiRequestTimeout consistently across all providers (#565 by @daewoongoh, PR #567 by @daewoongoh) +- Fix: Restore diff view scroll position and fix tab handling on save/deny (#586 by @awschmeder, PR #589 by @awschmeder) +- Fix: Deliver terminal completion signal when end event wins the race against setActiveStream (#489 by @drzraf, #622 by @onlineapps-cloud, PR #645 by @edelauna) +- Fix: Fetch OpenCode-Go models unconditionally — the /models endpoint is public (PR #437 by @proyectoauraorg) +- Refactor: Extract RateLimitClock from Task static state for cleaner rate-limit handling (#361 by @edelauna, PR #628 by @edelauna) +- Refactor: Use extractReasoningFromDelta helper for reasoning extraction across providers (PR #588 by @daewoongoh) +- Fix: Automate PR review-state and stale labels in GitHub Actions (PR #636 by @edelauna) +- Re-enable the prefer-const ESLint rule (PR #250 by @0xMink) +- Add stale PR workflows and auto-closure policy (PR #631 by @edelauna) +- Update dependency vitest to v4 [security] (PR #443 by @app/renovate) +- Update dependency shell-quote to v1.8.4 [security] (PR #554 by @app/renovate) +- Update dependency esbuild to v0.28.1 [security] (PR #595 by @app/renovate) +- Update dependency vite to v8.0.16 [security] (PR #642 by @app/renovate) +- Update GitHub Actions (PR #521 by @app/renovate) + +## [3.60.0] + +### Minor Changes + +- Add Claude Fable 5 support across Anthropic, Bedrock, and Vertex providers (PR #555 by @taltas) +- Add OpenAI GPT-5.5 support (PR #537 by @scream4ik) +- Add per-mode MCP server restrictions — configure an allowlist to restrict which MCP servers are active per mode (PR #453 by @simurg79) +- Add workspace `rootResolution` setting for controlling path resolution in multi-root workspaces (PR #538 by @simurg79) +- Add LiteLLM support for `reasoning_content` and `reasoning` fields in streaming responses (PR #449 by @daewoongoh) +- Add Show Ripgrep Diagnostic command for easier ripgrep troubleshooting (PR #281 by @0xMink) +- Redesign terminal profile settings UX — unified dropdown, consistent layout, and improved styling (#119 by @chenyuanrun, #321 by @F915, PR #533 by @F915) +- Fix chat window running out of memory when transcript grows large (PR #153 by @app/roomote) +- Fix relative symlinks in rules files not resolving correctly using realpath of parent directory (PR #442 by @p12tic) +- Fix command approval buttons not clearing when auto-executed (PR #480 by @awschmeder) +- Fix multi-line quoted command parsing, auto-approval behavior, and malformed-command error surfacing (PR #483 by @awschmeder) +- Fix `list-files` tool to validate directory exists before spawning ripgrep (#557 by @edelauna, PR #558 by @edelauna) +- Fix child tasks returning to parent when parent status is active in AttemptCompletionTool (PR #510 by @edelauna) +- Fix surface in-stream errors from Zoo and Vercel AI gateways (PR #569 by @JamesRobert20) +- Gate marketplace publish behind PR approval check (PR #516 by @edelauna) +- Stabilize flaky e2e provider suite ordering and zai requestCapture race (#512 by @edelauna, #514 by @edelauna, PR #45 by @app/roomote) +- Fix flaky e2e subtasks fixture collision and task identity prompt (#561, PR #563 by @simurg79) +- Add contributing guidelines: PR expectations and AI-assisted contribution policy (PR #562 by @edelauna) +- Configure knip and remove dead code (PR #225 by @app/roomote) +- Pin dependencies (PR #423 by @app/renovate) + +## [3.58.1] + +### Patch Changes + +- Fix: Remove unsupported `--no-absolute-filenames` tar argument (#491 by @kazenshi, PR #492 by @kazenshi) + +## 3.58.0 + +### Minor Changes + +- Add Zoo Gateway provider with auth callback and multi-profile token sync (PR #344 by @JamesRobert20, PR #345 by @JamesRobert20, PR #347 by @JamesRobert20) +- Add Gemini 3.5 Flash support (PR #331 by @jeanbispo) +- Add Semble as a local on-the-fly embedding provider for code indexing (PR #399 by @navedmerchant) +- Remove extension-side LLM telemetry; server logs only through gateway (PR #346 by @JamesRobert20) +- Add VS Code integrated terminal shell override (PR #277 by @proyectoauraorg) +- Add configurable chat font size (#157 by @duvw, PR #276 by @proyectoauraorg) +- Render GitHub-style alerts in the webview (#258 by @melck, PR #275 by @proyectoauraorg) +- Add configurable max output tokens for GLM models (#161 by @app/roomote, PR #274 by @proyectoauraorg) +- Introduce WorkspacePathResolver for async symlink-aware path canonicalization (#389 by @edelauna, PR #428 by @proyectoauraorg) +- Better secure release workflows and GitHub Actions (PR #482 by @edelauna) +- Fix React crash from malformed follow-up suggestion mode (PR #414 by @edelauna) +- Fix OpenAI temperature omitted when no custom value is set (#242 by @brunocasado, PR #247 by @proyectoauraorg) +- Handle per-key failures during settings import (PR #401 by @taltas) +- Add comprehensive test coverage for ReadFileTool (PR #222 by @proyectoauraorg) +- Unskip VS Code e2e replay for subtasks (PR #94 by @app/roomote) +- Fix e2e cache: replace paths filter with content-hash cache skip (PR #268 by @app/roomote) +- Remove deprecated requestRooCreditBalance handler (PR #385 by @JamesRobert20) +- Update mermaid to v11.15.0 for a security fix (PR #235 by @app/renovate) +- Update axios to v1.16.0 for a security fix (PR #400 by @app/renovate) +- Pin dependencies (PR #353 by @app/renovate) +- Remove unused tmp dependency and other unused packages (PR #341 by @app/renovate) + +## 3.56.0 + +### Minor Changes + +- Add Claude Opus 4.8 support across Anthropic, Bedrock, and Vertex providers (PR #386 by @vandre-sales) +- Add Opencode Go as a first-class provider (#172 by @vijay-0001, PR #319 by @proyectoauraorg) +- Add glm-5.1, kimi-k2.6, and deepseek-v4-pro models to the Fireworks provider (#198 by @DeCodeTheWeb, PR #231 by @proyectoauraorg) +- Show Zoo Code identity in outbound provider activity logs (#203 by @yfdyh000, PR #219 by @app/roomote) +- Fix API requests hanging indefinitely on VS Code 1.122.0+ (#381 by @greatgradz-svg, #382 by @abcxlab, PR #383 by @app/roomote) +- Fix terminal task cancellation so the running process is terminated when a task is cancelled (#245 by @proyectoauraorg, PR #261 by @proyectoauraorg) +- Fix terminal Ctrl+C retry so processes that need multiple SIGINT signals are properly stopped (#266 by @edelauna, PR #272 by @proyectoauraorg) +- Fix Gemini provider to honor custom model IDs instead of falling back to the default (#227 by @notoccupy2023-design, PR #317 by @proyectoauraorg) +- Fix truncated Grok diffs caused by missing diff markers (#186 by @jcalfee, PR #230 by @proyectoauraorg) +- Fix PowerShell detection on Windows when no shell profile is configured (#82 by @rossdonald, PR #239 by @proyectoauraorg) +- Fix Vertex AI warning when the Google Cloud Credentials field receives a file path instead of JSON (PR #294 by @0xMink) +- Rename Zoo Code in VS Code code actions (#328 by @rrewll, PR #329 by @rrewll) +- Localize VS Code code action commands (#334 by @edelauna, PR #339 by @rrewll) +- Migrate webview build to Vite 8 (PR #214 by @maxdewald) +- Add comprehensive unit tests for AskFollowupQuestionTool and ListFilesTool (#206 by @app/roomote, PR #212, #213 by @proyectoauraorg) +- Update `diff` to v5.2.2 for a security fix (PR #173 by @app/renovate) +- Update `i18next-http-backend` to v3.0.5 for a security fix (PR #174 by @app/renovate) +- Update `fast-xml-parser` to v5.7.0 for a security fix (PR #179 by @app/renovate) +- Update `simple-git` to v3.36.0 for a security fix (PR #182 by @app/renovate) +- Update `uuid` and pin esbuild/rollup/vite for a security fix (PR #205 by @app/renovate) +- Update `turbo` to v2.9.14 for a security fix (PR #236 by @app/renovate) + +## 3.55.1 + +### Patch Changes + +- Fix API requests hanging indefinitely on VS Code 1.122.0+ when Zoo Code could not find the bundled ripgrep binary after the `@vscode/ripgrep-universal` rename (#381 by @greatgradz-svg, PR #248 by @0xMink). + +All notable changes to Zoo Code will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and Zoo Code uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## 3.55.0 + +### Minor Changes + +- Add Xiaomi MiMo as a first-class API provider (#80 by @capitanfeeder, PR #81 by @capitanfeeder) +- Merge the Roo Code upstream sunset into Zoo Code and pull in related handoff updates (PR #123 by @edelauna) +- Fix Gemini requests when users enable the full MCP tool set (PR #148 by @app/roomote) +- Fix OpenAI requests by omitting temperature for models that do not support it (#215 by @marty-a11y, PR #233 by @proyectoauraorg) +- Fix the MCP OAuth callback page garbled text after sign-in (#217 by @mabiuroot-art, PR #218 by @app/roomote) +- Fix single-tilde Markdown so normal text no longer appears struck through (#154 by @slashedstar, PR #240 by @proyectoauraorg) +- Add deterministic xAI provider end-to-end coverage (PR #149 by @app/roomote) +- Update the default Z.AI model to GLM-4.7 (PR #90 by @bryce-hoehn) +- Fix GLM models reserving too much output context by default (PR #160 by @app/roomote) +- Fix the Vertex AI region dropdown so eu and us multi-region endpoints appear correctly (PR #170 by @app/roomote) +- Fix the webview diagnostics temp file prefix (#193 by @proyectoauraorg, PR #226 by @proyectoauraorg) +- Fix Shift+Enter sending chat messages when Ctrl/Cmd+Enter mode is enabled (PR #199 by @app/roomote) +- Fix recursive `list_files` omitting nested files in temp workspaces (PR #91 by @app/roomote) +- Fix the welcome screen (#162 by @navedmerchant, PR #163 by @navedmerchant) +- Refactor core monolith helpers (PR #27 by @doctarock) +- Unskip read-file tests (PR #53 by @edelauna) +- Improve core coverage CI and merge queue readiness (PR #207 by @app/roomote) +- Unskip the VS Code e2e replay for mutating tools (PR #92 by @app/roomote) +- Unskip the VS Code e2e replay for `use_mcp_tool` (PR #93 by @app/roomote) +- Reduce Renovate review noise (PR #144 by @app/roomote) +- Let Renovate open grouped updates on the normal bot cadence (PR #167 by @app/roomote) +- Add comprehensive unit tests for the MiMoHandler provider (PR #210 by @proyectoauraorg) +- Add unit tests for the SwitchModeTool (PR #211 by @proyectoauraorg) +- Update `yaml` to `2.8.3` for a security fix (PR #176 by @app/renovate) +- Update `axios` to `1.15.2` for a security fix (PR #177 by @app/renovate) +- Update `mammoth` to `1.11.0` for a security fix (PR #180 by @app/renovate) +- Update `undici` to `6.24.0` for a security fix (PR #183 by @app/renovate) +- Update `@ai-sdk/amazon-bedrock` to `4.0.107` (PR #55 by @app/renovate) +- Update `@ai-sdk/baseten` to `1.0.50` (PR #56 by @app/renovate) + +## 3.54.1 + +### Patch Changes + +- Fix Anthropic Opus 4.7 when reasoning is enabled (PR #111 by @app/roomote) +- Fix the OpenAI Compatible onboarding form starting above the viewport (PR #113 by @app/roomote) +- Fix settings and Marketplace access after importing Roo Router settings (PR #109 by @app/roomote) +- Fix the setup announcement origin and load LM Studio models on first open (PR #97 by @app/roomote) +- Fix Discord invite links that still pointed to the old Zoo Code server (PR #107 by @app/roomote) +- Fix support links that opened the wrong GitHub repository (PR #77 by @app/roomote) +- Refresh Zoo Code branding across docs and metadata (PR #85 by @taltas) +- Clarify Zoo Code migration messaging in the README (PR #99 by @taltas) +- Keep settings regression coverage in the webview-ui test suite (PR #95 by @app/roomote) +- Clean up skipped extension package tests (PR #110 by @app/roomote) +- Add DeepSeek V4 end-to-end coverage (PR #72 by @app/roomote) +- Use repo collaborators as the default code owners (PR #96 by @app/roomote) +- Use a single PR flow for extension releases (PR #142 by @app/roomote) +- Update `isbinaryfile` to `5.0.7` (PR #88 by @f14XuanLv) +- Update `@dotenvx/dotenvx` to `1.66.0` (PR #61 by @app/renovate) +- Update `lint-staged` to `16.4.0` (PR #64 by @app/renovate) +- Update Node.js to `20.20.2` (PR #65 by @app/renovate) + +## [3.54.0] - 2026-05-08 + +### Added + +- Publish Zoo Code under the `ZooCodeOrganization.zoo-code` Marketplace identity, continuing from upstream Roo Code `3.53.0`. +- Add stable publishing workflows for the VS Code Marketplace and Open VSX Registry. +- Add a VS Code Marketplace pre-release workflow. + +--- + +# Archived Roo Code Changelog + +The entries below are preserved from the upstream Roo Code project history before the Zoo Code marketplace handoff. + +## 3.53.0 + +### Minor Changes + +- **The Roo Code plugin is not going away.** You may have seen the [recent announcement](https://x.com/mattrubens/status/2046636598859559114) that Roo Code hit 3 million installs and the original team is going all-in on Roomote. We know that news was hard for a lot of you. This plugin means a lot to us and to you, and we hear you. The good news: a community team has stepped up to carry Roo Code forward, and we're working with them on an official handoff so the plugin you rely on keeps getting maintained and improved. +- Add GPT-5.5 support via the OpenAI Codex provider (PR #12170 by @hannesrudolph) +- Add Claude Opus 4.7 support on Vertex AI (#12134 by @saneroen, PR #12135 by @saneroen) +- Add previous checkpoint navigation controls and i18n in chat (#12138 by @saneroen, PR #12139 by @saneroen) +- Add Roomote banner (PR #12119 by @brunobergher) +- Redesign Roomote announcement banner with violet branding on the web (PR #12161 by @roomote-v0) +- Add sunsetting Roo Code blog post (PR #12160 by @roomote-v0) + +## 3.52.1 + +### Patch Changes + +- Add correct JSON schema for `.roomodes` configuration files (#11790 by @algorhythm85, PR #11791 by @app/roomote-v0) +- Remove the hiring announcement from the VS Code extension UI (PR #12108 by @app/roomote-v0) + +## 3.52.0 + +### Minor Changes + +- Add Poe as an AI provider so users can access Poe models directly in Roo Code (PR #12015 by @kamilio) +- Improve the xAI provider by migrating it to the Responses API with reusable transform utilities (#11961 by @carlesso, PR #11962 by @carlesso) +- Fix MiniMax model listings and context window handling for more reliable configuration (#11999 by @Rexarrior, PR #12069 by @Rexarrior) +- Add xAI Grok-4.20 models and update the default xAI model selection (#11955 by @carlesso, PR #11956 by @carlesso) +- Add OpenAI GPT-5.4 mini and nano models to expand the available OpenAI model lineup (PR #11946 by @PeterDaveHello) +- Chore: include the automated version bump PR from the previous release cycle for complete release accounting (PR #11892 by @app/github-actions) + +### Patch Changes + +- Add support for OpenAI `gpt-5.4-mini` and `gpt-5.4-nano` models. + +## 3.51.1 + +### Patch Changes + +- Feat: Add Cohere Embed v4 model support for Bedrock and improve credential handling (#11823 by @cscvenkatmadurai, PR #11824 by @cscvenkatmadurai) +- Feat: Add Gemini 3.1 Pro customtools model to Vertex AI provider (PR #11857 by @NVolcz) +- Feat: Add gpt-5.4 to ChatGPT Plus/Pro (Codex) model catalog (PR #11876 by @roomote-v0) + +## 3.51.0 + +### Minor Changes + +- Add OpenAI GPT-5.4 and GPT-5.3 Chat Latest model support so Roo Code can use the newest OpenAI chat models (PR #11848 by @PeterDaveHello) +- Add support for exposing skills as slash commands with skill fallback execution for faster workflows (PR #11834 by @hannesrudolph) +- Add CLI support for `--create-with-session-id` plus UUID session validation for more controlled session creation (PR #11859 by @cte) +- Add support for choosing a specific shell when running terminal commands (PR #11851 by @jr) +- Feature: Add the `ROO_ACTIVE` environment variable to terminal session settings for safer terminal guardrails (#11864 by @ajjuaire, PR #11862 by @ajjuaire) +- Improve cloud settings freshness by updating the refresh interval to one hour (PR #11749 by @roomote-v0) +- Add CLI session resume/history support plus an upgrade command for better long-running workflows (PR #11768 by @cte) +- Add support for images in CLI stdin stream commands (PR #11831 by @cte) +- Include `exitCode` in CLI command `tool_result` events for more reliable automation (PR #11820 by @cte) +- Add CLI types to improve development ergonomics and type safety (PR #11781 by @cte) +- Add CLI integration coverage for stdin stream routing and race-condition invariants (PR #11846 by @cte) +- Fix the CLI stdin-stream cancel race and add an integration test suite to prevent regressions (PR #11817 by @cte) +- Improve CLI stream recovery and add a configurable consecutive mistake limit (PR #11775 by @cte) +- Fix CLI streaming deltas, task ID propagation, cancel recovery, and other runtime edge cases (PR #11736 by @cte) +- Fix CLI task resumption so paused work can reliably continue (PR #11739 by @cte) +- Recover from unhandled exceptions in the CLI instead of failing hard (PR #11750 by @cte) +- Scope CLI session and resume flags to the current workspace to avoid cross-workspace confusion (PR #11774 by @cte) +- Fix stdin prompt streaming to forward task configuration correctly (PR #11778 by @daniel-lxs) +- Handle stdin-stream control-flow errors gracefully in the CLI runtime (PR #11811 by @cte) +- Fix stdin stream queued messages and command output streaming in the CLI (PR #11814 by @cte) +- Increase the CLI command execution timeout for long-running commands (PR #11815 by @cte) +- Fix knip checks to keep repository validation green (PR #11819 by @cte) +- Fix CLI upgrade version detection so upgrades resolve the correct target version (PR #11829 by @cte) +- Ignore model-provided timeout values in the CLI runtime to keep command handling consistent (PR #11835 by @cte) +- Fix redundant skill reloading during conversations to reduce duplicate work (PR #11838 by @hannesrudolph) +- Ensure full command output is streamed before the CLI reports completion (PR #11842 by @cte) +- Fix CLI follow-up routing after completion prompts so next actions land in the right place (PR #11844 by @cte) +- Remove the Netflix logo from the homepage (PR #11787 by @roomote-v0) +- Chore: Prepare CLI release v0.1.2 (PR #11737 by @cte) +- Chore: Prepare CLI release v0.1.3 (PR #11740 by @cte) +- Chore: Prepare CLI release v0.1.4 (PR #11751 by @cte) +- Chore: Prepare CLI release v0.1.5 (PR #11772 by @cte) +- Chore: Prepare CLI release v0.1.6 (PR #11780 by @cte) +- Release Roo Code v1.113.0 (PR #11782 by @cte) +- Chore: Prepare CLI release v0.1.7 (PR #11812 by @cte) +- Chore: Prepare CLI release v0.1.8 (PR #11816 by @cte) +- Chore: Prepare CLI release v0.1.9 (PR #11818 by @cte) +- Chore: Prepare CLI release v0.1.10 (PR #11821 by @cte) +- Release Roo Code v1.114.0 (PR #11822 by @cte) +- Chore: Prepare CLI release v0.1.11 (PR #11832 by @cte) +- Release Roo Code v1.115.0 (PR #11833 by @cte) +- Chore: Prepare CLI release v0.1.12 (PR #11836 by @cte) +- Chore: Prepare CLI release v0.1.13 (PR #11837 by @hannesrudolph) +- Chore: Prepare CLI release v0.1.14 (PR #11843 by @cte) +- Chore: Prepare CLI release v0.1.15 (PR #11845 by @cte) +- Chore: Prepare CLI release v0.1.16 (PR #11852 by @cte) +- Chore: Prepare CLI release v0.1.17 (PR #11860 by @cte) + +### Patch Changes + +- Add OpenAI's GPT-5.3-Chat-Latest model support +- Add OpenAI's GPT-5.3-Codex model support +- Add OpenAI's GPT-5.4 model support +- Add OpenAI's GPT-5.3-Codex model support (PR #11728 by @PeterDaveHello) +- Warm Roo models on CLI startup for faster initial responses (PR #11722 by @cte) +- Fix spelling/grammar and casing inconsistencies (#11478 by @PeterDaveHello, PR #11485 by @PeterDaveHello) +- Fix: Restore Linear integration page (PR #11725 by @roomote) +- Chore: Prepare CLI release v0.1.1 (PR #11723 by @cte) + +## [3.50.4] - 2026-02-21 + +- Feat: Add MiniMax M2.5 model support (#11471 by @love8ko, PR #11458 by @roomote) + +## [3.50.3] - 2026-02-20 + +- Fix: Correct Vertex AI claude-sonnet-4-6 model ID (#11625 by @yuvarajl, PR #11626 by @roomote) +- Restore Unbound as a provider (PR #11624 by @pugazhendhi-m) + +## [3.50.2] - 2026-02-20 + +- Fix: Inline terminal rendering parity with the VSCode Terminal (#10699 by @jerrill-johnson-bitwerx, PR #11361 by @RussellZager) +- Fix: Enable prompt caching for Bedrock custom ARN and default to ON (#10846 by @wisestmumbler, PR #11373 by @roomote) +- Feat: Add visual feedback to copy button in task actions (#11401 by @omagoduck, PR #11403 by @omagoduck) + +## [3.50.1] - 2026-02-20 + +- Fix OpenAI Codex and OpenAI Native stream parsing for done-only and `content_part` events, including duplicate-text guards when deltas are already streamed. + +## [3.50.0] - 2026-02-19 + +- Add Gemini 3.1 Pro support and set as default Gemini model (PR #11608 by @PeterDaveHello) +- Add NDJSON stdin protocol, list subcommands, and modularize CLI run command (PR #11597 by @cte) +- Prepare CLI v0.1.0 release (PR #11599 by @cte) +- Remove integration tests (PR #11598 by @roomote) +- Changeset version bump (PR #11596 by @github-actions) + +## [3.49.0] - 2026-02-19 + +- Add file changes panel to track all file modifications per conversation (#11493 by @saneroen, PR #11494 by @saneroen) +- Add per-workspace indexing opt-in and stop/cancel indexing controls (#11455 by @JamesRobert20, PR #11456 by @JamesRobert20) +- Add per-task file-based history store for cross-instance safety (PR #11490 by @roomote) +- Fix: Redesign rehydration scroll lifecycle for smoother chat experience (PR #11483 by @hannesrudolph) +- Fix: Bump @roo-code/types metadata version to 1.111.0 after revert regression (PR #11588 by @roomote) + +## [3.48.1] - 2026-02-18 + +- Fix: Await MCP server initialization before returning McpHub instance, preventing race conditions (PR #11518 by @daniel-lxs) +- Fix: Correct Bedrock Claude Sonnet 4.6 model ID (#11509 by @PeterDaveHello, PR #11569 by @PeterDaveHello) +- Add DeleteQueuedMessage IPC command for managing queued messages (PR #11464 by @roomote) + +## [3.48.0] - 2026-02-17 + +- Add Anthropic Claude Sonnet 4.6 support across all providers — Anthropic, Bedrock, Vertex, OpenRouter, and Vercel AI Gateway (PR #11509 by @PeterDaveHello) +- Add lock toggle to pin API config across all modes in a workspace (PR #11295 by @hannesrudolph) +- Fix: Prevent parent task state loss during orchestrator delegation (PR #11281 by @hannesrudolph) +- Fix: Resolve race condition in new_task delegation that loses parent task history (PR #11331 by @daniel-lxs) +- Fix: Serialize taskHistory writes and fix delegation status overwrite race (PR #11335 by @hannesrudolph) +- Fix: Prevent chat history loss during cloud/settings navigation (#11371 by @SannidhyaSah, PR #11372 by @SannidhyaSah) +- Fix: Preserve condensation summary during task resume (#11487 by @SannidhyaSah, PR #11488 by @SannidhyaSah) +- Fix: Resolve chat scroll anchoring and task-switch scroll race conditions (PR #11385 by @hannesrudolph) +- Fix: Preserve pasted images in chatbox during chat activity (PR #11375 by @app/roomote) +- Add disabledTools setting to globally disable native tools (PR #11277 by @daniel-lxs) +- Rename search_and_replace tool to edit and unify edit-family UI (PR #11296 by @hannesrudolph) +- Render nested subtasks as recursive tree in history view (PR #11299 by @hannesrudolph) +- Remove 9 low-usage providers and add retired-provider UX (PR #11297 by @hannesrudolph) +- Remove browser use functionality entirely (PR #11392 by @hannesrudolph) +- Remove built-in skills and built-in skills mechanism (PR #11414 by @hannesrudolph) +- Remove footgun prompting (file-based system prompt override) (PR #11387 by @hannesrudolph) +- Batch consecutive tool calls in chat UI with shared utility (PR #11245 by @hannesrudolph) +- Validate Gemini thinkingLevel against model capabilities and handle empty streams (PR #11303 by @hannesrudolph) +- Add GLM-5 model support to Z.ai provider (PR #11440 by @app/roomote) +- Fix: Prevent double notification sound playback (PR #11283 by @hannesrudolph) +- Fix: Prevent false unsaved changes prompt with OpenAI Compatible headers (#8230 by @hannesrudolph, PR #11334 by @daniel-lxs) +- Fix: Cancel backend auto-approval timeout when auto-approve is toggled off mid-countdown (PR #11439 by @SannidhyaSah) +- Fix: Add follow_up param validation in AskFollowupQuestionTool (PR #11484 by @rossdonald) +- Fix: Prevent webview postMessage crashes and make dispose idempotent (PR #11313 by @0xMink) +- Fix: Avoid zsh process-substitution false positives in assignments (PR #11365 by @hannesrudolph) +- Fix: Harden command auto-approval against inline JS false positives (PR #11382 by @hannesrudolph) +- Fix: Make tab close best-effort in DiffViewProvider.open (PR #11363 by @0xMink) +- Fix: Canonicalize core.worktree comparison to prevent Windows path mismatch failures (PR #11346 by @0xMink) +- Fix: Make removeClineFromStack() delegation-aware to prevent orphaned parent tasks (PR #11302 by @app/roomote) +- Fix task resumption in the API module (PR #11369 by @cte) +- Make defaultTemperature required in getModelParams to prevent silent temperature overrides (PR #11218 by @app/roomote) +- Remove noisy console.warn logs from NativeToolCallParser (PR #11264 by @daniel-lxs) +- Consolidate getState calls in resolveWebviewView (PR #11320 by @0xMink) +- Clean up repo-facing mode rules (PR #11410 by @hannesrudolph) +- Implement ModelMessage storage layer with AI SDK response messages (PR #11409 by @daniel-lxs) +- Extract translation and merge resolver modes into reusable skills (PR #11215 by @app/roomote) +- Add blog section with initial posts to roocode.com (PR #11127 by @app/roomote) +- Replace Roomote Control with Linear Integration in cloud features grid (PR #11280 by @app/roomote) +- Add IPC query handlers for commands, modes, and models (PR #11279 by @cte) +- Add stdin stream mode for the CLI (PR #11476 by @cte) +- Make CLI auto-approve by default with require-approval opt-in (PR #11424 by @cte) +- Update CLI default model from Opus 4.5 to Opus 4.6 (PR #11273 by @app/roomote) +- Add linux-arm64 support for the Roo CLI (PR #11314 by @cte) +- CLI release: v0.0.51 (PR #11274 by @cte) +- CLI release: v0.0.52 (PR #11324 by @cte) +- CLI release: v0.0.53 (PR #11425 by @cte) +- CLI release: v0.0.54 (PR #11477 by @cte) + +## [3.45.0] - 2026-01-27 + +![3.45.0 Release - Smart Code Folding](/releases/3.45.0-release.png) + +- Smart Code Folding: Context condensation now intelligently preserves a lightweight map of files you worked on—function signatures, class declarations, and type definitions—so Roo can continue referencing them accurately after condensing. Files are prioritized by most recent access, with a ~50k character budget ensuring your latest work is always preserved. (Idea by @shariqriazz, PR #10942 by @hannesrudolph) + +## [3.44.2] - 2026-01-27 + +- Re-enable parallel tool calling with new_task isolation safeguards (PR #11006 by @mrubens) +- Fix worktree indexing by using relative paths in isPathInIgnoredDirectory (PR #11009 by @daniel-lxs) +- Fix local model validation error for Ollama models (PR #10893 by @roomote) +- Fix duplicate tool_call emission from Responses API providers (PR #11008 by @daniel-lxs) + +## [3.44.1] - 2026-01-27 + +- Fix LiteLLM tool ID validation errors for Bedrock proxy (PR #10990 by @daniel-lxs) +- Add temperature=0.9 and top_p=0.95 to zai-glm-4.7 model for better generation quality (PR #10945 by @sebastiand-cerebras) +- Add quality checks to marketing site deployment workflows (PR #10959 by @mp-roocode) + +## [3.44.0] - 2026-01-26 + +![3.44.0 Release - Worktrees](/releases/3.44.0-release.png) + +- Add worktree selector and creation UX (PR #10940 by @brunobergher, thanks Cline!) +- Improve subtask visibility and navigation in history and chat views (PR #10864 by @brunobergher) +- Add wildcard support for MCP alwaysAllow configuration (PR #10948 by @app/roomote) +- Fix: Prevent nested condensing from including previously-condensed content (PR #10985 by @hannesrudolph) +- Fix: VS Code LM token counting returns 0 outside requests, breaking context condensing (#10968 by @srulyt, PR #10983 by @daniel-lxs) +- Fix: Record truncation event when condensation fails but truncation succeeds (PR #10984 by @hannesrudolph) +- Replace hyphen encoding with fuzzy matching for MCP tool names (PR #10775 by @daniel-lxs) +- Remove MCP SERVERS section from system prompt for cleaner prompts (PR #10895 by @daniel-lxs) +- new_task tool creates checkpoint the same way write_to_file does (PR #10982 by @daniel-lxs) +- Update Fireworks provider with new models (#10674 by @hannesrudolph, PR #10679 by @ThanhNguyxn) +- Fix: Truncate AWS Bedrock toolUseId to 64 characters (PR #10902 by @daniel-lxs) +- Fix: Restore opaque background to settings section headers (PR #10951 by @app/roomote) +- Fix: Remove unsupported Fireworks model tool fields (PR #10937 by @app/roomote) +- Update and improve zh-TW Traditional Chinese locale and docs (PR #10953 by @PeterDaveHello) +- Chore: Remove POWER_STEERING experiment remnants (PR #10980 by @hannesrudolph) + +## [3.43.0] - 2026-01-23 + +![3.43.0 Release - Intelligent Context Condensation](/releases/3.43.0-release.png) + +- Intelligent Context Condensation v2: New context condensation system that intelligently summarizes conversation history when approaching context limits, preserving important information while reducing token usage (PR #10873 by @hannesrudolph) +- Improved context condensation with environment details, accurate token counts, and lazy evaluation for better performance (PR #10920 by @hannesrudolph) +- Move condense prompt editor to Context Management tab for better discoverability and organization (PR #10909 by @hannesrudolph) +- Update Z.AI models with new variants and pricing (#10859 by @ErdemGKSL, PR #10860 by @ErdemGKSL) +- Add pnpm install:vsix:nightly command for easier nightly build installation (PR #10912 by @hannesrudolph) +- Fix: Convert orphaned tool_results to text blocks after condensing to prevent API errors (PR #10927 by @daniel-lxs) +- Fix: Auto-migrate v1 condensing prompt and handle invalid providers on import (PR #10931 by @hannesrudolph) +- Fix: Use json-stream-stringify for pretty-printing MCP config files to prevent memory issues with large configs (#9862 by @Michaelzag, PR #9864 by @Michaelzag) +- Fix: Correct Gemini 3 pricing for Flash and Pro models (#10432 by @rossdonald, PR #10487 by @roomote) +- Fix: Skip thoughtSignature blocks during markdown export for cleaner output (#10199 by @rossdonald, PR #10932 by @rossdonald) +- Fix: Duplicate model display for OpenAI Codex provider (PR #10930 by @roomote) +- Remove diffEnabled and fuzzyMatchThreshold settings as they are no longer needed (#10648 by @hannesrudolph, PR #10298 by @hannesrudolph) +- Remove MULTI_FILE_APPLY_DIFF experiment (PR #10925 by @hannesrudolph) +- Remove POWER_STEERING experimental feature (PR #10926 by @hannesrudolph) +- Remove legacy XML tool calling code (getToolDescription) for cleaner codebase (PR #10929 by @hannesrudolph) + +## [3.42.0] - 2026-01-22 + +![3.42.0 Release - ChatGPT Usage Tracking](/releases/3.42.0-release.png) + +- Added UI to track your ChatGPT usage limits in the OpenAI Codex provider (PR #10813 by @hannesrudolph) +- Removed deprecated Claude Code provider (PR #10883 by @daniel-lxs) +- Streamlined codebase by removing legacy XML tool calling functionality (#10848 by @hannesrudolph, PR #10841 by @hannesrudolph) +- Standardize model selectors across all providers: Improved consistency of model selection UI (#10650 by @hannesrudolph, PR #10294 by @hannesrudolph) +- Enable prompt caching for Cerebras zai-glm-4.7 model (#10601 by @jahanson, PR #10670 by @app/roomote) +- Add Kimi K2 thinking model to VertexAI provider (#9268 by @diwakar-s-maurya, PR #9269 by @app/roomote) +- Warn users when too many MCP tools are enabled (PR #10772 by @app/roomote) +- Migrate context condensing prompt to customSupportPrompts (PR #10881 by @hannesrudolph) +- Unify export path logic and default to Downloads folder (PR #10882 by @hannesrudolph) +- Performance improvements for webview state synchronization (PR #10842 by @hannesrudolph) +- Fix: Handle mode selector empty state on workspace switch (#10660 by @hannesrudolph, PR #9674 by @app/roomote) +- Fix: Resolve race condition in context condensing prompt input (PR #10876 by @hannesrudolph) +- Fix: Prevent double emission of text/reasoning in OpenAI native and codex handlers (PR #10888 by @hannesrudolph) +- Fix: Prevent task abortion when resuming via IPC/bridge (PR #10892 by @cte) +- Fix: Enforce file restrictions for all editing tools (PR #10896 by @app/roomote) +- Fix: Remove custom condensing model option (PR #10901 by @hannesrudolph) +- Unify user content tags to for consistent prompt formatting (#10658 by @hannesrudolph, PR #10723 by @app/roomote) +- Clarify linked SKILL.md file handling in prompts (PR #10907 by @hannesrudolph) +- Fix: Padding on Roo Code Cloud teaser (PR #10889 by @app/roomote) + +## [3.41.3] - 2026-01-18 + +- Fix: Thinking block word-breaking to prevent horizontal scroll in the chat UI (PR #10806 by @roomote) +- Add Claude-like CLI flags and authentication fixes for the Roo Code CLI (PR #10797 by @cte) +- Improve CLI authentication by using a redirect instead of a fetch (PR #10799 by @cte) +- Fix: Roo Code Router fixes for the CLI (PR #10789 by @cte) +- Release CLI v0.0.48 with latest improvements (PR #10800 by @cte) +- Release CLI v0.0.47 (PR #10798 by @cte) +- Revert E2E tests enablement to address stability issues (PR #10794 by @cte) + +## [3.41.2] - 2026-01-16 + +- Add button to open markdown in VSCode preview for easier reading of formatted content (PR #10773 by @brunobergher) +- Fix: Reset invalid model selection when using OpenAI Codex provider (PR #10777 by @hannesrudolph) +- Fix: Add openai-codex to providers that don't require an API key (PR #10786 by @roomote) +- Fix: Detect Gemini models with space-separated names for proper thought signature injection in LiteLLM (PR #10787 by @daniel-lxs) + +## [3.41.1] - 2026-01-16 + +![3.41.1 Release - Aggregated Subtask Costs](/releases/3.41.1-release.png) + +- Feat: Aggregate subtask costs in parent task (#5376 by @hannesrudolph, PR #10757 by @taltas) +- Fix: Prevent duplicate tool_use IDs causing API 400 errors (PR #10760 by @daniel-lxs) +- Fix: Handle missing tool identity in OpenAI Native streams (PR #10719 by @hannesrudolph) +- Fix: Truncate call_id to 64 chars for OpenAI Responses API (PR #10763 by @daniel-lxs) +- Fix: Gemini thought signature validation errors (PR #10694 by @daniel-lxs) +- Fix: Filter out empty text blocks from user messages for Gemini compatibility (PR #10728 by @daniel-lxs) +- Fix: Flatten top-level anyOf/oneOf/allOf in MCP tool schemas (PR #10726 by @daniel-lxs) +- Fix: Filter Ollama models without native tool support (PR #10735 by @daniel-lxs) +- Feat: Add settings tab titles to search index (PR #10761 by @roomote) +- Feat: Clarify Slack and Linear are Cloud Team only features (PR #10748 by @roomote) + +## [3.41.0] - 2026-01-15 + +![3.41.0 Release - OpenAI - ChatGPT Plus/Pro Provider](/releases/3.41.0-release.png) + +- Add OpenAI - ChatGPT Plus/Pro Provider that gives subscription-based access to Codex models without per-token costs (PR #10736 by @hannesrudolph) +- Add gpt-5.2-codex model to openai-native provider, providing access to the latest GPT model with enhanced coding capabilities (PR #10731 by @hannesrudolph) +- Fix: Clear terminal output buffers to prevent memory leaks that could cause gray screens and performance degradation (#10666, PR #7666 by @hannesrudolph) +- Fix: Inject dummy thought signatures on ALL tool calls for Gemini models, resolving issues with Gemini tool call handling through LiteLLM (PR #10743 by @daniel-lxs) +- Enable E2E tests with 39 passing tests, improving test coverage and reliability (PR #10720 by @ArchimedesCrypto) +- Add alwaysAllow config for MCP time server tools in E2E tests (PR #10733 by @ArchimedesCrypto) + +## [3.40.1] - 2026-01-13 + +- Fix: Add allowedFunctionNames support for Gemini to prevent mode switch errors (#10711 by @hannesrudolph, PR #10708 by @hannesrudolph) + +## [3.40.0] - 2026-01-13 + +![3.40.0 Release - Settings Search](/releases/3.40.0-release.png) + +- Add settings search functionality to quickly find and navigate to specific settings (PR #10619 by @mrubens) +- Improve settings search UI with better styling and usability (PR #10633 by @brunobergher) +- Add standardized stop button for improved task cancellation visibility (PR #10639 by @brunobergher) +- Display edit_file errors in UI after consecutive failures for better debugging feedback (PR #10581 by @daniel-lxs) +- Improve error display styling and visibility in chat messages (PR #10692 by @brunobergher) +- Improve stop button visibility and streamline error handling (PR #10696 by @brunobergher) +- Fix: Omit parallel_tool_calls when not explicitly enabled to prevent API errors (#10553 by @Idlebrand, PR #10671 by @daniel-lxs) +- Fix: Encode hyphens in MCP tool names before sanitization (#10642 by @pdecat, PR #10644 by @pdecat) +- Fix: Correct Gemini 3 thought signature injection format via OpenRouter (PR #10640 by @daniel-lxs) +- Fix: Sanitize tool_use IDs to match API validation pattern (PR #10649 by @daniel-lxs) +- Fix: Use placeholder for empty tool result content to fix Gemini API validation (PR #10672 by @daniel-lxs) +- Fix: Return empty string from getReadablePath when path is empty (PR #10638 by @daniel-lxs) +- Optimize message block cloning in presentAssistantMessage for better performance (PR #10616 by @ArchimedesCrypto) + +## [3.39.3] - 2026-01-10 + +![3.39.3 Release - Roo Code Router](/releases/3.39.3-release.png) + +- Rename Roo Code Cloud Provider to Roo Code Router for clearer branding (PR #10560 by @roomote) +- Update Roo Code Router service name throughout the codebase (PR #10607 by @mrubens) +- Update router name in types for consistency (PR #10605 by @mrubens) +- Improve ExtensionHost code organization and cleanup (PR #10600 by @cte) +- Add local installation option to CLI release script for testing (PR #10597 by @cte) +- Reorganize CLI file structure for better maintainability (PR #10599 by @cte) +- Add TUI to CLI (PR #10480 by @cte) + +## [3.39.2] - 2026-01-09 + +- Fix: Ensure all tools have consistent strict mode values for Cerebras compatibility (#10334 by @brianboysen51, PR #10589 by @app/roomote) +- Fix: Remove convertToSimpleMessages to restore tool calling for OpenAI-compatible providers (PR #10575 by @daniel-lxs) +- Fix: Make edit_file matching more resilient to prevent false negatives (PR #10585 by @hannesrudolph) +- Fix: Order text parts before tool calls in assistant messages for vscode-lm (PR #10573 by @daniel-lxs) +- Fix: Ensure assistant message content is never undefined for Gemini compatibility (PR #10559 by @daniel-lxs) +- Fix: Merge approval feedback into tool result instead of pushing duplicate messages (PR #10519 by @daniel-lxs) +- Fix: Round-trip Gemini thought signatures for tool calls (PR #10590 by @hannesrudolph) +- Feature: Improve error messaging for stream termination errors from provider (PR #10548 by @daniel-lxs) +- Feature: Add debug setting to settings page for easier troubleshooting (PR #10580 by @hannesrudolph) +- Chore: Disable edit_file tool for Gemini/Vertex providers (PR #10594 by @hannesrudolph) +- Chore: Stop overriding tool allow/deny lists for Gemini (PR #10592 by @hannesrudolph) +- Chore: Change default CLI model to anthropic/claude-opus-4.5 (PR #10544 by @mrubens) +- Chore: Update Terms of Service effective January 9, 2026 (PR #10568 by @mrubens) +- Chore: Move more types to @roo-code/types for CLI support (PR #10583 by @cte) +- Chore: Add functionality to @roo-code/core for CLI support (PR #10584 by @cte) +- Chore: Add slash commands useful for CLI development (PR #10586 by @cte) + +## [3.39.1] - 2026-01-08 + +- Fix: Stabilize file paths during native tool call streaming to prevent path corruption (PR #10555 by @daniel-lxs) +- Fix: Disable Gemini thought signature persistence to prevent corrupted signature errors (PR #10554 by @daniel-lxs) +- Fix: Change minItems from 2 to 1 for Anthropic API compatibility (PR #10551 by @daniel-lxs) + +## [3.39.0] - 2026-01-08 + +![3.39.0 Release - Kangaroo go BRRR](/releases/3.39.0-release.png) + +- Implement sticky provider profile for task-level API config persistence (#8010 by @hannesrudolph, PR #10018 by @hannesrudolph) +- Add support for image file @mentions (PR #10189 by @hannesrudolph) +- Rename YOLO to BRRR (#8574 by @mojomast, PR #10507 by @roomote) +- Add debug-mode proxy routing for debugging API calls (#7042 by @SleeperSmith, PR #10467 by @hannesrudolph) +- Add Kimi K2 thinking model to Fireworks AI provider (#9201 by @kavehsfv, PR #9202 by @roomote) +- Add xhigh reasoning effort to OpenAI compatible endpoints (#10060 by @Soorma718, PR #10061 by @roomote) +- Filter @ mention file search results using .rooignore (#10169 by @jerrill-johnson-bitwerx, PR #10174 by @roomote) +- Add image support documentation to read_file native tool description (#10440 by @nabilfreeman, PR #10442 by @roomote) +- Add zai-glm-4.7 to Cerebras models (PR #10500 by @sebastiand-cerebras) +- VSCode shim and basic CLI for running Roo Code headlessly (PR #10452 by @cte) +- Add CLI installer for headless Roo Code (PR #10474 by @cte) +- Add option to use CLI for evals (PR #10456 by @cte) +- Remember last Roo model selection in web-evals and add evals skill (PR #10470 by @hannesrudolph) +- Tweak the style of follow up suggestion modes (PR #9260 by @mrubens) +- Fix: Handle PowerShell ENOENT error in os-name on Windows (#9859 by @Yang-strive, PR #9897 by @roomote) +- Fix: Make command chaining examples shell-aware for Windows compatibility (#10352 by @AlexNek, PR #10434 by @roomote) +- Fix: Preserve tool_use blocks for all tool_results in kept messages during condensation (PR #10471 by @daniel-lxs) +- Fix: Add additionalProperties: false to MCP tool schemas for OpenAI Responses API (PR #10472 by @daniel-lxs) +- Fix: Prevent duplicate tool_result blocks causing API errors (PR #10497 by @daniel-lxs) +- Fix: Add explicit deduplication for duplicate tool_result blocks (#10465 by @nabilfreeman, PR #10466 by @roomote) +- Fix: Use task stored API config as fallback for rate limit (PR #10266 by @roomote) +- Fix: Remove legacy Claude 2 series models from Bedrock provider (#9220 by @KevinZhao, PR #10501 by @roomote) +- Fix: Add missing description fields for debugProxy configuration (PR #10505 by @roomote) +- Fix: Glitchy kangaroo bounce animation on welcome screen (PR #10035 by @objectiveSee) + +## [3.38.3] - 2026-01-03 + +- Feat: Add option in Context settings to recursively load `.roo/rules` and `AGENTS.md` from subdirectories (PR #10446 by @mrubens) +- Fix: Stop frequent Claude Code sign-ins by hardening OAuth refresh token handling (PR #10410 by @hannesrudolph) +- Fix: Add `maxConcurrentFileReads` limit to native `read_file` tool schema (PR #10449 by @app/roomote) +- Fix: Add type check for `lastMessage.text` in TTS useEffect to prevent runtime errors (PR #10431 by @app/roomote) + +## [3.38.2] - 2025-12-31 + +![3.38.2 Release - Skill Alignment](/releases/3.38.2-release.png) + +- Align skills system with Agent Skills specification (PR #10409 by @hannesrudolph) +- Prevent write_to_file from creating files at truncated paths (PR #10415 by @mrubens and @daniel-lxs) +- Update Cerebras maxTokens to 16384 (PR #10387 by @sebastiand-cerebras) +- Fix rate limit wait display (PR #10389 by @hannesrudolph) +- Remove human-relay provider (PR #10388 by @hannesrudolph) +- Replace Todo Lists video with Context Management video in documentation (PR #10375 by @SannidhyaSah) + +## [3.38.1] - 2025-12-29 + +![3.38.1 Release - Bug Fixes and Stability](/releases/3.38.1-release.png) + +- Fix: Flush pending tool results before condensing context (PR #10379 by @daniel-lxs) +- Fix: Revert mergeToolResultText for OpenAI-compatible providers (PR #10381 by @hannesrudolph) +- Fix: Enforce maxConcurrentFileReads limit in read_file tool (PR #10363 by @roomote) +- Fix: Improve feedback message when read_file is used on a directory (PR #10371 by @roomote) +- Fix: Handle custom tool use similarly to MCP tools for IPC schema purposes (PR #10364 by @jr) +- Fix: Correct GitHub repository URL in marketing page (#10376 by @jishnuteegala, PR #10377 by @roomote) +- Docs: Clarify path to Security Settings in privacy policy (PR #10367 by @roomote) + +## [3.38.0] - 2025-12-27 + +![3.38.0 Release - Skills](/releases/3.38.0-release.png) + +- Add support for [Agent Skills](https://agentskills.io/), enabling reusable packages of prompts, tools, and resources to extend Roo's capabilities (PR #10335 by @mrubens) +- Add optional mode field to slash command front matter, allowing commands to automatically switch to a specific mode when triggered (PR #10344 by @app/roomote) +- Add support for npm packages and .env files to custom tools, allowing custom tools to import dependencies and access environment variables (PR #10336 by @cte) +- Remove simpleReadFileTool feature, streamlining the file reading experience (PR #10254 by @app/roomote) +- Remove OpenRouter Transforms feature (PR #10341 by @app/roomote) +- Fix mergeToolResultText handling in Roo provider (PR #10359 by @mrubens) + +## [3.37.1] - 2025-12-23 + +![3.37.1 Release - Tool Fixes and Provider Improvements](/releases/3.37.1-release.png) + +- Fix: Send native tool definitions by default for OpenAI to ensure proper tool usage (PR #10314 by @hannesrudolph) +- Fix: Preserve reasoning_details shape to prevent malformed responses when processing model output (PR #10313 by @hannesrudolph) +- Fix: Drain queued messages while waiting for ask to prevent message loss (PR #10315 by @hannesrudolph) +- Feat: Add grace retry for empty assistant messages to improve reliability (PR #10297 by @hannesrudolph) +- Feat: Enable mergeToolResultText for all OpenAI-compatible providers for better tool result handling (PR #10299 by @hannesrudolph) +- Feat: Enable mergeToolResultText for Roo Code Router (PR #10301 by @hannesrudolph) +- Feat: Strengthen native tool-use guidance in prompts for improved model behavior (PR #10311 by @hannesrudolph) +- UX: Account-centric signup flow for improved onboarding experience (PR #10306 by @brunobergher) + +## [3.37.0] - 2025-12-22 + +![3.37.0 Release - Custom Tool Calling](/releases/3.37.0-release.png) + +- Add MiniMax M2.1 and improve environment_details handling for Minimax thinking models (PR #10284 by @hannesrudolph) +- Add GLM-4.7 model with thinking mode support for Zai provider (PR #10282 by @hannesrudolph) +- Add experimental custom tool calling - define custom tools that integrate seamlessly with your AI workflow (PR #10083 by @cte) +- Deprecate XML tool protocol selection and force native tool format for new tasks (PR #10281 by @daniel-lxs) +- Fix: Emit tool_call_end events in OpenAI handler when streaming ends (#10275 by @torxeon, PR #10280 by @daniel-lxs) +- Fix: Emit tool_call_end events in BaseOpenAiCompatibleProvider (PR #10293 by @hannesrudolph) +- Fix: Disable strict mode for MCP tools to preserve optional parameters (PR #10220 by @daniel-lxs) +- Fix: Move array-specific properties into anyOf variant in normalizeToolSchema (PR #10276 by @daniel-lxs) +- Fix: Add CRLF line ending normalization to search_replace and search_and_replace tools (PR #10288 by @hannesrudolph) +- Fix: Add graceful fallback for model parsing in Chutes provider (PR #10279 by @hannesrudolph) +- Fix: Enable Requesty refresh models with credentials (PR #10273 by @daniel-lxs) +- Fix: Improve reasoning_details accumulation and serialization (PR #10285 by @hannesrudolph) +- Fix: Preserve reasoning_content in condense summary for DeepSeek-reasoner (PR #10292 by @hannesrudolph) +- Refactor Zai provider to merge environment_details into tool result instead of system message (PR #10289 by @hannesrudolph) +- Remove parallel_tool_calls parameter from litellm provider (PR #10274 by @roomote) +- Add Cloud Team page with comprehensive team management features (PR #10267 by @roomote) +- Add message log deduper utility for evals (PR #10286 by @hannesrudolph) + +## [3.36.16] - 2025-12-19 + +- Fix: Normalize tool schemas for VS Code LM API to resolve error 400 when using VS Code Language Model API providers (PR #10221 by @hannesrudolph) + +## [3.36.15] - 2025-12-19 + +![3.36.15 Release - 1M Context Window Support](/releases/3.36.15-release.png) + +- Add 1M context window beta support for Claude Sonnet 4 on Vertex AI, enabling significantly larger context for complex tasks (PR #10209 by @hannesrudolph) +- Add native tool calling support for LM Studio and Qwen-Code providers, improving compatibility with local models (PR #10208 by @hannesrudolph) +- Add native tool call defaults for OpenAI-compatible providers, expanding native function calling across more configurations (PR #10213 by @hannesrudolph) +- Enable native tool calls for Requesty provider (PR #10211 by @daniel-lxs) +- Improve API error handling and visibility with clearer error messages and better user feedback (PR #10204 by @brunobergher) +- Add downloadable error diagnostics from chat errors, making it easier to troubleshoot and report issues (PR #10188 by @brunobergher) +- Fix refresh models button not properly flushing the cache, ensuring model lists update correctly (#9682 by @tl-hbk, PR #9870 by @pdecat) +- Fix additionalProperties handling for strict mode compatibility, resolving schema validation issues with certain providers (PR #10210 by @daniel-lxs) + +## [3.36.14] - 2025-12-18 + +![3.36.14 Release - Native Tool Calling for Claude on Vertex AI](/releases/3.36.14-release.png) + +- Add native tool calling support for Claude models on Vertex AI, enabling more efficient and reliable tool interactions (PR #10197 by @hannesrudolph) +- Fix JSON Schema format value stripping for OpenAI compatibility, resolving issues with unsupported format values (PR #10198 by @daniel-lxs) +- Improve "no tools used" error handling with graceful retry mechanism for better reliability when tools fail to execute (PR #10196 by @hannesrudolph) + +## [3.36.13] - 2025-12-18 + +![3.36.13 Release - Native Tool Protocol](/releases/3.36.13-release.png) + +- Change default tool protocol from XML to native for improved reliability and performance (PR #10186 by @mrubens) +- Add native tool support for VS Code Language Model API providers (PR #10191 by @daniel-lxs) +- Lock task tool protocol for consistent task resumption, ensuring tasks resume with the same protocol they started with (PR #10192 by @daniel-lxs) +- Replace edit_file tool alias with actual edit_file tool for improved diff editing capabilities (PR #9983 by @hannesrudolph) +- Fix LiteLLM router models by merging default model info for native tool calling support (PR #10187 by @daniel-lxs) +- Add PostHog exception tracking for consecutive mistake errors to improve error monitoring (PR #10193 by @daniel-lxs) + +## [3.36.12] - 2025-12-18 + +![3.36.12 Release - Better telemetry and Bedrock fixes](/releases/3.36.12-release.png) + +- Fix: Add userAgentAppId to Bedrock embedder for code indexing (#10165 by @jackrein, PR #10166 by @roomote) +- Update OpenAI and Gemini tool preferences for improved model behavior (PR #10170 by @hannesrudolph) +- Extract error messages from JSON payloads for better PostHog error grouping (PR #10163 by @daniel-lxs) + +## [3.36.11] - 2025-12-17 + +![3.36.11 Release - Native Tool Calling Enhancements](/releases/3.36.11-release.png) + +- Add support for Claude Code Provider native tool calling, improving tool execution performance and reliability (PR #10077 by @hannesrudolph) +- Enable native tool calling by default for Z.ai models for better model compatibility (PR #10158 by @app/roomote) +- Enable native tools by default for OpenAI compatible provider to improve tool calling support (PR #10159 by @daniel-lxs) +- Fix: Normalize MCP tool schemas for Bedrock and OpenAI strict mode to ensure proper tool compatibility (PR #10148 by @daniel-lxs) +- Fix: Remove dots and colons from MCP tool names for Bedrock compatibility (PR #10152 by @daniel-lxs) +- Fix: Convert tool_result to XML text when native tools disabled for Bedrock (PR #10155 by @daniel-lxs) +- Fix: Refresh Roo models cache with session token on auth state change to resolve model list refresh issues (PR #10156 by @daniel-lxs) +- Fix: Support AWS GovCloud and China region ARNs in Bedrock provider for expanded regional support (PR #10157 by @app/roomote) + +## [3.36.10] - 2025-12-17 + +![3.36.10 Release - Gemini 3 Flash Preview](/releases/3.36.10-release.png) + +- Add support for Gemini 3 Flash Preview model in the Gemini provider (PR #10151 by @hannesrudolph) +- Implement interleaved thinking mode for DeepSeek Reasoner, enabling streaming reasoning output (PR #9969 by @hannesrudolph) +- Fix: Preserve reasoning_content during tool call sequences in DeepSeek (PR #10141 by @hannesrudolph) +- Fix: Correct token counting for context truncation display (PR #9961 by @hannesrudolph) +- Update Next.js dependency to ~15.2.8 (PR #10140 by @jr) + +## [3.36.9] - 2025-12-15 + +![3.36.9 Release - Cross-Provider Compatibility](/releases/3.36.9-release.png) + +- Fix: Normalize tool call IDs for cross-provider compatibility via OpenRouter, ensuring consistent handling across different AI providers (PR #10102 by @daniel-lxs) +- Fix: Add additionalProperties: false to nested MCP tool schemas, improving schema validation and preventing unexpected properties (PR #10109 by @daniel-lxs) +- Fix: Validate tool_result IDs in delegation resume flow, preventing errors when resuming delegated tasks (PR #10135 by @daniel-lxs) +- Feat: Add full error details to streaming failure dialog, providing more comprehensive information for debugging streaming issues (PR #10131 by @roomote) +- Feat: Improve evals UI with tool groups and duration fix, enhancing the evaluation interface organization and timing accuracy (PR #10133 by @hannesrudolph) + +## [3.36.8] - 2025-12-16 + +![3.36.8 Release - Native Tools Enabled by Default](/releases/3.36.8-release.png) + +- Implement incremental token-budgeted file reading for smarter, more efficient file content retrieval (PR #10052 by @jr) +- Enable native tools by default for multiple providers including OpenAI, Azure, Google, Vertex, and more (PR #10059 by @daniel-lxs) +- Enable native tools by default for Anthropic and add telemetry tracking for tool format usage (PR #10021 by @daniel-lxs) +- Fix: Prevent race condition from deleting wrong API messages during streaming (PR #10113 by @hannesrudolph) +- Fix: Prevent duplicate MCP tools error by deduplicating servers at source (PR #10096 by @daniel-lxs) +- Remove strict ARN validation for Bedrock custom ARN users allowing more flexibility (#10108 by @wisestmumbler, PR #10110 by @roomote) +- Add metadata to error details dialog for improved debugging (PR #10050 by @roomote) +- Add configuration to control public sharing feature (PR #10105 by @mrubens) +- Remove description from Bedrock service tiers for cleaner UI (PR #10118 by @mrubens) +- Fix: Correct link to provider pricing page on web (PR #10107 by @brunobergher) + +## [3.36.7] - 2025-12-15 + +- Improve tool configuration for OpenAI models in OpenRouter (PR #10082 by @hannesrudolph) +- Capture more detailed provider-specific error information from OpenRouter for better debugging (PR #10073 by @jr) +- Add Amazon Nova 2 Lite model to Bedrock provider (#9802 by @Smartsheet-JB-Brown, PR #9830 by @roomote) +- Add AWS Bedrock service tier support (#9874 by @Smartsheet-JB-Brown, PR #9955 by @roomote) +- Remove auto-approve toggles for to-do and retry actions to simplify the approval workflow (PR #10062 by @hannesrudolph) +- Move isToolAllowedForMode out of shared directory for better code organization (PR #10089 by @cte) +- Improve run logs and formatters in web-evals for better evaluation tracking (PR #10081 by @hannesrudolph) + +## [3.36.6] - 2025-12-12 + +![3.36.6 Release - Tool Alias Support](/releases/3.36.6-release.png) + +- Add tool alias support for model-specific tool customization, allowing users to configure how tools are presented to different AI models (PR #9989 by @daniel-lxs) +- Sanitize MCP server and tool names for API compatibility, ensuring special characters don't cause issues with API calls (PR #10054 by @daniel-lxs) +- Improve auto-approve timer visibility in follow-up suggestions for better user awareness of pending actions (PR #10048 by @brunobergher) +- Fix: Cancel auto-approval timeout when user starts typing, preventing accidental auto-approvals during user interaction (PR #9937 by @roomote) +- Add WorkspaceTaskVisibility type for organization cloud settings to support team visibility controls (PR #10020 by @roomote) +- Fix: Extract raw error message from OpenRouter metadata for clearer error reporting (PR #10039 by @daniel-lxs) +- Fix: Show tool protocol dropdown for LiteLLM provider, restoring missing configuration option (PR #10053 by @daniel-lxs) + +## [3.36.5] - 2025-12-11 + +![3.36.5 Release - GPT-5.2](/releases/3.36.5-release.png) + +- Add: GPT-5.2 model to openai-native provider (PR #10024 by @hannesrudolph) +- Add: Toggle for Enter key behavior in chat input allowing users to configure whether Enter sends or creates new line (#8555 by @lmtr0, PR #10002 by @hannesrudolph) +- Add: App version to telemetry exception captures and filter 402 errors (PR #9996 by @daniel-lxs) +- Fix: Handle empty Gemini responses and reasoning loops to prevent infinite retries (PR #10007 by @hannesrudolph) +- Fix: Add missing tool_result blocks to prevent API errors when tool results are expected (PR #10015 by @daniel-lxs) +- Fix: Filter orphaned tool_results when more results than tool_uses to prevent message validation errors (PR #10027 by @daniel-lxs) +- Fix: Add general API endpoints for Z.ai provider (#9879 by @richtong, PR #9894 by @roomote) +- Fix: Apply versioned settings on nightly builds (PR #9997 by @hannesrudolph) +- Remove: Glama provider (PR #9801 by @hannesrudolph) +- Remove: Deprecated list_code_definition_names tool (PR #10005 by @hannesrudolph) + +## [3.36.4] - 2025-12-10 + +![3.36.4 Release - Error Details Modal](/releases/3.36.4-release.png) + +- Add error details modal with on-demand display for improved error visibility when debugging issues (PR #9985 by @roomote) +- Fix: Prevent premature rawChunkTracker clearing for MCP tools, improving reliability of MCP tool streaming (PR #9993 by @daniel-lxs) +- Fix: Filter out 429 rate limit errors from API error telemetry for cleaner metrics (PR #9987 by @daniel-lxs) +- Fix: Correct TODO list display order in chat view to show items in proper sequence (PR #9991 by @roomote) + +## [3.36.3] - 2025-12-09 + +![3.36.3 Release](/releases/3.36.3-release.png) + +- Refactor: Unified context-management architecture with improved UX for better context control (PR #9795 by @hannesrudolph) +- Add new `search_replace` native tool for single-replacement operations with improved editing precision (PR #9918 by @hannesrudolph) +- Streaming tool stats and token usage throttling for better real-time feedback during generation (PR #9926 by @hannesrudolph) +- Add versioned settings support with minPluginVersion gating for Roo provider (PR #9934 by @hannesrudolph) +- Make Architect mode save plans to `/plans` directory and gitignore it (PR #9944 by @brunobergher) +- Add announcement support CTA and social icons to UI (PR #9945 by @hannesrudolph) +- Add ability to save screenshots from the browser tool (PR #9963 by @mrubens) +- Refactor: Decouple tools from system prompt for cleaner architecture (PR #9784 by @daniel-lxs) +- Update DeepSeek models to V3.2 with new pricing (PR #9962 by @hannesrudolph) +- Add minimal and medium reasoning effort levels for Gemini models (PR #9973 by @hannesrudolph) +- Update xAI models catalog with latest model options (PR #9872 by @hannesrudolph) +- Add DeepSeek V3-2 support for Baseten provider (PR #9861 by @AlexKer) +- Tweaks to Baseten model definitions for better defaults (PR #9866 by @mrubens) +- Fix: Add xhigh reasoning effort support for gpt-5.1-codex-max (#9891 by @andrewginns, PR #9900 by @andrewginns) +- Fix: Add Kimi, MiniMax, and Qwen model configurations for Bedrock (#9902 by @jbearak, PR #9905 by @app/roomote) +- Configure tool preferences for xAI models (PR #9923 by @hannesrudolph) +- Default to using native tools when supported on OpenRouter (PR #9878 by @mrubens) +- Fix: Exclude apply_diff from native tools when diffEnabled is false (#9919 by @denis-kudelin, PR #9920 by @app/roomote) +- Fix: Always show tool protocol selector for openai-compatible provider (#9965 by @bozoweed, PR #9966 by @hannesrudolph) +- Fix: Respect explicit supportsReasoningEffort array values for proper model configuration (PR #9970 by @hannesrudolph) +- Add timeout configuration to OpenAI Compatible Provider Client (PR #9898 by @dcbartlett) +- Revert default tool protocol change from xml to native for stability (PR #9956 by @mrubens) +- Remove defaultTemperature from Roo provider configuration (PR #9932 by @mrubens) +- Improve OpenAI error messages to be more useful for debugging (PR #9639 by @mrubens) +- Better error logs for parseToolCall exceptions (PR #9857 by @cte) +- Improve cloud job error logging for RCC provider errors (PR #9924 by @cte) +- Fix: Display actual API error message instead of generic text on retry (PR #9954 by @hannesrudolph) +- Add API error telemetry to OpenRouter provider for better diagnostics (PR #9953 by @daniel-lxs) +- Fix: Sanitize removed/invalid API providers to prevent infinite loop (PR #9869 by @hannesrudolph) +- Fix: Use foreground color for context-management icons (PR #9912 by @hannesrudolph) +- Fix: Suppress 'ask promise was ignored' error in handleError (PR #9914 by @daniel-lxs) +- Fix: Process finish_reason to emit tool_call_end events properly (PR #9927 by @daniel-lxs) +- Fix: Add finish_reason processing to xai.ts provider (PR #9929 by @daniel-lxs) +- Fix: Validate and fix tool_result IDs before API requests (PR #9952 by @daniel-lxs) +- Fix: Return undefined instead of 0 for disabled API timeout (PR #9960 by @hannesrudolph) +- Stop making unnecessary count_tokens requests for better performance (PR #9884 by @mrubens) +- Refactor: Consolidate ThinkingBudget components and fix disable handling (PR #9930 by @hannesrudolph) +- Forbid time estimates in architect mode for more focused planning (PR #9931 by @app/roomote) +- Web: Add product pages (PR #9865 by @brunobergher) +- Make eval runs deletable in the web UI (PR #9909 by @mrubens) +- Feat: Change defaultToolProtocol default from xml to native (later reverted) (PR #9892 by @app/roomote) + +## [3.36.2] - 2025-12-04 + +![3.36.2 Release - Dynamic API Settings](/releases/3.36.2-release.png) + +- Restrict GPT-5 tool set to apply_patch for improved compatibility (PR #9853 by @hannesrudolph) +- Add dynamic settings support for Roo models from API, allowing model-specific configurations to be fetched dynamically (PR #9852 by @hannesrudolph) +- Fix: Resolve Chutes provider model fetching issue (PR #9854 by @cte) + +## [3.36.1] - 2025-12-04 + +![3.36.1 Release - Message Management & Stability Improvements](/releases/3.36.1-release.png) + +- Add MessageManager layer for centralized history coordination, fixing message synchronization issues (PR #9842 by @hannesrudolph) +- Fix: Prevent cascading truncation loop by only truncating visible messages (PR #9844 by @hannesrudolph) +- Fix: Handle unknown/invalid native tool calls to prevent extension freeze (PR #9834 by @daniel-lxs) +- Always enable reasoning for models that require it (PR #9836 by @cte) +- ChatView: Smoother stick-to-bottom behavior during streaming (PR #8999 by @hannesrudolph) +- UX: Improved error messages and documentation links (PR #9777 by @brunobergher) +- Fix: Overly round follow-up question suggestions styling (PR #9829 by @brunobergher) +- Add symlink support for slash commands in .roo/commands folder (PR #9838 by @mrubens) +- Ignore input to the execa terminal process for safer command execution (PR #9827 by @mrubens) +- Be safer about large file reads (PR #9843 by @jr) +- Add gpt-5.1-codex-max model to OpenAI provider (PR #9848 by @hannesrudolph) +- Evals UI: Add filtering, bulk delete, tool consolidation, and run notes (PR #9837 by @hannesrudolph) +- Evals UI: Add multi-model launch and UI improvements (PR #9845 by @hannesrudolph) +- Web: New pricing page (PR #9821 by @brunobergher) + +## [3.36.0] - 2025-12-04 + +![3.36.0 Release - Rewind Kangaroo](/releases/3.36.0-release.png) + +- Fix: Restore context when rewinding after condense (#8295 by @hannesrudolph, PR #9665 by @hannesrudolph) +- Add reasoning_details support to Roo provider for enhanced model reasoning visibility (PR #9796 by @app/roomote) +- Default to native tools for all models in the Roo provider for improved performance (PR #9811 by @mrubens) +- Enable search_and_replace for Minimax models (PR #9780 by @mrubens) +- Fix: Resolve Vercel AI Gateway model fetching issues (PR #9791 by @cte) +- Fix: Apply conservative max tokens for Cerebras provider (PR #9804 by @sebastiand-cerebras) +- Fix: Remove omission detection logic to eliminate false positives (#9785 by @Michaelzag, PR #9787 by @app/roomote) +- Refactor: Remove deprecated insert_content tool (PR #9751 by @daniel-lxs) +- Chore: Hide parallel tool calls experiment and disable feature (PR #9798 by @hannesrudolph) +- Update next.js documentation site dependencies (PR #9799 by @jr) +- Fix: Correct download count display on homepage (PR #9807 by @mrubens) + +## [3.35.5] - 2025-12-03 + +- Feat: Add provider routing selection for OpenRouter embeddings (#9144 by @SannidhyaSah, PR #9693 by @SannidhyaSah) +- Default Minimax M2 to native tool calling (PR #9778 by @mrubens) +- Sanitize the native tool calls to fix a bug with Gemini (PR #9769 by @mrubens) +- UX: Updates to CloudView (PR #9776 by @roomote) + +## [3.35.4] - 2025-12-02 + +- Fix: Handle malformed native tool calls to prevent hanging (PR #9758 by @daniel-lxs) +- Fix: Remove reasoning toggles for GLM-4.5 and GLM-4.6 on z.ai provider (PR #9752 by @roomote) +- Refactor: Remove line_count parameter from write_to_file tool (PR #9667 by @hannesrudolph) + +## [3.35.3] - 2025-12-02 + +- Switch to new welcome view for improved onboarding experience (PR #9741 by @mrubens) +- Update homepage with latest changes (PR #9675 by @brunobergher) +- Improve privacy for stealth models by adding vendor confidentiality section to system prompt (PR #9742 by @mrubens) + +## [3.35.2] - 2025-12-01 + +![3.35.2 Release - Model Default Temperatures](/releases/3.35.2-release.png) + +- Allow models to contain default temperature settings for provider-specific optimal defaults (PR #9734 by @mrubens) +- Add tag-based native tool calling detection for Roo provider models (PR #9735 by @mrubens) +- Enable native tool support for all LiteLLM models by default (PR #9736 by @mrubens) +- Pass app version to provider for improved request tracking (PR #9730 by @cte) + +## [3.35.1] - 2025-12-01 + +- Fix: Flush pending tool results before task delegation (PR #9726 by @daniel-lxs) +- Improve: Better IPC error logging for easier debugging (PR #9727 by @cte) + +## [3.35.0] - 2025-12-01 + +![3.35.0 Release - Subtasks & Native Tools](/releases/3.35.0-release.png) + +- Metadata-driven subtasks with automatic parent resume and single-open safety for improved task orchestration (#8081 by @hannesrudolph, PR #9090 by @hannesrudolph) +- Native tool calling support expanded across many providers: Bedrock (PR #9698 by @mrubens), Cerebras (PR #9692 by @mrubens), Chutes with auto-detection from API (PR #9715 by @daniel-lxs), DeepInfra (PR #9691 by @mrubens), DeepSeek and Doubao (PR #9671 by @daniel-lxs), Groq (PR #9673 by @daniel-lxs), LiteLLM (PR #9719 by @daniel-lxs), Ollama (PR #9696 by @mrubens), OpenAI-compatible providers (PR #9676 by @daniel-lxs), Requesty (PR #9672 by @daniel-lxs), Unbound (PR #9699 by @mrubens), Vercel AI Gateway (PR #9697 by @mrubens), Vertex Gemini (PR #9678 by @daniel-lxs), and xAI with new Grok 4 Fast and Grok 4.1 Fast models (PR #9690 by @mrubens) +- Fix: Preserve tool_use blocks in summary for parallel tool calls (#9700 by @SilentFlower, PR #9714 by @SilentFlower) +- Default Grok Code Fast to native tools for better performance (PR #9717 by @mrubens) +- UX improvements to the Roo Code Router-centric onboarding flow (PR #9709 by @brunobergher) +- UX toolbar cleanup and settings consolidation for a cleaner interface (PR #9710 by @brunobergher) +- Add model-specific tool customization via `excludedTools` and `includedTools` configuration (PR #9641 by @daniel-lxs) +- Add new `apply_patch` native tool for more efficient file editing operations (PR #9663 by @hannesrudolph) +- Add new `search_and_replace` tool for batch text replacements across files (PR #9549 by @hannesrudolph) +- Add debug buttons to view API and UI history for troubleshooting (PR #9684 by @hannesrudolph) +- Include tool format in environment details for better context awareness (PR #9661 by @mrubens) +- Fix: Display install count in millions instead of thousands (PR #9677 by @app/roomote) +- Web-evals improvements: add task log viewing, export failed logs, and new run options (PR #9637 by @hannesrudolph) +- Web-evals updates: add kill run functionality (PR #9681 by @hannesrudolph) +- Fix: Prevent navigation buttons from wrapping on smaller screens (PR #9721 by @app/roomote) + +## [3.34.8] - 2025-11-27 + +![3.34.8 Release - Race Condition Fix](/releases/3.34.8-release.png) + +- Fix: Race condition in new_task tool for native protocol (PR #9655 by @daniel-lxs) + +## [3.34.7] - 2025-11-27 + +![3.34.7 Release - More Native Tool Integrations](/releases/3.34.7-release.png) + +- Support native tools in the Anthropic provider for improved tool calling (PR #9644 by @mrubens) +- Enable native tool calling for z.ai models (PR #9645 by @mrubens) +- Enable native tool calling for Moonshot models (PR #9646 by @mrubens) +- Fix: OpenRouter tool calls handling improvements (PR #9642 by @mrubens) +- Fix: OpenRouter GPT-5 strict schema validation for read_file tool (PR #9633 by @daniel-lxs) +- Fix: Create parent directories early in write_to_file to prevent ENOENT errors (#9634 by @ivanenev, PR #9640 by @daniel-lxs) +- Fix: Disable native tools and temperature support for claude-code provider (PR #9643 by @hannesrudolph) +- Add 'taking you to cloud' screen after provider welcome for improved onboarding (PR #9652 by @mrubens) + +## [3.34.6] - 2025-11-26 + +![3.34.6 Release - Bedrock Embeddings](/releases/3.34.6-release.png) + +- Add support for AWS Bedrock embeddings in code indexing (#8658 by @kyle-hobbs, PR #9475 by @ggoranov-smar) +- Add native tool calling support for Mistral provider (PR #9625 by @hannesrudolph) +- Wire MULTIPLE_NATIVE_TOOL_CALLS experiment to OpenAI parallel_tool_calls for parallel tool execution (PR #9621 by @hannesrudolph) +- Add fine grained tool streaming for OpenRouter Anthropic (PR #9629 by @mrubens) +- Allow global inference selection for Bedrock when cross-region is enabled (PR #9616 by @roomote) +- Fix: Filter non-Anthropic content blocks before sending to Vertex API (#9583 by @cardil, PR #9618 by @hannesrudolph) +- Fix: Restore content undefined check in WriteToFileTool.handlePartial() (#9611 by @Lissanro, PR #9614 by @daniel-lxs) +- Fix: Prevent model cache from persisting empty API responses (#9597 by @zx2021210538, PR #9623 by @daniel-lxs) +- Fix: Exclude access_mcp_resource tool when MCP has no resources (PR #9615 by @daniel-lxs) +- Fix: Update default settings for inline terminal and codebase indexing (PR #9622 by @roomote) +- Fix: Convert line_ranges strings to lineRanges objects in native tool calls (PR #9627 by @daniel-lxs) +- Fix: Defer new_task tool_result until subtask completes for native protocol (PR #9628 by @daniel-lxs) + +## [3.34.5] - 2025-11-25 + +![3.34.5 Release - Experimental Parallel Tool Calling](/releases/3.34.5-release.png) + +- Experimental feature to enable multiple native tool calls per turn (PR #9273 by @daniel-lxs) +- Add Bedrock Opus 4.5 to global inference model list (PR #9595 by @roomote) +- Fix: Update API handler when toolProtocol changes (PR #9599 by @mrubens) +- Set native tools as default for minimax-m2 and claude-haiku-4.5 (PR #9586 by @daniel-lxs) +- Make single file read only apply to XML tools (PR #9600 by @mrubens) +- Enhance web-evals dashboard with dynamic tool columns and UX improvements (PR #9592 by @hannesrudolph) +- Revert "Add support for Roo Code Cloud as an embeddings provider" while we fix some issues (PR #9602 by @mrubens) + +## [3.34.4] - 2025-11-25 + +![3.34.4 Release - BFL Image Generation](/releases/3.34.4-release.png) + +- Add new Black Forest Labs image generation models, free on Roo Code Cloud and also available on OpenRouter (PR #9587 and #9589 by @mrubens) +- Fix: Preserve dynamic MCP tool names in native mode API history to prevent tool name mismatches (PR #9559 by @daniel-lxs) +- Fix: Preserve tool_use blocks in summary message during condensing with native tools to maintain conversation context (PR #9582 by @daniel-lxs) + +## [3.34.3] - 2025-11-25 + +![3.34.3 Release - Streaming and Opus 4.5](/releases/3.34.3-release.png) + +- Implement streaming for native tool calls, providing real-time feedback during tool execution (PR #9542 by @daniel-lxs) +- Add Claude Opus 4.5 model to Claude Code provider (PR #9560 by @mrubens) +- Add Claude Opus 4.5 model to Bedrock provider (#9571 by @pisicode, PR #9572 by @roomote) +- Enable caching for Opus 4.5 model to improve performance (#9567 by @iainRedro, PR #9568 by @roomote) +- Add support for Roo Code Cloud as an embeddings provider (PR #9543 by @mrubens) +- Fix ask_followup_question streaming issue and add missing tool cases (PR #9561 by @daniel-lxs) +- Add contact links to About Roo Code settings page (PR #9570 by @roomote) +- Switch from asdf to mise-en-place in bare-metal evals setup script (PR #9548 by @cte) + +## [3.34.2] - 2025-11-24 + +![3.34.2 Release - Opus Conductor](/releases/3.34.2-release.png) + +- Add support for Claude Opus 4.5 in Anthropic and Vertex providers (PR #9541 by @daniel-lxs) +- Add support for Claude Opus 4.5 in OpenRouter with prompt caching and reasoning budget (PR #9540 by @daniel-lxs) +- Add Roo Code Cloud as an image generation provider (PR #9528 by @mrubens) +- Fix: Gracefully skip unsupported content blocks in Gemini transformer (PR #9537 by @daniel-lxs) +- Fix: Flush LiteLLM cache when credentials change on refresh (PR #9536 by @daniel-lxs) +- Fix: Ensure XML parser state matches tool protocol on config update (PR #9535 by @daniel-lxs) +- Update Cerebras models (PR #9527 by @sebastiand-cerebras) +- Fix: Support reasoning_details format for Gemini 3 models (PR #9506 by @daniel-lxs) + +## [3.34.1] - 2025-11-23 + +- Show the prompt for image generation in the UI (PR #9505 by @mrubens) +- Fix double todo list display issue (PR #9517 by @mrubens) +- Add tracking for cloud synced messages (PR #9518 by @mrubens) +- Enable the Roo Code Router in evals (PR #9492 by @cte) + +## [3.34.0] - 2025-11-21 + +![3.34.0 Release - Browser Use 2.0](/releases/3.34.0-release.png) + +- Add Browser Use 2.0 with enhanced browser interaction capabilities (PR #8941 by @hannesrudolph) +- Add support for Baseten as a new AI provider (PR #9461 by @AlexKer) +- Improve base OpenAI compatible provider with better error handling and configuration (PR #9462 by @mrubens) +- Add provider-oriented welcome screen to improve onboarding experience (PR #9484 by @mrubens) +- Pin Roo provider to the top of the provider list for better discoverability (PR #9485 by @mrubens) +- Enhance native tool descriptions with examples and clarifications for better AI understanding (PR #9486 by @daniel-lxs) +- Fix: Make cancel button immediately responsive during streaming (#9435 by @jwadow, PR #9448 by @daniel-lxs) +- Fix: Resolve apply_diff performance regression from earlier changes (PR #9474 by @daniel-lxs) +- Fix: Implement model cache refresh to prevent stale disk cache issues (PR #9478 by @daniel-lxs) +- Fix: Copy model-level capabilities to OpenRouter endpoint models correctly (PR #9483 by @daniel-lxs) +- Fix: Add fallback to yield tool calls regardless of finish_reason (PR #9476 by @daniel-lxs) + +## [3.33.3] - 2025-11-20 + +![3.33.3 Release - Gemini 3 Pro Image Preview](/releases/3.33.3-release.png) + +- Add Google Gemini 3 Pro Image Preview to image generation models (PR #9440 by @app/roomote) +- Add support for Minimax as Anthropic-compatible provider (PR #9455 by @daniel-lxs) +- Store reasoning in conversation history for all providers (PR #9451 by @daniel-lxs) +- Fix: Improve preserveReasoning flag to control API reasoning inclusion (PR #9453 by @daniel-lxs) +- Fix: Prevent OpenAI Native parallel tool calls for native tool calling (PR #9433 by @hannesrudolph) +- Fix: Improve search and replace symbol parsing (PR #9456 by @daniel-lxs) +- Fix: Send tool_result blocks for skipped tools in native protocol (PR #9457 by @daniel-lxs) +- Fix: Improve markdown formatting and add reasoning support (PR #9458 by @daniel-lxs) +- Fix: Prevent duplicate environment_details when resuming cancelled tasks (PR #9442 by @daniel-lxs) +- Improve read_file tool description with examples (PR #9422 by @daniel-lxs) +- Update glob dependency to ^11.1.0 (PR #9449 by @jr) +- Update tar-fs to 3.1.1 via pnpm override (PR #9450 by @app/roomote) + +## [3.33.2] - 2025-11-19 + +- Enable native tool calling for Gemini provider (PR #9343 by @hannesrudolph) +- Add RCC credit balance display (PR #9386 by @jr) +- Fix: Preserve user images in native tool call results (PR #9401 by @daniel-lxs) +- Perf: Reduce excessive getModel() calls and implement disk cache fallback (PR #9410 by @daniel-lxs) +- Show zero price for free models (PR #9419 by @mrubens) + +## [3.33.1] - 2025-11-18 + +![3.33.1 Release - Native Tool Protocol Fixes](/releases/3.33.1-release.png) + +- Add native tool calling support to OpenAI-compatible (PR #9369 by @mrubens) +- Fix: Resolve native tool protocol race condition causing 400 errors (PR #9363 by @daniel-lxs) +- Fix: Update tools to return structured JSON for native protocol (PR #9373 by @daniel-lxs) +- Fix: Include nativeArgs in tool repetition detection (PR #9377 by @daniel-lxs) +- Fix: Ensure no XML parsing when protocol is native (PR #9371 by @daniel-lxs) +- Fix: Gemini maxOutputTokens and reasoning config (PR #9375 by @hannesrudolph) +- Fix: Gemini thought signature validation and token counting errors (PR #9380 by @hannesrudolph) +- Fix: Exclude XML tool examples from MODES section when native protocol enabled (PR #9367 by @daniel-lxs) +- Retry eval tasks if API instability detected (PR #9365 by @cte) +- Add toolProtocol property to PostHog tool usage telemetry (PR #9374 by @app/roomote) + +## [3.33.0] - 2025-11-18 + +![3.33.0 Release - Twin Kangaroos and the Gemini Constellation](/releases/3.33.0-release.png) + +- Add Gemini 3 Pro Preview model (PR #9357 by @hannesrudolph) +- Improve Google Gemini defaults with better temperature and cost reporting (PR #9327 by @hannesrudolph) +- Enable native tool calling for openai-native provider (PR #9348 by @hannesrudolph) +- Add git status information to environment details (PR #9310 by @daniel-lxs) +- Add tool protocol selector to advanced settings (PR #9324 by @daniel-lxs) +- Implement dynamic tool protocol resolution with proper precedence hierarchy (PR #9286 by @daniel-lxs) +- Move Import/Export functionality to Modes view toolbar and cleanup Mode Edit view (PR #9077 by @hannesrudolph) +- Update cloud agent CTA to point to setup page (PR #9338 by @app/roomote) +- Fix: Prevent duplicate tool_result blocks in native tool protocol (PR #9248 by @daniel-lxs) +- Fix: Format tool responses properly for native protocol (PR #9270 by @daniel-lxs) +- Fix: Centralize toolProtocol configuration checks (PR #9279 by @daniel-lxs) +- Fix: Preserve tool blocks for native protocol in conversation history (PR #9319 by @daniel-lxs) +- Fix: Prevent infinite loop when task_done succeeds (PR #9325 by @daniel-lxs) +- Fix: Sync parser state with profile/model changes (PR #9355 by @daniel-lxs) +- Fix: Pass tool protocol parameter to lineCountTruncationError (PR #9358 by @daniel-lxs) +- Use VSCode theme color for outline button borders (PR #9336 by @app/roomote) +- Replace broken badgen.net badges with shields.io (PR #9318 by @app/roomote) +- Add max git status files setting to evals (PR #9322 by @mrubens) +- Roo Code Router pricing page and changes elsewhere (PR #9195 by @brunobergher) + +## [3.32.1] - 2025-11-14 + +![3.32.1 Release - Bug Fixes](/releases/3.32.1-release.png) + +- Fix: Add abort controller for request cancellation in OpenAI native protocol (PR #9276 by @daniel-lxs) +- Fix: Resolve duplicate tool blocks causing 'tool has already been used' error in native protocol mode (PR #9275 by @daniel-lxs) +- Fix: Prevent duplicate tool_result blocks in native protocol mode for read_file (PR #9272 by @daniel-lxs) +- Fix: Correct OpenAI Native handling of encrypted reasoning blocks to prevent errors during condensing (PR #9263 by @hannesrudolph) +- Fix: Disable XML parser for native tool protocol to prevent parsing conflicts (PR #9277 by @daniel-lxs) + +## [3.32.0] - 2025-11-14 + +![3.32.0 Release - GPT-5.1 models and OpenAI prompt caching](/releases/3.32.0-release.png) + +- Feature: Add GPT-5.1 models to OpenAI provider (PR #9252 by @hannesrudolph) +- Feature: Support for OpenAI Responses 24 hour prompt caching (PR #9259 by @hannesrudolph) +- Fix: Repair the share button in the UI (PR #9253 by @hannesrudolph) +- Docs: Include PR numbers in the release guide to improve traceability (PR #9236 by @hannesrudolph) + +## [3.31.3] - 2025-11-13 + +![3.31.3 Release - Kangaroo Decrypting a Message](/releases/3.31.3-release.png) + +- Fix: OpenAI Native encrypted_content handling and remove gpt-5-chat-latest verbosity flag (#9225 by @politsin, PR by @hannesrudolph) +- Fix: Roo Code Router Anthropic input token normalization to avoid double-counting (thanks @hannesrudolph!) +- Refactor: Rename sliding-window to context-management and truncateConversationIfNeeded to manageContext (thanks @hannesrudolph!) + +## [3.31.2] - 2025-11-12 + +- Fix: Apply updated API profile settings when provider/model unchanged (#9208 by @hannesrudolph, PR by @hannesrudolph) +- Migrate conversation continuity to plugin-side encrypted reasoning items using Responses API for improved reliability (thanks @hannesrudolph!) +- Fix: Include mcpServers in getState() for auto-approval (#9190 by @bozoweed, PR by @daniel-lxs) +- Batch settings updates from the webview to the extension host for improved performance (thanks @cte!) +- Fix: Replace rate-limited badges with badgen.net to improve README reliability (thanks @daniel-lxs!) + +## [3.31.1] - 2025-11-11 + +![3.31.1 Release - Kangaroo Stuck in the Clouds](/releases/3.31.1-release.png) + +- Fix: Prevent command_output ask from blocking in cloud/headless environments (thanks @daniel-lxs!) +- Add IPC command for sending messages to the current task (thanks @mrubens!) +- Fix: Model switch re-applies selected profile, ensuring task configuration stays in sync (#9179 by @hannesrudolph, PR by @hannesrudolph) +- Move auto-approval logic from `ChatView` to `Task` for better architecture (thanks @cte!) +- Add custom Button component with variant system (thanks @brunobergher!) + +## [3.31.0] - 2025-11-07 + +![3.31.0 Release - Todo List and Task Header Improvements](/releases/3.31.0-release.png) + +- Improvements to to-do lists and task headers (thanks @brunobergher!) +- Fix: Prevent crash when streaming chunks have null choices array (thanks @daniel-lxs!) +- Fix: Prevent context condensing on settings save when provider/model unchanged (#4430 by @hannesrudolph, PR by @daniel-lxs) +- Fix: Respect custom OpenRouter URL for all API operations (#8947 by @sstraus, PR by @roomote) +- Add comprehensive error logging to Roo Cloud provider (thanks @daniel-lxs!) +- UX: Less caffeinated kangaroo (thanks @brunobergher!) + +## [3.30.3] - 2025-11-06 + +![3.30.3 Release - Moonshot Brain](/releases/3.30.3-release.png) + +- Feat: Add kimi-k2-thinking model to Moonshot provider (thanks @daniel-lxs!) +- Fix: Auto-retry on empty assistant response to prevent task failures (#9076 by @Akillatech, PR by @daniel-lxs) +- Fix: Use system role for OpenAI Compatible provider when streaming is disabled (#8215 by @whitfin, PR by @roomote) +- Fix: Prevent notification sound on attempt_completion with queued messages (#8537 by @hannesrudolph, PR by @roomote) +- Feat: Auto-switch to imported mode with architect fallback for better mode detection (#8239 by @hannesrudolph, PR by @daniel-lxs) +- Feat: Add MiniMax-M2-Stable model and enable prompt caching (#9070 by @nokaka, PR by @roomote) +- Feat: Improve diff appearance in main chat view (thanks @hannesrudolph!) +- UX: Home screen visuals (thanks @brunobergher!) +- Docs: Clarify that setting 0 disables Error & Repetition Limit (thanks @roomote!) +- Chore: Update dependency @changesets/cli to v2.29.7 (thanks @renovate!) + +## [3.30.2] - 2025-11-05 + +![3.30.2 Release - Eliminating UI Flicker](/releases/3.30.2-release.png) + +- Fix: eliminate UI flicker during task cancellation (thanks @daniel-lxs!) +- Add Global Inference support for Bedrock models (#8750 by @ronyblum, PR by @hannesrudolph) +- Add Qwen3 embedding models (0.6B and 4B) to OpenRouter support (#9058 by @dmarkey, PR by @app/roomote) +- Fix: resolve incorrect commit location when GIT_DIR set in Dev Containers (#4567 by @nonsleepr, PR by @heyseth) +- Fix: keep pinned models fixed at top of scrollable list (#8812 by @XiaoYingYo, PR by @app/roomote) +- Fix: update Opus 4.1 max tokens from 8K to 32K (#9045 by @kaveh-deriv, PR by @app/roomote) +- Set Claude Sonnet 4.5 as default for key providers (thanks @hannesrudolph!) +- Fix: dynamic provider model validation to prevent cross-contamination (#9047 by @NotADev137, PR by @daniel-lxs) +- Fix: Bedrock user agent to report full SDK details (#9031 by @ajjuaire, PR by @ajjuaire) +- Add file path tooltips with centralized PathTooltip component (#8278 by @da2ce7, PR by @daniel-lxs) +- Add conditional test running to pre-push hook (thanks @daniel-lxs!) +- Update Cerebras integration (thanks @sebastiand-cerebras!) + +## [3.30.1] - 2025-11-04 + +- Fix: Correct OpenRouter Mistral model embedding dimension from 3072 to 1536 (thanks @daniel-lxs!) +- Revert: Previous UI flicker fix that caused issues with task resumption (thanks @mrubens!) + +## [3.30.0] - 2025-11-03 + +![3.30.0 Release - PR Fixer](/releases/3.30.0-release.png) + +- Feat: Add OpenRouter embedding provider support (#8972 by @dmarkey, PR by @dmarkey) +- Feat: Add GLM-4.6 model to Fireworks provider (#8752 by @mmealman, PR by @app/roomote) +- Feat: Add MiniMax M2 model to Fireworks provider (#8961 by @dmarkey, PR by @app/roomote) +- Feat: Add preserveReasoning flag to include reasoning in API history (thanks @daniel-lxs!) +- Fix: Prevent message loss during queue drain race condition (#8536 by @hannesrudolph, PR by @daniel-lxs) +- Fix: Capture the reasoning content in base-openai-compatible for GLM 4.6 (thanks @mrubens!) +- Fix: Create new Requesty profile during OAuth (thanks @Thibault00!) +- Fix: Prevent UI flicker and enable resumption after task cancellation (thanks @daniel-lxs!) +- Fix: Cleanup terminal settings tab and change default terminal to inline (thanks @hannesrudolph!) + +## [3.29.5] - 2025-11-01 + +- Fix: Resolve Qdrant codebase_search error by adding keyword index for type field (#8963 by @rossdonald, PR by @app/roomote) +- Fix cost and token tracking between provider styles to ensure accurate usage metrics (thanks @mrubens!) + +## [3.29.4] - 2025-10-30 + +- Feat: Add Minimax Provider (thanks @Maosghoul!) +- Fix: prevent infinite loop when canceling during auto-retry (#8901 by @mini2s, PR by @app/roomote) +- Fix: Enhanced codebase index recovery and reuse ('Start Indexing' button now reuses existing Qdrant index) (#8129 by @jaroslaw-weber, PR by @heyseth) +- Fix: make code index initialization non-blocking at activation (#8777 by @cjlawson02, PR by @daniel-lxs) +- Fix: remove search_and_replace tool from codebase (#8891 by @hannesrudolph, PR by @app/roomote) +- Fix: custom modes under custom path not showing (#8122 by @hannesrudolph, PR by @elianiva) +- Fix: prevent MCP server restart when toggling tool permissions (#8231 by @hannesrudolph, PR by @heyseth) +- Fix: truncate type definition to match max read line (#8149 by @chenxluo, PR by @elianiva) +- Fix: auto-sync enableReasoningEffort with reasoning dropdown selection (thanks @daniel-lxs!) +- Fix: Gate auth-driven Roo model refresh to active provider only (thanks @daniel-lxs!) +- Prevent a noisy cloud agent exception (thanks @cte!) +- Feat: improve @ file search for large projects (#5721 by @Naituw, PR by @daniel-lxs) +- Feat: add zai-glm-4.6 model to Cerebras and set gpt-oss-120b as default (thanks @kevint-cerebras!) +- Feat: rename MCP Errors tab to Logs for mixed-level messages (#8893 by @hannesrudolph, PR by @app/roomote) +- docs(vscode-lm): clarify VS Code LM API integration warning (thanks @hannesrudolph!) + +## [3.29.3] - 2025-10-28 + +- Update Gemini models with latest 09-2025 versions including Gemini 2.5 Pro and Flash (#8485 by @cleacos, PR by @roomote) +- Add reasoning support for Z.ai GLM binary thinking mode (#8465 by @BeWater799, PR by @daniel-lxs) +- Enable reasoning in Roo provider (thanks @mrubens!) +- Add settings to configure time and cost display in system prompt (#8450 by @jaxnb, PR by @roomote) +- Fix: Use max_output_tokens when available in LiteLLM fetcher (#8454 by @fabb, PR by @roomote) +- Fix: Process queued messages after context condensing completes (#8477 by @JosXa, PR by @roomote) +- Fix: Use monotonic clock for rate limiting to prevent timing issues (#7770 by @intermarkec, PR by @chrarnoldus) +- Fix: Resolve checkpoint menu popover overflow (thanks @daniel-lxs!) +- Fix: LiteLLM test failures after merge (thanks @daniel-lxs!) +- Improve UX: Focus textbox and add newlines after adding to context (thanks @mrubens!) + +## [3.29.2] - 2025-10-27 + +- Add support for LongCat-Flash-Thinking-FP8 models in Chutes AI provider (#8425 by @leakless21, PR by @roomote) +- Fix: Remove specific Claude model version from settings descriptions to avoid outdated references (#8435 by @rwydaegh, PR by @roomote) +- Fix: Correct caching logic in Roo provider to improve performance (thanks @mrubens!) +- Fix: Ensure free models don't display pricing information in the UI (thanks @mrubens!) + +## [3.29.1] - 2025-10-26 + +![3.29.1 Release - Window Cleaning](/releases/3.29.1-release.png) + +- Fix: Clean up max output token calculations to prevent context window overruns (#8821 by @enerage, PR by @roomote) +- Fix: Change Add to Context keybinding to avoid Redo conflict (#8652 by @swythan, PR by @roomote) +- Fix provider model loading race conditions (thanks @mrubens!) + +## [3.29.0] - 2025-10-24 + +![3.29.0 Release - Intelligent File Reading](/releases/3.29.0-release.png) + +- Add token-budget based file reading with intelligent preview to avoid context overruns (thanks @daniel-lxs!) +- Enable browser-use tool for all image-capable models (#8116 by @hannesrudolph, PR by @app/roomote!) +- Add dynamic model loading for Roo Code Router (thanks @app/roomote!) +- Fix: Respect nested .gitignore files in search_files (#7921 by @hannesrudolph, PR by @daniel-lxs) +- Fix: Preserve trailing newlines in stripLineNumbers for apply_diff (#8020 by @liyi3c, PR by @app/roomote) +- Fix: Exclude max tokens field for models that don't support it in export (#7944 by @hannesrudolph, PR by @elianiva) +- Retry API requests on stream failures instead of aborting task (thanks @daniel-lxs!) +- Improve auto-approve button responsiveness (thanks @daniel-lxs!) +- Add checkpoint initialization timeout settings and fix checkpoint timeout warnings (#7843 by @NaccOll, PR by @NaccOll) +- Always show checkpoint restore options regardless of change detection (thanks @daniel-lxs!) +- Improve checkpoint menu translations (thanks @daniel-lxs!) +- Add GLM-4.6-turbo model to chutes ai provider (thanks @mohammad154!) +- Add Claude Haiku 4.5 to prompt caching models (thanks @hannesrudolph!) +- Expand Z.ai model coverage with GLM-4.5-X, AirX, Flash (thanks @hannesrudolph!) +- Update Mistral Medium model name (#8362 by @ThomsenDrake, PR by @ThomsenDrake) +- Remove GPT-5 instructions/reasoning_summary from UI message metadata to prevent ui_messages.json bloat (thanks @hannesrudolph!) +- Normalize docs-extractor audience tags; remove admin/stakeholder; strip tool invocations (thanks @hannesrudolph!) +- Update X/Twitter username from roo_code to roocode (thanks @app/roomote!) +- Update Configuring Profiles video link (thanks @app/roomote!) +- Fix link text for Roomote Control in README (thanks @laz-001!) +- Remove verbose error for cloud agents (thanks @cte!) +- Try 5s status mutation timeout (thanks @cte!) + +## [3.28.18] - 2025-10-17 + +- Fix: Remove request content from UI messages to improve performance and reduce clutter (#5601 by @MuriloFP, #8594 by @multivac2x, #8690 by @hannesrudolph, PR by @mrubens) +- Fix: Prevent file editing issues when git diff views are open (thanks @hassoncs!) +- Fix: Add userAgent to Bedrock client for version tracking (#8660 by @ajjuaire, PR by @app/roomote) +- Feat: Z AI now uses only two coding endpoints for better performance (#8687 by @hannesrudolph) +- Feat: Update image generation model selection for improved quality (thanks @chrarnoldus!) + +## [3.28.17] - 2025-10-15 + +- Add support for Claude Haiku 4.5 model (thanks @daniel-lxs!) +- Fix: Update zh-TW run command title translation (thanks @PeterDaveHello!) + +## [3.28.16] - 2025-10-09 + +![3.28.16 Release - Expanded Context Window](/releases/3.28.16-release.png) + +- feat: Add Claude Sonnet 4.5 1M context window support for Claude Code (thanks @ColbySerpa!) +- feat: Identify cloud tasks in the extension bridge (thanks @cte!) +- fix: Add the parent task ID in telemetry (thanks @mrubens!) + +## [3.28.15] - 2025-10-03 + +![3.28.15 Release - Kangaroo Sliding Down a Chute](/releases/3.28.15-release.png) + +- Add new DeepSeek and GLM models with detailed descriptions to the Chutes provider (thanks @mohammad154!) +- Fix: properly reset cost limit tracking when user clicks "Reset and Continue" (#6889 by @alecoot, PR by app/roomote) +- Fix: improve save button activation in prompts settings (#5780 by @beccare, PR by app/roomote) +- Fix: overeager 'there are unsaved changes' dialog in settings (thanks @brunobergher!) +- Fix: show send button when only images are selected in chat textarea (thanks app/roomote!) +- Fix: Claude Sonnet 4.5 compatibility improvements (thanks @mrubens!) +- Add UsageStats schema and type for better analytics tracking (thanks app/roomote!) +- Include reasoning messages in cloud tasks (thanks @mrubens!) +- Security: update dependency vite to v6.3.6 (thanks app/renovate!) +- Deprecate free grok 4 fast model (thanks @mrubens!) +- Remove unsupported Gemini 2.5 Flash Image Preview free model (thanks @SannidhyaSah!) +- Add structured data to the homepage for better SEO (thanks @mrubens!) +- Update dependency glob to v11.0.3 (thanks app/renovate!) + +## [3.28.14] - 2025-09-30 + +![3.28.14 Release - GLM-4.6 Model Support](/releases/3.28.14-release.png) + +- Add support for GLM-4.6 model for z.ai provider (#8406 by @dmarkey, PR by @roomote) + +## [3.28.13] - 2025-09-29 + +- Fix: Remove topP parameter from Bedrock inference config (#8377 by @ronyblum, PR by @daniel-lxs) +- Fix: Correct Vertex AI Sonnet 4.5 model configuration (#8387 by @nickcatal, PR by @mrubens!) + +## [3.28.12] - 2025-09-29 + +- Fix: Correct Anthropic Sonnet 4.5 model ID and add Bedrock 1M context checkbox (thanks @daniel-lxs!) + +## [3.28.11] - 2025-09-29 + +- Fix: Correct Amazon Bedrock Claude Sonnet 4.5 model identifier (#8371 by @sunhyung, PR by @app/roomote) +- Fix: Correct Claude Sonnet 4.5 model ID format (thanks @daniel-lxs!) + +## [3.28.10] - 2025-09-29 + +![3.28.10 Release - Kangaroo Writing Sonnet 4.5](/releases/3.28.10-release.png) + +- Feat: Add Sonnet 4.5 support (thanks @daniel-lxs!) +- Fix: Resolve max_completion_tokens issue for GPT-5 models in LiteLLM provider (#6979 by @lx1054331851, PR by @roomote) +- Fix: Make chat icons properly sized with shrink-0 class (thanks @mrubens!) +- Enhancement: Track telemetry settings changes for better analytics (thanks @mrubens!) +- Web: Add testimonials section to website (thanks @brunobergher!) +- CI: Refresh contrib.rocks cache workflow for contributor badges (thanks @hannesrudolph!) + +## [3.28.9] - 2025-09-26 + +![3.28.9 Release - Supernova Upgrade](/releases/3.28.9-release.png) + +- The free Supernova model now has a 1M token context window (thanks @mrubens!) +- Experiment to show the Roo provider on the welcome screen (thanks @mrubens!) +- Web: Website improvements to https://roocode.com/ (thanks @brunobergher!) +- Fix: Remove tags from prompts for cleaner output and fewer tokens (#8318 by @hannesrudolph, PR by @app/roomote) +- Correct tool use suggestion to improve model adherence to suggestion (thanks @hannesrudolph!) +- feat: log out from cloud when resetting extension state (thanks @app/roomote!) +- feat: Add telemetry tracking to DismissibleUpsell component (thanks @app/roomote!) +- refactor: remove pr-reviewer mode (thanks @daniel-lxs!) +- Removing user hint when refreshing models (thanks @requesty-JohnCosta27!) + +## [3.28.8] - 2025-09-25 + +![3.28.8 Release - Bug fixes and improvements](/releases/3.28.8-release.png) + +- Fix: Resolve frequent "No tool used" errors by clarifying tool-use rules (thanks @hannesrudolph!) +- Fix: Include initial ask in condense summarization (thanks @hannesrudolph!) +- Add support for more free models in the Roo provider (thanks @mrubens!) +- Show cloud switcher and option to add a team when logged in (thanks @mrubens!) +- Add Opengraph image for web (thanks @brunobergher!) + +## [3.28.7] - 2025-09-23 + +![3.28.7 Release - Hidden Thinking](/releases/3.28.7-release.png) + +- UX: Collapse thinking blocks by default with UI settings to always show them (thanks @brunobergher!) +- Fix: Resolve checkpoint restore popover positioning issue (#8219 by @NaccOll, PR by @app/roomote) +- Add cloud account switcher functionality (thanks @mrubens!) +- Add support for zai-org/GLM-4.5-turbo model in Chutes provider (#8155 by @mugnimaestra, PR by @app/roomote) + +## [3.28.6] - 2025-09-23 + +![3.28.6 Release - Kangaroo studying ancient codex](/releases/3.28.6-release.png) + +- Feat: Add GPT-5-Codex model (thanks @daniel-lxs!) +- Feat: Add keyboard shortcut for toggling auto-approve (Cmd/Ctrl+Alt+A) (thanks @brunobergher!) +- Fix: Improve reasoning block formatting for better readability (thanks @daniel-lxs!) +- Fix: Respect Ollama Modelfile num_ctx configuration (#7797 by @hannesrudolph, PR by @app/roomote) +- Fix: Prevent checkpoint text from wrapping in non-English languages (#8206 by @NaccOll, PR by @app/roomote) +- Remove language selection and word wrap toggle from CodeBlock (thanks @mrubens!) +- Feat: Add package.nls.json checking to find-missing-translations script (thanks @app/roomote!) +- Fix: Bare metal evals fixes (thanks @cte!) +- Fix: Follow-up questions should trigger the "interactive" state (thanks @cte!) + +## [3.28.5] - 2025-09-20 + +![3.28.5 Release - Kangaroo staying hydrated](/releases/3.28.5-release.png) + +- Fix: Resolve duplicate rehydrate during reasoning; centralize rehydrate and preserve cancel metadata (#8153 by @hannesrudolph, PR by @hannesrudolph) +- Add an announcement for Supernova (thanks @mrubens!) +- Wrap code blocks by default for improved readability (thanks @mrubens!) +- Fix: Support dash prefix in parseMarkdownChecklist for todo lists (#8054 by @NaccOll, PR by app/roomote) +- Fix: Apply tiered pricing for Gemini models via Vertex AI (#8017 by @ikumi3, PR by app/roomote) +- Update SambaNova models to latest versions (thanks @snova-jorgep!) +- Update privacy policy to allow occasional emails (thanks @jdilla1277!) + +## [3.28.4] - 2025-09-19 + +![3.28.4 Release - Supernova Discovery](/releases/3.28.4-release.png) + +- UX: Redesigned Message Feed (thanks @brunobergher!) +- UX: Responsive Auto-Approve (thanks @brunobergher!) +- Add telemetry retry queue for network resilience (thanks @daniel-lxs!) +- Fix: Transform keybindings in nightly build to fix command+y shortcut (thanks @app/roomote!) +- New code-supernova stealth model in the Roo Code Router (thanks @mrubens!) + +## [3.28.3] - 2025-09-16 + +![3.28.3 Release - UI/UX Improvements and Bug Fixes](/releases/3.28.3-release.png) + +- Fix: Filter out Claude Code built-in tools (ExitPlanMode, BashOutput, KillBash) (#7817 by @juliettefournier-econ, PR by @roomote) +- Replace + icon with edit icon for New Task button (#7941 by @hannesrudolph, PR by @roomote) +- Fix: Corrected C# tree-sitter query (#5238 by @vadash, PR by @mubeen-zulfiqar) +- Add keyboard shortcut for "Add to Context" action (#7907 by @hannesrudolph, PR by @roomote) +- Fix: Context menu is obscured when edit message (#7759 by @mini2s, PR by @NaccOll) +- Fix: Handle ByteString conversion errors in OpenAI embedders (#7959 by @PavelA85, PR by @daniel-lxs) +- Add Z.ai coding plan support (thanks @daniel-lxs!) +- Move slash commands to Settings tab with gear icon for discoverability (thanks @roomote!) +- Reposition Add Image button inside ChatTextArea (thanks @roomote!) +- Bring back a way to temporarily and globally pause auto-approve without losing your toggle state (thanks @brunobergher!) +- Makes text area buttons appear only when there's text (thanks @brunobergher!) +- CONTRIBUTING.md tweaks and issue template rewrite (thanks @hannesrudolph!) +- Bump axios from 1.9.0 to 1.12.0 (thanks @dependabot!) + +## [3.28.2] - 2025-09-14 + +![3.28.2 Release - Auto-approve improvements](/releases/3.28.2-release.png) + +- Improve auto-approve UI with smaller and more subtle design (thanks @brunobergher!) +- Fix: Message queue re-queue loop in Task.ask() causing performance issues (#7861 by @hannesrudolph, PR by @daniel-lxs) +- Fix: Restrict @-mention parsing to line-start or whitespace boundaries to prevent false triggers (#7875 by @hannesrudolph, PR by @app/roomote) +- Fix: Make nested git repository warning persistent with path info for better visibility (#7884 by @hannesrudolph, PR by @app/roomote) +- Fix: Include API key in Ollama /api/tags requests for authenticated instances (#7902 by @ItsOnlyBinary, PR by @app/roomote) +- Fix: Preserve original first message context during conversation condensing (thanks @daniel-lxs!) +- Add Qwen3 Next 80B A3B models to chutes provider (thanks @daniel-lxs!) +- Disable Roomote Control on logout for better security (thanks @cte!) +- Add padding to the cloudview for better visual spacing (thanks @mrubens!) + +## [3.28.1] - 2025-09-11 + +![3.28.1 Release - Kangaroo riding rocket to the clouds](/releases/3.28.1-release.png) + +- Announce Roo Code Cloud! +- Add cloud task button for opening tasks in Roo Code Cloud (thanks @app/roomote!) +- Make Posthog telemetry the default (thanks @mrubens!) +- Show notification when the checkpoint initialization fails (thanks @app/roomote!) +- Bust cache in generated image preview (thanks @mrubens!) +- Fix: Center active mode in selector dropdown on open (#7882 by @hannesrudolph, PR by @app/roomote) +- Fix: Preserve first message during conversation condensing (thanks @daniel-lxs!) + +## [3.28.0] - 2025-09-10 + +![3.28.0 Release - Continue tasks in Roo Code Cloud](/releases/3.28.0-release.png) + +- feat: Continue tasks in Roo Code Cloud (thanks @brunobergher!) +- feat: Support connecting to Cloud without redirect handling (thanks @mrubens!) +- feat: Add toggle to control task syncing to Cloud (thanks @jr!) +- feat: Add click-to-edit, ESC-to-cancel, and fix padding consistency for chat messages (#7788 by @hannesrudolph, PR by @app/roomote) +- feat: Make reasoning more visible (thanks @app/roomote!) +- fix: Fix Groq context window display (thanks @mrubens!) +- fix: Add GIT_EDITOR env var to merge-resolver mode for non-interactive rebase (thanks @daniel-lxs!) +- fix: Resolve chat message edit/delete duplication issues (thanks @daniel-lxs!) +- fix: Reduce CodeBlock button z-index to prevent overlap with popovers (#7703 by @A0nameless0man, PR by @daniel-lxs) +- fix: Revert PR #7188 - Restore temperature parameter to fix TabbyApi/ExLlamaV2 crashes (#7581 by @drknyt, PR by @daniel-lxs) +- fix: Make ollama models info transport work like lmstudio (#7674 by @ItsOnlyBinary, PR by @ItsOnlyBinary) +- fix: Update DeepSeek pricing to new unified rates effective Sept 5, 2025 (#7685 by @NaccOll, PR by @app/roomote) +- feat: Update Vertex AI models and regions (#7725 by @ssweens, PR by @ssweens) +- chore: Update dependency eslint-plugin-turbo to v2.5.6 (thanks @app/renovate!) +- chore: Update dependency @changesets/cli to v2.29.6 (thanks @app/renovate!) +- chore: Update dependency nock to v14.0.10 (thanks @app/renovate!) +- chore: Update dependency eslint-config-prettier to v10.1.8 (thanks @app/renovate!) +- chore: Update dependency esbuild to v0.25.9 (thanks @app/renovate!) + +## [3.27.0] - 2025-09-05 + +![3.27.0 Release - Bug Fixes and Improvements](/releases/3.27.0-release.png) + +- Add: User message editing and deletion functionality (thanks @NaccOll!) +- Add: Kimi K2-0905 model support in Chutes provider (#7700 by @pwilkin, PR by @app/roomote) +- Fix: Prevent stack overflow in codebase indexing for large projects (#7588 by @StarTrai1, PR by @daniel-lxs) +- Fix: Resolve race condition in Gemini Grounding Sources by improving code design (#6372 by @daniel-lxs, PR by @HahaBill) +- Fix: Preserve conversation context by retrying with full conversation on invalid previous_response_id (thanks @daniel-lxs!) +- Fix: Identify MCP and slash command config path in multiple folder workspaces (#6720 by @kfuglsang, PR by @NaccOll) +- Fix: Handle array paths from VSCode terminal profiles correctly (#7695 by @Amosvcc, PR by @app/roomote) +- Fix: Improve WelcomeView styling and readability (thanks @daniel-lxs!) +- Fix: Resolve CI e2e test ETIMEDOUT errors when downloading VS Code (thanks @daniel-lxs!) + +## [3.26.7] - 2025-09-04 + +![3.26.7 Release - OpenAI Service Tiers](/releases/3.26.7-release.png) + +- Feature: Add OpenAI Responses API service tiers (flex/priority) with UI selector and pricing (thanks @hannesrudolph!) +- Feature: Add DeepInfra as a model provider in Roo Code (#7661 by @Thachnh, PR by @Thachnh) +- Feature: Update kimi-k2-0905-preview and kimi-k2-turbo-preview models on the Moonshot provider (thanks @CellenLee!) +- Feature: Add kimi-k2-0905-preview to Groq, Moonshot, and Fireworks (thanks @daniel-lxs and Cline!) +- Fix: Prevent countdown timer from showing in history for answered follow-up questions (#7624 by @XuyiK, PR by @daniel-lxs) +- Fix: Moonshot's maximum return token count limited to 1024 issue resolved (#6936 by @greyishsong, PR by @wangxiaolong100) +- Fix: Add error transform to cryptic OpenAI SDK errors when API key is invalid (#7483 by @A0nameless0man, PR by @app/roomote) +- Fix: Validate MCP tool exists before execution (#7631 by @R-omk, PR by @app/roomote) +- Fix: Handle zsh glob qualifiers correctly (thanks @mrubens!) +- Fix: Handle zsh process substitution correctly (thanks @mrubens!) +- Fix: Minor zh-TW Traditional Chinese locale typo fix (thanks @PeterDaveHello!) + +## [3.26.6] - 2025-09-03 + +![3.26.6 Release - Bug Fixes and Tool Improvements](/releases/3.26.6-release.png) + +- Add experimental run_slash_command tool to let the model initiate slash commands (thanks @app/roomote!) +- Fix: use askApproval wrapper in insert_content and search_and_replace tools (#7648 by @hannesrudolph, PR by @app/roomote) +- Add Kimi K2 Turbo model configuration to moonshotModels (thanks @wangxiaolong100!) +- Fix: preserve scroll position when switching tabs in settings (thanks @DC-Dancao!) + +## [3.26.5] - 2025-09-03 + +![3.26.5 Release - Enhanced AI Thinking Capabilities](/releases/3.26.5-release.png) + +- feat: Add support for Qwen3 235B A22B Thinking 2507 model in chutes (thanks @mohammad154!) +- feat: Add auto-approve support for MCP access_resource tool (#7565 by @m-ibm, PR by @daniel-lxs) +- feat: Add configurable embedding batch size for code indexing (#7356 by @BenLampson, PR by @app/roomote) +- fix: Add cache reporting support for OpenAI-Native provider (thanks @hannesrudolph!) +- feat: Move message queue to the extension host for better performance (thanks @cte!) + +## [3.26.4] - 2025-09-01 + +![3.26.4 Release - Memory Optimization](/releases/3.26.4-release.png) + +- Optimize memory usage for image handling in webview (thanks @daniel-lxs!) +- Fix: Special tokens should not break task processing (#7539 by @pwilkin, PR by @pwilkin) +- Add Ollama API key support for Turbo mode (#7147 by @LivioGama, PR by @app/roomote) +- Rename Account tab to Cloud tab for clarity (thanks @app/roomote!) +- Add kangaroo-themed release image generation (thanks @mrubens!) + +## [3.26.3] - 2025-08-29 + +![3.26.3 Release - Kangaroo Photo Editor](/releases/3.26.3-release.png) + +- Add optional input image parameter to image generation tool (thanks @roomote!) +- Refactor: Flatten image generation settings structure (thanks @daniel-lxs!) +- Show console logging in vitests when the --no-silent flag is set (thanks @hassoncs!) + +## [3.26.2] - 2025-08-28 + +![3.26.2 Release - Kangaroo Digital Artist](/releases/3.26.2-release.png) + +- feat: Add experimental image generation tool with OpenRouter integration (thanks @daniel-lxs!) +- Fix: Resolve GPT-5 Responses API issues with condensing and image support (#7334 by @nlbuescher, PR by @daniel-lxs) +- Fix: Hide .rooignore'd files from environment details by default (#7368 by @AlexBlack772, PR by @app/roomote) +- Fix: Exclude browser scroll actions from repetition detection (#7470 by @cgrierson-smartsheet, PR by @app/roomote) + +## [3.26.1] - 2025-08-27 + +![3.26.1 Release - Kangaroo Network Engineer](/releases/3.26.1-release.png) + +- Add Vercel AI Gateway provider integration (thanks @joshualipman123!) +- Add support for Vercel embeddings (thanks @mrubens!) +- Enable on-disk storage for Qdrant vectors and HNSW index (thanks @daniel-lxs!) +- Show model ID in API configuration dropdown (thanks @daniel-lxs!) +- Update tooltip component to match native VSCode tooltip shadow styling (thanks @roomote!) +- Fix: remove duplicate cache display in task header (thanks @mrubens!) +- Random chat text area cleanup (thanks @cte!) + +## [3.26.0] - 2025-08-26 + +![3.26.0 Release - Kangaroo Speed Racer](/releases/3.26.0-release.png) + +- Sonic -> Grok Code Fast +- feat: Add Qwen Code CLI API Support with OAuth Authentication (thanks @evinelias and Cline!) +- feat: Add Deepseek v3.1 to Fireworks AI provider (#7374 by @dmarkey, PR by @app/roomote) +- Add a built-in /init slash command (thanks @mrubens and @hannesrudolph!) +- Fix: Make auto approve toggle trigger stay (#3909 by @kyle-apex, PR by @elianiva) +- Fix: Preserve user input when selecting follow-up choices (#7316 by @teihome, PR by @daniel-lxs) +- Fix: Handle Mistral thinking content as reasoning chunks (#6842 by @Biotrioo, PR by @app/roomote) +- Fix: Resolve newTaskRequireTodos setting not working correctly (thanks @hannesrudolph!) +- Fix: Requesty model listing (#7377 by @dtrugman, PR by @dtrugman) +- feat: Hide static providers with no models from provider list (thanks @daniel-lxs!) +- Add todos parameter to new_task tool usage in issue-fixer mode (thanks @hannesrudolph!) +- Handle substitution patterns in command validation (thanks @mrubens!) +- Mark code-workspace files as protected (thanks @mrubens!) +- Update list of default allowed commands (thanks @mrubens!) +- Follow symlinks in rooignore checks (thanks @mrubens!) +- Show cache read and write prices for OpenRouter inference providers (thanks @chrarnoldus!) +- chore(deps): Update dependency drizzle-kit to v0.31.4 (thanks @app/renovate!) + +## [3.25.23] - 2025-08-22 + +- feat: add custom base URL support for Requesty provider (thanks @requesty-JohnCosta27!) +- feat: add DeepSeek V3.1 model to Chutes AI provider (#7294 by @dmarkey, PR by @app/roomote) +- Revert "feat: enable loading Roo modes from multiple files in .roo/modes directory" temporarily to fix a bug with mode installation + +## [3.25.22] - 2025-08-22 + +- Add prompt caching support for Kimi K2 on Groq (thanks @daniel-lxs and @benank!) +- Add documentation links for global custom instructions in UI (thanks @app/roomote!) + +## [3.25.21] - 2025-08-21 + +- Ensure subtask results are provided to GPT-5 in OpenAI Responses API +- Promote the experimental AssistantMessageParser to the default parser +- Update DeepSeek models context window to 128k (thanks @JuanPerezReal) +- Enable grounding features for Vertex AI (thanks @anguslees) +- Allow orchestrator to pass TODO lists to subtasks +- Improved MDM handling +- Handle nullish token values in ContextCondenseRow to prevent UI crash (thanks @s97712) +- Improved context window error handling for OpenAI and other providers +- Add "installed" filter to Roo Marketplace (thanks @semidark) +- Improve filesystem access checks (thanks @elianiva) +- Support for loading Roo modes from multiple YAML files in the `.roo/modes/` directory (thanks @farazoman) +- Add Featherless provider (thanks @DarinVerheijke) + +## [3.25.20] - 2025-08-19 + +- Add announcement for Sonic model + +## [3.25.19] - 2025-08-19 + +- Fix issue where new users couldn't select the Roo Code Router (thanks @daniel-lxs!) + +## [3.25.18] - 2025-08-19 + +- Add new stealth Sonic model through the Roo Code Router +- Fix: respect enableReasoningEffort setting when determining reasoning usage (#7048 by @ikbencasdoei, PR by @app/roomote) +- Fix: prevent duplicate LM Studio models with case-insensitive deduplication (#6954 by @fbuechler, PR by @daniel-lxs) +- Feat: simplify ask_followup_question prompt documentation (thanks @daniel-lxs!) +- Feat: simple read_file tool for single-file-only models (thanks @daniel-lxs!) +- Fix: Add missing zaiApiKey and doubaoApiKey to SECRET_STATE_KEYS (#7082 by @app/roomote) +- Feat: Add new models and update configurations for vscode-lm (thanks @NaccOll!) + +## [3.25.17] - 2025-08-17 + +- Fix: Resolve terminal reuse logic issues + +## [3.25.16] - 2025-08-16 + +- Add support for OpenAI gpt-5-chat-latest model (#7057 by @PeterDaveHello, PR by @app/roomote) +- Fix: Use native Ollama API instead of OpenAI compatibility layer (#7070 by @LivioGama, PR by @daniel-lxs) +- Fix: Prevent XML entity decoding in diff tools (#7107 by @indiesewell, PR by @app/roomote) +- Fix: Add type check before calling .match() on diffItem.content (#6905 by @pwilkin, PR by @app/roomote) +- Refactor task execution system: improve call stack management (thanks @catrielmuller!) +- Fix: Enable save button for provider dropdown and checkbox changes (thanks @daniel-lxs!) +- Add an API for resuming tasks by ID (thanks @mrubens!) +- Emit event when a task ask requires interaction (thanks @cte!) +- Make enhance with task history default to true (thanks @liwilliam2021!) +- Fix: Use cline.cwd as primary source for workspace path in codebaseSearchTool (thanks @NaccOll!) +- Hotfix multiple folder workspace checkpoint (thanks @NaccOll!) + +## [3.25.15] - 2025-08-14 + +- Fix: Remove 500-message limit to prevent scrollbar jumping in long conversations (#7052, #7063 by @daniel-lxs, PR by @app/roomote) +- Fix: Reset condensing state when switching tasks (#6919 by @f14XuanLv, PR by @f14XuanLv) +- Fix: Implement sitemap generation in TypeScript and remove XML file (#5231 by @abumalick, PR by @abumalick) +- Fix: allowedMaxRequests and allowedMaxCost values not showing in the settings UI (thanks @chrarnoldus!) + +## [3.25.14] - 2025-08-13 + +- Fix: Only include verbosity parameter for models that support it (#7054 by @eastonmeth, PR by @app/roomote) +- Fix: Amazon Bedrock 1M context - Move anthropic_beta to additionalModelRequestFields (thanks @daniel-lxs!) +- Fix: Make cancelling requests more responsive by reverting recent changes + +## [3.25.13] - 2025-08-12 + +- Add Sonnet 1M context checkbox to Bedrock +- Fix: add --no-messages flag to ripgrep to suppress file access errors (#6756 by @R-omk, PR by @app/roomote) +- Add support for AGENT.md alongside AGENTS.md (#6912 by @Brendan-Z, PR by @app/roomote) +- Remove deprecated GPT-4.5 Preview model (thanks @PeterDaveHello!) + +## [3.25.12] - 2025-08-12 + +- Update: Claude Sonnet 4 context window configurable to 1 million tokens in Anthropic provider (thanks @daniel-lxs!) +- Add: Minimal reasoning support to OpenRouter (thanks @daniel-lxs!) +- Fix: Add configurable API request timeout for local providers (#6521 by @dabockster, PR by @app/roomote) +- Fix: Add --no-sandbox flag to browser launch options (#6632 by @QuinsZouls, PR by @QuinsZouls) +- Fix: Ensure JSON files respect .rooignore during indexing (#6690 by @evermoving, PR by @app/roomote) +- Add: New Chutes provider models (#6698 by @fstandhartinger, PR by @app/roomote) +- Add: OpenAI gpt-oss models to Amazon Bedrock dropdown (#6752 by @josh-clanton-powerschool, PR by @app/roomote) +- Fix: Correct tool repetition detector to not block first tool call when limit is 1 (#6834 by @NaccOll, PR by @app/roomote) +- Fix: Improve checkpoint service initialization handling (thanks @NaccOll!) +- Update: Improve zh-TW Traditional Chinese locale (thanks @PeterDaveHello!) +- Add: Task expand and collapse translations (thanks @app/roomote!) +- Update: Exclude GPT-5 models from 20% context window output token cap (thanks @app/roomote!) +- Fix: Truncate long model names in model selector to prevent overflow (thanks @app/roomote!) +- Add: Requesty base url support (thanks @requesty-JohnCosta27!) + +## [3.25.11] - 2025-08-11 + +- Add: Native OpenAI provider support for Codex Mini model (#5386 by @KJ7LNW, PR by @daniel-lxs) +- Add: IO Intelligence Provider support (thanks @ertan2002!) +- Fix: MCP startup issues and remove refresh notifications (thanks @hannesrudolph!) +- Fix: Improvements to GPT-5 OpenAI provider configuration (thanks @hannesrudolph!) +- Fix: Clarify codebase_search path parameter as optional and improve tool descriptions (thanks @app/roomote!) +- Fix: Bedrock provider workaround for LiteLLM passthrough issues (thanks @jr!) +- Fix: Token usage and cost being underreported on cancelled requests (thanks @chrarnoldus!) + +## [3.25.10] - 2025-08-07 + +- Add support for GPT-5 (thanks Cline and @app/roomote!) +- Fix: Use CDATA sections in XML examples to prevent parser errors (#4852 by @hannesrudolph, PR by @hannesrudolph) +- Fix: Add missing MCP error translation keys (thanks @app/roomote!) + +## [3.25.9] - 2025-08-07 + +- Fix: Resolve rounding issue with max tokens (#6806 by @markp018, PR by @mrubens) +- Add support for GLM-4.5 and OpenAI gpt-oss models in Fireworks provider (#6753 by @alexfarlander, PR by @app/roomote) +- Improve UX by focusing chat input when clicking plus button in extension menu (thanks @app/roomote!) + +## [3.25.8] - 2025-08-06 + +- Fix: Prevent disabled MCP servers from starting processes and show correct status (#6036 by @hannesrudolph, PR by @app/roomote) +- Fix: Handle current directory path "." correctly in codebase_search tool (#6514 by @hannesrudolph, PR by @app/roomote) +- Fix: Trim whitespace from OpenAI base URL to fix model detection (#6559 by @vauhochzett, PR by @app/roomote) +- Feat: Reduce Gemini 2.5 Pro minimum thinking budget to 128 (thanks @app/roomote!) +- Fix: Improve handling of net::ERR_ABORTED errors in URL fetching (#6632 by @QuinsZouls, PR by @app/roomote) +- Fix: Recover from error state when Qdrant becomes available (#6660 by @hannesrudolph, PR by @app/roomote) +- Fix: Resolve memory leak in ChatView virtual scrolling implementation (thanks @xyOz-dev!) +- Add: Swift files to fallback list (#5857 by @niteshbalusu11, #6555 by @sealad886, PR by @niteshbalusu11) +- Feat: Clamp default model max tokens to 20% of context window (thanks @mrubens!) + +## [3.25.7] - 2025-08-05 + +- Add support for Claude Opus 4.1 +- Add Fireworks AI provider (#6653 by @ershang-fireworks, PR by @ershang-fireworks) +- Add Z AI provider (thanks @jues!) +- Add Groq support for GPT-OSS +- Add Cerebras support for GPT-OSS +- Add code indexing support for multiple folders similar to task history (#6197 by @NaccOll, PR by @NaccOll) +- Make mode selection dropdowns responsive (#6423 by @AyazKaan, PR by @AyazKaan) +- Redesigned task header and task history (thanks @brunobergher!) +- Fix checkpoints timing and ensure checkpoints work properly (#4827 by @mrubens, PR by @NaccOll) +- Fix empty mode names from being saved (#5766 by @kfxmvp, PR by @app/roomote) +- Fix MCP server creation when setting is disabled (#6607 by @characharm, PR by @app/roomote) +- Update highlight layer style and align to textarea (#6647 by @NaccOll, PR by @NaccOll) +- Fix UI for approving chained commands +- Use assistantMessageParser class instead of parseAssistantMessage (#5340 by @qdaxb, PR by @qdaxb) +- Conditionally include reminder section based on todo list config (thanks @NaccOll!) +- Task and TaskProvider event emitter cleanup with new events (thanks @cte!) + +## [3.25.6] - 2025-08-01 + +- Set horizon-beta model max tokens to 32k for OpenRouter (requested by @hannesrudolph, PR by @app/roomote) +- Add support for syncing provider profiles from the cloud + +## [3.25.5] - 2025-08-01 + +- Fix: Improve Claude Code ENOENT error handling with installation guidance (#5866 by @JamieJ1, PR by @app/roomote) +- Fix: LM Studio model context length (#5075 by @Angular-Angel, PR by @pwilkin) +- Fix: VB.NET indexing by implementing fallback chunking system (#6420 by @JensvanZutphen, PR by @daniel-lxs) +- Add auto-approved cost limits (thanks @hassoncs!) +- Add Cerebras as a provider (thanks @kevint-cerebras!) +- Add Qwen 3 Coder from Cerebras (thanks @kevint-cerebras!) +- Fix: Handle Qdrant deletion errors gracefully to prevent indexing interruption (thanks @daniel-lxs!) +- Fix: Restore message sending when clicking save button (thanks @daniel-lxs!) +- Fix: Linter not applied to locales/\*/README.md (thanks @liwilliam2021!) +- Handle more variations of chaining and subshell command validation +- More tolerant search/replace match +- Clean up the auto-approve UI (thanks @mrubens!) +- Skip interpolation for non-existent slash commands (thanks @app/roomote!) + +## [3.25.4] - 2025-07-30 + +- feat: add SambaNova provider integration (#6077 by @snova-jorgep, PR by @snova-jorgep) +- feat: add Doubao provider integration (thanks @AntiMoron!) +- feat: set horizon-alpha model max tokens to 32k for OpenRouter (thanks @app/roomote!) +- feat: add zai-org/GLM-4.5-FP8 model to Chutes AI provider (#6440 by @leakless21, PR by @app/roomote) +- feat: add symlink support for AGENTS.md file loading (thanks @app/roomote!) +- feat: optionally add task history context to prompt enhancement (thanks @liwilliam2021!) +- fix: remove misleading task resumption message (#5850 by @KJ7LNW, PR by @KJ7LNW) +- feat: add pattern to support Databricks /invocations endpoints (thanks @adambrand!) +- fix: resolve navigator global error by updating mammoth and bluebird dependencies (#6356 by @hishtadlut, PR by @app/roomote) +- feat: enhance token counting by extracting text from messages using VSCode LM API (#6112 by @sebinseban, PR by @NaccOll) +- feat: auto-refresh marketplace data when organization settings change (thanks @app/roomote!) +- fix: kill button for execute_command tool (thanks @daniel-lxs!) + +## [3.25.3] - 2025-07-30 + +- Allow queueing messages with images +- Increase Claude Code default max output tokens to 16k (#6125 by @bpeterson1991, PR by @app/roomote) +- Add docs link for slash commands +- Hide Gemini checkboxes on the welcome view +- Clarify apply_diff tool descriptions to emphasize surgical edits +- Fix: Prevent input clearing when clicking chat buttons (thanks @hassoncs!) +- Update PR reviewer rules and mode configuration (thanks @daniel-lxs!) +- Add translation check action to pull_request.opened event (thanks @app/roomote!) +- Remove "(prev Roo Cline)" from extension title in all languages (thanks @app/roomote!) +- Remove event types mention from PR reviewer rules (thanks @daniel-lxs!) + +## [3.25.2] - 2025-07-29 + +- Fix: Show diff view before approval when background edits are disabled (thanks @daniel-lxs!) +- Add support for organization-level MCP controls +- Fix zap icon hover state + +## [3.25.1] - 2025-07-29 + +- Add support for GLM-4.5-Air model to Chutes AI provider (#6376 by @matbgn, PR by @app/roomote) +- Improve subshell validation for commands + +## [3.25.0] - 2025-07-29 + +- Add message queueing (thanks @app/roomote!) +- Add custom slash commands +- Add options for URL Context and Grounding with Google Search to the Gemini provider (thanks @HahaBill!) +- Add image support to read_file tool (thanks @samhvw8!) +- Add experimental setting to prevent editor focus disruption (#4784 by @hannesrudolph, PR by @app/roomote) +- Add prompt caching support for LiteLLM (#5791 by @steve-gore-snapdocs, PR by @MuriloFP) +- Add markdown table rendering support +- Fix list_files recursive mode now works for dot directories (#2992 by @avtc, #4807 by @zhang157686, #5409 by @MuriloFP, PR by @MuriloFP) +- Add search functionality to mode selector popup and reorganize layout +- Sync API config selector style with mode selector +- Fix keyboard shortcuts for non-QWERTY layouts (#6161 by @shlgug, PR by @app/roomote) +- Add ESC key handling for modes, API provider, and indexing settings popovers (thanks @app/roomote!) +- Make task mode sticky to task (thanks @app/roomote!) +- Add text wrapping to command patterns in Manage Command Permissions (thanks @app/roomote!) +- Update list-files test for fixed hidden files bug (thanks @daniel-lxs!) +- Fix normalize Windows paths to forward slashes in mode export (#6307 by @hannesrudolph, PR by @app/roomote) +- Ensure form-data >= 4.0.4 +- Fix filter out non-text tab inputs (Kilo-Org/kilocode#712 by @szermatt, PR by @hassoncs) + +## [3.24.0] - 2025-07-25 + +- Add Hugging Face provider with support for open source models (thanks @TGlide!) +- Add terminal command permissions UI to chat interface +- Add support for Agent Rules standard via AGENTS.md (thanks @sgryphon!) +- Add settings to control diagnostic messages +- Fix auto-approve checkbox to be toggled at any time (thanks @KJ7LNW!) +- Add efficiency warning for single SEARCH/REPLACE blocks in apply_diff (thanks @KJ7LNW!) +- Fix respect maxReadFileLine setting for file mentions to prevent context exhaustion (thanks @sebinseban!) +- Fix Ollama API URL normalization by removing trailing slashes (thanks @Naam!) +- Fix restore list styles for markdown lists in chat interface (thanks @village-way!) +- Add support for bedrock api keys +- Add confirmation dialog and proper cleanup for marketplace mode removal +- Fix cancel auto-approve timer when editing follow-up suggestion (thanks @hassoncs!) +- Fix add error message when no workspace folder is open for code indexing + +## [3.23.19] - 2025-07-23 + +- Add Roo Code Cloud Waitlist CTAs (thanks @brunobergher!) +- Split commands on newlines when evaluating auto-approve +- Smarter auto-deny of commands + +## [3.23.18] - 2025-07-23 + +- Fix: Resolve 'Bad substitution' error in command parsing (#5978 by @KJ7LNW, PR by @daniel-lxs) +- Fix: Add ErrorBoundary component for better error handling (#5731 by @elianiva, PR by @KJ7LNW) +- Fix: Todo list toggle not working (thanks @chrarnoldus!) +- Improve: Use SIGKILL for command execution timeouts in the "execa" variant (thanks @cte!) + +## [3.23.17] - 2025-07-22 + +- Add: todo list tool enable checkbox to provider advanced settings +- Add: Moonshot provider (thanks @CellenLee!) +- Add: Qwen/Qwen3-235B-A22B-Instruct-2507 model to Chutes AI provider +- Fix: move context condensing prompt to Prompts section (thanks @SannidhyaSah!) +- Add: jump icon for newly created files +- Fix: add character limit to prevent terminal output context explosion +- Fix: resolve global mode export not including rules files +- Fix: enable export, share, and copy buttons during API operations (thanks @MuriloFP!) +- Add: configurable timeout for evals (5-10 min) +- Add: auto-omit MCP content when no servers are configured +- Fix: sort symlinked rules files by symlink names, not target names +- Docs: clarify when to use update_todo_list tool +- Add: Mistral embedding provider (thanks @SannidhyaSah!) +- Fix: add run parameter to vitest command in rules (thanks @KJ7LNW!) +- Update: the max_tokens fallback logic in the sliding window +- Fix: Bedrock and Vertex token counting improvements (thanks @daniel-lxs!) +- Add: llama-4-maverick model to Vertex AI provider (thanks @MuriloFP!) +- Fix: properly distinguish between user cancellations and API failures +- Fix: add case sensitivity mention to suggested fixes in apply_diff error message + +## [3.23.16] - 2025-07-19 + +- Add global rate limiting for OpenAI-compatible embeddings (thanks @daniel-lxs!) +- Add batch limiting to code indexer (thanks @daniel-lxs!) +- Fix Docker port conflicts for evals services + +## [3.23.15] - 2025-07-18 + +- Fix configurable delay for diagnostics to prevent premature error reporting +- Add command timeout allowlist +- Add description and whenToUse fields to custom modes in .roomodes (thanks @RandalSchwartz!) +- Fix Claude model detection by name for API protocol selection (thanks @daniel-lxs!) +- Move marketplace icon from overflow menu to top navigation +- Optional setting to prevent completion with open todos +- Added YouTube to website footer (thanks @thill2323!) + +## [3.23.14] - 2025-07-17 + +- Log api-initiated tasks to a tmp directory + +## [3.23.13] - 2025-07-17 + +- Add the ability to "undo" enhance prompt changes +- Fix a bug where the path component of the baseURL for the LiteLLM provider contains path in it (thanks @ChuKhaLi) +- Add support for Vertex AI model name formatting when using Claude Code with Vertex AI (thanks @janaki-sasidhar) +- The list-files tool must include at least the first-level directory contents (thanks @qdaxb) +- Add a configurable limit that controls both consecutive errors and tool repetitions (thanks @MuriloFP) +- Add `.terraform/` and `.terragrunt-cache/` directories to the checkpoint exclusion patterns (thanks @MuriloFP) +- Increase Ollama API timeout values (thanks @daniel-lxs) +- Fix an issue where you need to "discard changes" before saving even though there are no settings changes +- Fix `DirectoryScanner` memory leak and improve file limit handling (thanks @daniel-lxs) +- Fix time formatting in environment (thanks @chrarnoldus) +- Prevent empty mode names from being saved (thanks @daniel-lxs) +- Improve auto-approve checkbox UX +- Improve the chat message edit / delete functionality (thanks @liwilliam2021) +- Add `commandExecutionTimeout` to `GlobalSettings` + +## [3.23.12] - 2025-07-15 + +- Update the max-token calculation in model-params to better support Kimi K2 and others + +## [3.23.11] - 2025-07-14 + +- Add Kimi K2 model to Groq along with fixes to context condensing math +- Add Cmd+Shift+. keyboard shortcut for previous mode switching + +## [3.23.10] - 2025-07-14 + +- Prioritize built-in model dimensions over custom dimensions (thanks @daniel-lxs!) +- Add padding to the index model options + +## [3.23.9] - 2025-07-14 + +- Enable Claude Code provider to run natively on Windows (thanks @SannidhyaSah!) +- Add gemini-embedding-001 model to code-index service (thanks @daniel-lxs!) +- Resolve vector dimension mismatch error when switching embedding models +- Return the cwd in the exec tool's response so that the model is not lost after subsequent calls (thanks @chris-garrett!) +- Add configurable timeout for command execution in VS Code settings + +## [3.23.8] - 2025-07-13 + +- Add enable/disable toggle for code indexing (thanks @daniel-lxs!) +- Add a command auto-deny list to auto-approve settings +- Add navigation link to history tab in HistoryPreview + +## [3.23.7] - 2025-07-11 + +- Fix Mermaid syntax warning (thanks @MuriloFP!) +- Expand Vertex AI region config to include all available regions in GCP Vertex AI (thanks @shubhamgupta731!) +- Handle Qdrant vector dimension mismatch when switching embedding models (thanks @daniel-lxs!) +- Fix typos in comment & document (thanks @noritaka1166!) +- Improve the display of codebase search results +- Correct translation fallback logic for embedding errors (thanks @daniel-lxs!) +- Clean up MCP tool disabling +- Link to marketplace from modes and MCP tab +- Fix TTS button display (thanks @sensei-woo!) +- Add Devstral Medium model support +- Add comprehensive error telemetry to code-index service (thanks @daniel-lxs!) +- Exclude cache tokens from context window calculation (thanks @daniel-lxs!) +- Enable dynamic tool selection in architect mode for context discovery +- Add configurable max output tokens setting for claude-code + +## [3.23.6] - 2025-07-10 + +- Grok 4 + +## [3.23.5] - 2025-07-09 + +- Fix: use decodeURIComponent in openFile (thanks @vivekfyi!) +- Fix(embeddings): Translate error messages before sending to UI (thanks @daniel-lxs!) +- Make account tab visible + +## [3.23.4] - 2025-07-09 + +- Update chat area icons for better discoverability & consistency +- Fix a bug that allowed `list_files` to return directory results that should be excluded by .gitignore +- Add an overflow header menu to make the UI a little tidier (thanks @dlab-anton) +- Fix a bug the issue where null custom modes configuration files cause a 'Cannot read properties of null' error (thanks @daniel-lxs!) +- Replace native title attributes with StandardTooltip component for consistency (thanks @daniel-lxs!) + +## [3.23.3] - 2025-07-09 + +- Remove erroneous line from announcement modal + +## [3.23.2] - 2025-07-09 + +- Fix bug where auto-approval was intermittently failing + +## [3.23.1] - 2025-07-09 + +- Always show the code indexing dot under the chat text area + +## [3.23.0] - 2025-07-08 + +- Move codebase indexing out of experimental (thanks @daniel-lxs and @MuriloFP!) +- Add todo list tool (thanks @qdaxb!) +- Fix code index secret persistence and improve settings UX (thanks @daniel-lxs!) +- Add Gemini embedding provider for codebase indexing (thanks @SannidhyaSah!) +- Support full endpoint URLs in OpenAI Compatible provider (thanks @SannidhyaSah!) +- Add markdown support to codebase indexing (thanks @MuriloFP!) +- Add Search/Filter Functionality to API Provider Selection in Settings (thanks @GOODBOY008!) +- Add configurable max search results (thanks @MuriloFP!) +- Add copy prompt button to task actions (thanks @Juice10 and @vultrnerd!) +- Fix insertContentTool to create new files with content (thanks @Ruakij!) +- Fix typescript compiler watch path inconsistency (thanks @bbenshalom!) +- Use actual max_completion_tokens from OpenRouter API (thanks @shariqriazz!) +- Prevent completion sound from replaying when reopening completed tasks (thanks @SannidhyaSah!) +- Fix access_mcp_resource fails to handle images correctly (thanks @s97712!) +- Prevent chatbox focus loss during automated file editing (thanks @hannesrudolph!) +- Resolve intermittent hangs and lack of clear error feedback in apply_diff tool (thanks @lhish!) +- Resolve Go duplicate references in tree-sitter queries (thanks @MuriloFP!) +- Chat UI consistency and layout shifts (thanks @seedlord!) +- Chat index UI enhancements (thanks @MuriloFP!) +- Fix model search being prefilled on dropdown (thanks @kevinvandijk!) +- Improve chat UI - add camera icon margin and make placeholder non-selectable (thanks @MuriloFP!) +- Delete .roo/rules-{mode} folder when custom mode is deleted +- Enforce file restrictions for all edit tools in architect mode +- Add User-Agent header to API providers +- Fix auto question timer unmount (thanks @liwilliam2021!) +- Fix new_task tool streaming issue +- Optimize file listing when maxWorkspaceFiles is 0 (thanks @daniel-lxs!) +- Correct export/import of OpenAI Compatible codebase indexing settings (thanks @MuriloFP!) +- Resolve workspace path inconsistency in code indexing for multi-workspace scenarios + +## [3.22.6] - 2025-07-02 + +- Add timer-based auto approve for follow up questions (thanks @liwilliam2021!) +- Add import/export modes functionality +- Add persistent version indicator on chat screen +- Add automatic configuration import on extension startup (thanks @takakoutso!) +- Add user-configurable search score threshold slider for semantic search (thanks @hannesrudolph!) +- Add default headers and testing for litellm fetcher (thanks @andrewshu2000!) +- Fix consistent cancellation error messages for thinking vs streaming phases +- Fix Amazon Bedrock cross-region inference profile mapping (thanks @KevinZhao!) +- Fix URL loading timeout issues in @ mentions (thanks @MuriloFP!) +- Fix API retry exponential backoff capped at 10 minutes (thanks @MuriloFP!) +- Fix Qdrant URL field auto-filling with default value (thanks @SannidhyaSah!) +- Fix profile context condensation threshold (thanks @PaperBoardOfficial!) +- Fix apply_diff tool documentation for multi-file capabilities +- Fix cache files excluded from rules compilation (thanks @MuriloFP!) +- Add streamlined extension installation and documentation (thanks @devxpain!) +- Prevent Architect mode from providing time estimates +- Remove context size from environment details +- Change default mode to architect for new installations +- Suppress Mermaid error rendering +- Improve Mermaid buttons with light background in light mode (thanks @chrarnoldus!) +- Add .vscode/ to write-protected files/directories +- Update Amazon Bedrock cross-region inference profile mapping (thanks @KevinZhao!) + +## [3.22.5] - 2025-06-28 + +- Remove Gemini CLI provider while we work with Google on a better integration + +## [3.22.4] - 2025-06-27 + +- Fix: resolve E2BIG error by passing large prompts via stdin to Claude CLI (thanks @Fovty!) +- Add optional mode suggestions to follow-up questions +- Fix: move StandardTooltip inside PopoverTrigger in ShareButton (thanks @daniel-lxs!) + +## [3.22.3] - 2025-06-27 + +- Restore JSON backwards compatibility for .roomodes files (thanks @daniel-lxs!) + +## [3.22.2] - 2025-06-27 + +- Fix: eliminate XSS vulnerability in CodeBlock component (thanks @KJ7LNW!) +- Fix terminal keyboard shortcut error when adding content to context (thanks @MuriloFP!) +- Fix checkpoint popover not opening due to StandardTooltip wrapper conflict (thanks @daniel-lxs!) +- Fix(i18n): correct gemini cli error translation paths (thanks @daniel-lxs!) +- Code Index (Qdrant) recreate services when change configurations (thanks @catrielmuller!) + +## [3.22.1] - 2025-06-26 + +- Add Gemini CLI provider (thanks Cline!) +- Fix undefined mcp command (thanks @qdaxb!) +- Use upstream_inference_cost for OpenRouter BYOK cost calculation and show cached token count (thanks @chrarnoldus!) +- Update maxTokens value for qwen/qwen3-32b model on Groq (thanks @KanTakahiro!) +- Standardize tooltip delays to 300ms + +## [3.22.0] - 2025-06-25 + +- Add 1-click task sharing +- Add support for loading rules from a global .roo directory (thanks @samhvw8!) +- Modes selector improvements (thanks @brunobergher!) +- Use safeWriteJson for all JSON file writes to avoid task history corruption (thanks @KJ7LNW!) +- Improve YAML error handling when editing modes +- Register importSettings as VSCode command (thanks @shivamd1810!) +- Add default task names for empty tasks (thanks @daniel-lxs!) +- Improve translation workflow to avoid unnecessary file reads (thanks @KJ7LNW!) +- Allow write_to_file to handle newline-only and empty content (thanks @Githubguy132010!) +- Address multiple memory leaks in CodeBlock component (thanks @kiwina!) +- Memory cleanup (thanks @xyOz-dev!) +- Fix port handling bug in code indexing for HTTPS URLs (thanks @benashby!) +- Improve Bedrock error handling for throttling and streaming contexts +- Handle long Claude code messages (thanks @daniel-lxs!) +- Fixes to Claude Code caching and image upload +- Disable reasoning budget UI controls for Claude Code provider +- Remove temperature parameter for Azure OpenAI reasoning models (thanks @ExactDoug!) +- Allowed commands import/export (thanks @catrielmuller!) +- Add VS Code setting to disable quick fix context actions (thanks @OlegOAndreev!) + +## [3.21.5] - 2025-06-23 + +- Fix Qdrant URL prefix handling for QdrantClient initialization (thanks @CW-B-W!) +- Improve LM Studio model detection to show all downloaded models (thanks @daniel-lxs!) +- Resolve Claude Code provider JSON parsing and reasoning block display + +## [3.21.4] - 2025-06-23 + +- Fix start line not working in multiple apply diff (thanks @samhvw8!) +- Resolve diff editor issues with markdown preview associations (thanks @daniel-lxs!) +- Resolve URL port handling bug for HTTPS URLs in Qdrant (thanks @benashby!) +- Mark unused Ollama schema properties as optional (thanks @daniel-lxs!) +- Close the local browser when used as fallback for remote (thanks @markijbema!) +- Add Claude Code provider for local CLI integration (thanks @BarreiroT!) + +## [3.21.3] - 2025-06-21 + +- Add profile-specific context condensing thresholds (thanks @SannidhyaSah!) +- Fix context length for lmstudio and ollama (thanks @thecolorblue!) +- Resolve MCP tool eye icon state and hide in chat context (thanks @daniel-lxs!) + +## [3.21.2] - 2025-06-20 + +- Add LaTeX math equation rendering in chat window +- Add toggle for excluding MCP server tools from the prompt (thanks @Rexarrior!) +- Add symlink support to list_files tool +- Fix marketplace blanking after populating +- Fix recursive directory scanning in @ mention "Add Folder" functionality (thanks @village-way!) +- Resolve phantom subtask display on cancel during API retry +- Correct Gemini 2.5 Flash pricing (thanks @daniel-lxs!) +- Resolve marketplace timeout issues and display installed MCPs (thanks @daniel-lxs!) +- Onboarding tweaks to emphasize modes (thanks @brunobergher!) +- Rename 'Boomerang Tasks' to 'Task Orchestration' for clarity +- Remove command execution from attempt_completion +- Fix markdown for links followed by punctuation (thanks @xyOz-dev!) + +## [3.21.1] - 2025-06-19 + +- Fix tree-sitter issues that were preventing codebase indexing from working correctly +- Improve error handling for codebase search embeddings +- Resolve MCP server execution on Windows with node version managers +- Default 'Enable MCP Server Creation' to false +- Rate limit correctly when starting a subtask (thanks @olweraltuve!) + +## [3.21.0] - 2025-06-17 + +- Add Roo Marketplace to make it easy to discover and install great MCPs and modes! +- Add Gemini 2.5 models (Pro, Flash and Flash Lite) (thanks @daniel-lxs!) +- Add support for Excel (.xlsx) files in tools (thanks @chrarnoldus!) +- Add max tokens checkbox option for OpenAI compatible provider (thanks @AlexandruSmirnov!) +- Update provider models and prices for Groq & Mistral (thanks @KanTakahiro!) +- Add proper error handling for API conversation history issues (thanks @KJ7LNW!) +- Fix ambiguous model id error (thanks @elianiva!) +- Fix save/discard/revert flow for Prompt Settings (thanks @hassoncs!) +- Fix codebase indexing alignment with list-files hidden directory filtering (thanks @daniel-lxs!) +- Fix subtask completion mismatch (thanks @feifei325!) +- Fix Windows path normalization in MCP variable injection (thanks @daniel-lxs!) +- Update marketplace branding to 'Roo Marketplace' (thanks @SannidhyaSah!) +- Refactor to more consistent history UI (thanks @elianiva!) +- Adjust context menu positioning to be near Copilot +- Update evals Docker setup to work on Windows (thanks @StevenTCramer!) +- Include current working directory in terminal details +- Encourage use of start_line in multi-file diff to match legacy diff +- Always focus the panel when clicked to ensure menu buttons are visible (thanks @hassoncs!) + +## [3.20.3] - 2025-06-13 + +- Resolve diff editor race condition in multi-monitor setups (thanks @daniel-lxs!) +- Add logic to prevent auto-approving edits of configuration files +- Adjust searching and listing files outside of the workspace to respect the auto-approve settings +- Add Indonesian translation support (thanks @chrarnoldus and @daniel-lxs!) +- Fix multi-file diff error handling and UI feedback (thanks @daniel-lxs!) +- Improve prompt history navigation to not interfere with text editing (thanks @daniel-lxs!) +- Fix errant maxReadFileLine default + +## [3.20.2] - 2025-06-13 + +- Limit search_files to only look within the workspace for improved security +- Force tar-fs >=2.1.3 for security vulnerability fix +- Add cache breakpoints for custom vertex models on Unbound (thanks @pugazhendhi-m!) +- Reapply reasoning for bedrock with fix (thanks @daniel-lxs!) +- Sync BatchDiffApproval styling with BatchFilePermission for UI consistency (thanks @samhvw8!) +- Add max height constraint to MCP execution response for better UX (thanks @samhvw8!) +- Prevent MCP 'installed' label from being squeezed #4630 (thanks @daniel-lxs!) +- Allow a lower context condensing threshold (thanks @SECKainersdorfer!) +- Avoid type system duplication for cleaner codebase (thanks @EamonNerbonne!) + +## [3.20.1] - 2025-06-12 + +- Temporarily revert thinking support for Bedrock models +- Improve performance of MCP execution block +- Add indexing status badge to chat view + +## [3.20.0] - 2025-06-12 + +- Add experimental Marketplace for extensions and modes (thanks @Smartsheet-JB-Brown, @elianiva, @monkeyDluffy6017, @NamesMT, @daniel-lxs, Cline, and more!) +- Add experimental multi-file edits (thanks @samhvw8!) +- Move concurrent reads setting to context settings with default of 5 +- Improve MCP execution UX (thanks @samhvw8!) +- Add magic variables support for MCPs with `workspaceFolder` injection (thanks @NamesMT!) +- Add prompt history navigation via arrow up/down in prompt field +- Add support for escaping context mentions (thanks @KJ7LNW!) +- Add DeepSeek R1 support to Chutes provider +- Add reasoning budget support to Bedrock models for extended thinking +- Add mermaid diagram support buttons (thanks @qdaxb!) +- Update XAI models and pricing (thanks @edwin-truthsearch-io!) +- Update O3 model pricing +- Add manual OpenAI-compatible format specification and parsing (thanks @dflatline!) +- Add core tools integration tests for comprehensive coverage +- Add JSDoc documentation for ClineAsk and ClineSay types (thanks @hannesrudolph!) +- Populate whenToUse descriptions for built-in modes +- Fix file write tool with early relPath & newContent validation checks (thanks @Ruakij!) +- Fix TaskItem display and copy issues with HTML tags in task messages (thanks @forestyoo!) +- Fix OpenRouter cost calculation with BYOK (thanks @chrarnoldus!) +- Fix terminal busy state reset after manual commands complete +- Fix undefined output on multi-file apply_diff operations (thanks @daniel-lxs!) + +## [3.19.7] - 2025-06-11 + +- Fix McpHub sidebar focus behavior to prevent unwanted focus grabbing +- Disable checkpoint functionality when nested git repositories are detected to prevent conflicts +- Remove unused Storybook components and dependencies to reduce bundle size +- Add data-testid ESLint rule for improved testing standards (thanks @elianiva!) +- Update development dependencies including eslint, knip, @types/node, i18next, fast-xml-parser, and @google/genai +- Improve CI infrastructure with GitHub Actions and Blacksmith runner migrations + +## [3.19.6] - 2025-06-09 + +- Replace explicit caching with implicit caching to reduce latency for Gemini models +- Clarify that the default concurrent file read limit is 15 files (thanks @olearycrew!) +- Fix copy button logic (thanks @samhvw8!) +- Fade buttons on history preview if no interaction in progress (thanks @sachasayan!) +- Allow MCP server refreshing, fix state changes in MCP server management UI view (thanks @taylorwilsdon!) +- Remove unnecessary npx usage in some npm scripts (thanks @user202729!) +- Bug fix for trailing slash error when using LiteLLM provider (thanks @kcwhite!) + +## [3.19.5] - 2025-06-05 + +- Fix Gemini 2.5 Pro Preview thinking budget bug + +## [3.19.4] - 2025-06-05 + +- Add Gemini Pro 06-05 model support (thanks @daniel-lxs and @shariqriazz!) +- Fix reading PDF, DOCX, and IPYNB files in read_file tool (thanks @samhvw8!) +- Fix Mermaid CSP errors with enhanced bundling strategy (thanks @KJ7LNW!) +- Improve model info detection for custom Bedrock ARNs (thanks @adamhill!) +- Add OpenAI Compatible embedder for codebase indexing (thanks @SannidhyaSah!) +- Fix multiple memory leaks in ChatView component (thanks @kiwina!) +- Fix WorkspaceTracker resource leaks by disposing FileSystemWatcher (thanks @kiwina!) +- Fix RooTips setTimeout cleanup to prevent state updates on unmounted components (thanks @kiwina!) +- Fix FileSystemWatcher leak in RooIgnoreController (thanks @kiwina!) +- Fix clipboard memory leak by clearing setTimeout in useCopyToClipboard (thanks @kiwina!) +- Fix ClineProvider instance cleanup (thanks @xyOz-dev!) +- Enforce codebase_search as primary tool for code understanding tasks (thanks @hannesrudolph!) +- Improve Docker setup for evals +- Move evals into pnpm workspace, switch from SQLite to Postgres +- Refactor MCP to use getDefaultEnvironment for stdio client transport (thanks @samhvw8!) +- Get rid of "partial" component in names referencing not necessarily partial messages (thanks @wkordalski!) +- Improve feature request template (thanks @elianiva!) + +## [3.19.3] - 2025-06-02 + +- Fix SSE MCP Invocation - Fixed SSE connection issue in McpHub.ts by ensuring transport.start override only applies to stdio transports, allowing SSE and streamable-http transports to retain their original start methods (thanks @taylorwilsdon!) + +## [3.19.2] - 2025-06-01 + +- Add support for Streamable HTTP Transport MCP servers (thanks @taylorwilsdon!) +- Add cached read and writes to stats and cost calculation for LiteLLM provider (thanks @mollux!) +- Prevent dump of an entire file into the context on user edit (thanks @KJ7LNW!) +- Fix directory link handling in markdown (thanks @KJ7LNW!) +- Prevent start_line/end_line in apply_diff REPLACE (thanks @KJ7LNW!) +- Unify history item UI with TaskItem and TaskItemHeader (thanks @KJ7LNW!) +- Fix the label of the OpenAI-compatible API keys +- Fix Virtuoso footer re-rendering issue (thanks @kiwina!) +- Optimize ChatRowContent layout and styles (thanks @zhangtony239!) +- Release memory in apply diff (thanks @xyOz-dev!) +- Upgrade Node.js to v20.19.2 for security enhancements (thanks @PeterDaveHello!) +- Fix typos (thanks @noritaka1166!) + +## [3.19.1] - 2025-05-30 + +- Experimental feature to allow reading multiple files at once (thanks @samhvw8!) +- Fix to correctly pass headers to SSE MCP servers +- Adding support for custom VPC endpoints when using Amazon Bedrock (thanks @kcwhite!) +- Fix bug with context condensing in Amazon Bedrock +- Fix UTF-8 encoding in ExecaTerminalProcess (thanks @mr-ryan-james!) +- Set sidebar name bugfix (thanks @chrarnoldus!) +- Fix link to CONTRIBUTING.md in feature request template (thanks @cannuri!) +- Add task metadata to Unbound and improve caching logic (thanks @pugazhendhi-m!) + +## [3.19.0] - 2025-05-29 + +- Enable intelligent content condensing by default and move condense button out of expanded task menu +- Skip condense and show error if context grows during condensing +- Transform Prompts tab into Modes tab and move support prompts to Settings for better organization +- Add DeepSeek R1 0528 model support to Chutes provider (thanks @zeozeozeo!) +- Fix @directory not respecting .rooignore files (thanks @xyOz-dev!) +- Add rooignore checking for insert_content and search_and_replace tools +- Fix menu breaking when Roo is moved between primary and secondary sidebars (thanks @chrarnoldus!) +- Resolve memory leak in ChatView by stabilizing callback props (thanks @samhvw8!) +- Fix write_to_file to properly create empty files when content is empty (thanks @Ruakij!) +- Fix chat input clearing during running tasks (thanks @xyOz-dev!) +- Update AWS regions to include Spain and Hyderabad +- Improve POSIX shell compatibility in pre-push hook (thanks @PeterDaveHello and @chrarnoldus!) +- Update PAGER environment variable for Windows compatibility in Terminal (thanks @SmartManoj!) +- Add environment variable injection support for whole MCP config (thanks @NamesMT!) +- Update codebase search description to emphasize English query requirements (thanks @ChuKhaLi!) + +## [3.18.5] - 2025-05-27 + +- Add thinking controls for Requesty (thanks @dtrugman!) +- Re-enable telemetry +- Improve zh-TW Traditional Chinese locale (thanks @PeterDaveHello and @chrarnoldus!) +- Improve model metadata for LiteLLM + +## [3.18.4] - 2025-05-25 + +- Fix codebase indexing settings saving and Ollama indexing (thanks @daniel-lxs!) +- Fix handling BOM when user rejects apply_diff (thanks @avtc!) +- Fix wrongfully clearing input on auto-approve (thanks @Ruakij!) +- Fix correct spawnSync parameters for pnpm check in bootstrap.mjs (thanks @ChuKhaLi!) +- Update xAI models and default model ID (thanks @PeterDaveHello!) +- Add metadata to create message (thanks @dtrugman!) + +## [3.18.3] - 2025-05-24 + +- Add reasoning support for Claude 4 and Gemini 2.5 Flash on OpenRouter, plus a fix for o1-pro +- Add experimental codebase indexing + semantic search feature (thanks @daniel-lxs!) +- For providers that used to default to Sonnet 3.7, change to Sonnet 4 +- Enable prompt caching for Gemini 2.5 Flash Preview (thanks @shariqriazz!) +- Preserve model settings when selecting a specific OpenRouter provider +- Add ability to refresh LiteLLM models list +- Improve tool descriptions to guide proper file editing tool selection +- Fix MCP Server error loading config when running with npx and bunx (thanks @devxpain!) +- Improve pnpm bootstrapping and add compile script (thanks @KJ7LNW!) +- Simplify object assignment & use startsWith (thanks @noritaka1166!) +- Fix mark-as-read logic in the context tracker (thanks @samhvw8!) +- Remove deprecated claude-3.7-sonnet models from vscodelm (thanks @shariqriazz!) + +## [3.18.2] - 2025-05-23 + +- Fix vscode-material-icons in the file picker +- Fix global settings export +- Respect user-configured terminal integration timeout (thanks @KJ7LNW) +- Context condensing enhancements (thanks @SannidhyaSah) + +## [3.18.1] - 2025-05-22 + +- Add support for Claude Sonnet 4 and Claude Opus 4 models with thinking variants in Anthropic, Bedrock, and Vertex (thanks @shariqriazz!) +- Fix README gif display in all localized versions +- Fix referer URL +- Switch codebase to a monorepo and create an automated "nightly" build + +## [3.18.0] - 2025-05-21 + +- Add support for Gemini 2.5 Flash preview models (thanks @shariqriazz and @daniel-lxs!) +- Add button to task header to intelligently condense content with visual feedback +- Add YAML support for mode definitions (thanks @R-omk!) +- Add allowedMaxRequests feature to cap consecutive auto-approved requests (inspired by Cline, thanks @hassoncs!) +- Add Qwen3 model series to the Chutes provider (thanks @zeozeozeo!) +- Fix more causes of grey screen issues (thanks @xyOz-dev!) +- Add LM Studio reasoning support (thanks @avtc!) +- Add refresh models button for Unbound provider (thanks @pugazhendhi-m!) +- Add template variables for version numbers in announcement strings (thanks @ChuKhaLi!) +- Make prompt input textareas resizable again +- Fix diffview scroll display (thanks @qdaxb!) +- Fix LM Studio and Ollama usage tracking (thanks @xyOz-dev!) +- Fix links to filename:0 (thanks @RSO!) +- Fix missing or inconsistent syntax highlighting across UI components (thanks @KJ7LNW!) +- Fix packaging to include correct tiktoken.wasm (thanks @vagadiya!) +- Fix import settings bugs and position error messages correctly (thanks @ChuKhaLi!) +- Move audio playing to the webview to ensure cross-platform support (thanks @SmartManoj and @samhvw8!) +- Simplify loop syntax in multiple components (thanks @noritaka1166!) +- Auto reload extension core changes in dev mode (thanks @hassoncs!) + +## [3.17.2] - 2025-05-15 + +- Revert "Switch to the new Roo message parser" (appears to cause a tool parsing bug) +- Lock the versions of vsce and ovsx + +## [3.17.1] - 2025-05-15 + +- Fix the display of the command to execute during approval +- Fix incorrect reserved tokens calculation on OpenRouter (thanks @daniel-lxs!) + +## [3.17.0] - 2025-05-14 + +- Enable Gemini implicit caching +- Add "when to use" section to mode definitions to enable better orchestration +- Add experimental feature to intelligently condense the task context instead of truncating it +- Fix one of the causes of the gray screen issue (thanks @xyOz-dev!) +- Focus improvements for better UI interactions (thanks Cline!) +- Switch to the new Roo message parser for improved performance (thanks Cline!) +- Enable source maps for improved debugging (thanks @KJ7LNW!) +- Update OpenRouter provider to use provider-specific model info (thanks @daniel-lxs!) +- Fix Requesty cost/token reporting (thanks @dtrugman!) +- Improve command execution UI +- Add more in-app links to relevant documentation +- Update the new task tool description and the ask mode custom instructions in the system prompt +- Add IPC types to roo-code.d.ts +- Add build VSIX workflow to pull requests (thanks @SmartManoj!) +- Improve apply_diff tool to intelligently deduce line numbers (thanks @samhvw8!) +- Fix command validation for shell array indexing (thanks @KJ7LNW!) +- Handle diagnostics that point at a directory URI (thanks @daniel-lxs!) +- Fix "Current ask promise was ignored" error (thanks @zxdvd!) + +## [3.16.6] - 2025-05-12 + +- Restore "Improve provider profile management in the external API" +- Fix to subtask sequencing (thanks @wkordalski!) +- Fix webview terminal output processing error (thanks @KJ7LNW!) +- Fix textarea empty string fallback logic (thanks @elianiva!) + +## [3.16.5] - 2025-05-10 + +- Revert "Improve provider profile management in the external API" until we track down a bug with defaults + +## [3.16.4] - 2025-05-09 + +- Improve provider profile management in the external API +- Enforce provider selection in OpenRouter by using 'only' parameter and disabling fallbacks (thanks @shariqriazz!) +- Fix display issues with long profile names (thanks @cannuri!) +- Prevent terminal focus theft on paste after command execution (thanks @MuriloFP!) +- Save OpenAI compatible custom headers correctly +- Fix race condition when updating prompts (thanks @elianiva!) +- Fix display issues in high contrast themes (thanks @zhangtony239!) +- Fix not being able to use specific providers on Openrouter (thanks @daniel-lxs!) +- Show properly formatted multi-line commands in preview (thanks @KJ7LNW!) +- Handle unsupported language errors gracefully in read_file tool (thanks @KJ7LNW!) +- Enhance focus styles in select-dropdown and fix docs URL (thanks @zhangtony239!) +- Properly handle mode name overflow in UI (thanks @elianiva!) +- Fix project MCP always allow issue (thanks @aheizi!) + +## [3.16.3] - 2025-05-08 + +- Revert Tailwind migration while we fix a few spots +- Add Elixir file extension support in language parser (thanks @pfitz!) + +## [3.16.2] - 2025-05-07 + +- Clarify XML tool use formatting instructions +- Error handling code cleanup (thanks @monkeyDluffy6017!) + +## [3.16.1] - 2025-05-07 + +- Add LiteLLM provider support +- Improve stability by detecting and preventing tool loops +- Add Dutch localization (thanks @Githubguy132010!) +- Add editor name to telemetry for better analytics +- Migrate to Tailwind CSS for improved UI consistency +- Fix footer button wrapping in About section on narrow screens (thanks @ecmasx!) +- Update evals defaults +- Update dependencies to latest versions + +## [3.16.0] - 2025-05-06 + +- Add vertical tab navigation to the settings (thanks @dlab-anton) +- Add Groq and Chutes API providers (thanks @shariqriazz) +- Clickable code references in code block (thanks @KJ7LNW) +- Improve accessibility of auto-approve toggles (thanks @Deon588) +- Requesty provider fixes (thanks @dtrugman) +- Fix migration and persistence of per-mode API profiles (thanks @alasano) +- Fix usage of `path.basename` in the extension webview (thanks @samhvw8) +- Fix display issue of the programming language dropdown in the code block component (thanks @zhangtony239) +- MCP server errors are now captured and shown in a new "Errors" tab (thanks @robertheadley) +- Error logging will no longer break MCP functionality if the server is properly connected (thanks @ksze) +- You can now toggle the `terminal.integrated.inheritEnv` VSCode setting directly for the Roo Code settings (thanks @KJ7LNW) +- Add `gemini-2.5-pro-preview-05-06` to the Vertex and Gemini providers (thanks @zetaloop) +- Ensure evals exercises are up-to-date before running evals (thanks @shariqriazz) +- Lots of general UI improvements (thanks @elianiva) +- Organize provider settings into separate components +- Improved icons and translations for the code block component +- Add support for tests that use ESM libraries +- Move environment detail generation to a separate module +- Enable prompt caching by default for supported Gemini models + +## [3.15.5] - 2025-05-05 + +- Update @google/genai to 0.12 (includes some streaming completion bug fixes) +- Rendering performance improvements for code blocks in chat (thanks @KJ7LNW) + +## [3.15.4] - 2025-05-04 + +- Fix a nasty bug that would cause Roo Code to hang, particularly in orchestrator mode +- Improve Gemini caching efficiency + +## [3.15.3] - 2025-05-02 + +- Terminal: Fix empty command bug +- Terminal: More robust process killing +- Optimize Gemini prompt caching for OpenRouter +- Chat view performance improvements + +## [3.15.2] - 2025-05-02 + +- Fix terminal performance issues +- Handle Mermaid validation errors +- Add customizable headers for OpenAI-compatible provider (thanks @mark-bradshaw!) +- Add config option to overwrite OpenAI's API base (thanks @GOODBOY008!) +- Fixes to padding and height issues when resizing the sidebar (thanks @zhangtony239!) +- Remove tool groups from orchestrator mode definition +- Add telemetry for title button clicks + +## [3.15.1] - 2025-04-30 + +- Capture stderr in execa-spawned processes +- Play sound only when action needed from the user (thanks @olearycrew) +- Make retries respect the global auto approve checkbox +- Fix a selection mode bug in the history view (thanks @jr) + +## [3.15.0] - 2025-04-30 + +- Add prompt caching to the Google Vertex provider (thanks @ashktn) +- Add a fallback mechanism for executing terminal commands if VSCode terminal shell integration fails +- Improve the UI/UX of code snippets in the chat (thanks @KJ7LNW) +- Add a reasoning effort setting for the OpenAI Compatible provider (thanks @mr-ryan-james) +- Allow terminal commands to be stopped directly from the chat UI +- Adjust chat view padding to accommodate small width layouts (thanks @zhangtony239) +- Fix file mentions for filenames containing spaces +- Improve the auto-approve toggle buttons for some high-contrast VSCode themes +- Offload expensive count token operations to a web worker (thanks @samhvw8) +- Improve support for multi-root workspaces (thanks @snoyiatk) +- Simplify and streamline Roo Code's quick actions +- Allow Roo Code settings to be imported from the welcome screen (thanks @julionav) +- Remove unused types (thanks @wkordalski) +- Improve the performance of mode switching (thanks @dlab-anton) +- Fix importing & exporting of custom modes (thanks @julionav) + +## [3.14.3] - 2025-04-25 + +- Add Boomerang Orchestrator as a built-in mode +- Improve home screen UI +- Make token count estimation more efficient to reduce gray screens +- Revert change to automatically close files after edit until we figure out how to make it work well with diagnostics +- Clean up settings data model +- Omit reasoning params for non-reasoning models +- Clearer documentation for adding settings (thanks @shariqriazz!) +- Fix word wrapping in Roo message title (thanks @zhangtony239!) +- Update default model id for Unbound from claude 3.5 to 3.7 (thanks @pugazhendhi-m!) + +## [3.14.2] - 2025-04-24 + +- Enable prompt caching for Gemini (with some improvements) +- Allow users to turn prompt caching on / off for Gemini 2.5 on OpenRouter +- Compress terminal output with backspace characters (thanks @KJ7LNW) +- Add Russian language (Спасибо @asychin) + +## [3.14.1] - 2025-04-24 + +- Disable Gemini caching while we investigate issues reported by the community. + +## [3.14.0] - 2025-04-23 + +- Add prompt caching for `gemini-2.5-pro-preview-03-25` in the Gemini provider (Vertex and OpenRouter coming soon!) +- Improve the search_and_replace and insert_content tools and bring them out of experimental, and deprecate append_to_file (thanks @samhvw8!) +- Use material icons for files and folders in mentions (thanks @elianiva!) +- Make the list_files tool more efficient and smarter about excluding directories like .git/ +- Fix file drag and drop on Windows and when using SSH tunnels (thanks @NyxJae!) +- Correctly revert changes and suggest alternative tools when write_to_file fails on a missing line count +- Allow interpolation of `workspace`, `mode`, `language`, `shell`, and `operatingSystem` into custom system prompt overrides (thanks @daniel-lxs!) +- Fix interpolation bug in the “add to context” code action (thanks @elianiva!) +- Preserve editor state and prevent tab unpinning during diffs (thanks @seedlord!) +- Improvements to icon rendering on Linux (thanks @elianiva!) +- Improvements to Requesty model list fetching (thanks @dtrugman!) +- Fix user feedback not being added to conversation history in API error state, redundant ‘TASK RESUMPTION’ prompts, and error messages not showing after cancelling API requests (thanks @System233!) +- Track tool use errors in evals +- Fix MCP hub error when dragging extension to another sidebar +- Improve display of long MCP tool arguments +- Fix redundant ‘TASK RESUMPTION’ prompts (thanks @System233!) +- Fix bug opening files when editor has no workspace root +- Make the VS Code LM provider show the correct model information (thanks @QuinsZouls!) +- Fixes to make the focusInput command more reliable (thanks @hongzio!) +- Better handling of aftercursor content in context mentions (thanks @elianiva!) +- Support injecting environment variables in MCP config (thanks @NamesMT!) +- Better handling of FakeAI “controller” object (thanks @wkordalski) +- Remove unnecessary calculation from VS Code LM provider (thanks @d-oit!) +- Allow Amazon Bedrock Marketplace ARNs (thanks @mlopezr!) +- Give better loading feedback on chat rows (thanks @elianiva!) +- Performance improvements to task size calculations +- Don’t immediately show a model ID error when changing API providers +- Fix apply_diff edge cases +- Use a more sensible task export icon +- Use path aliases in webview source files +- Display a warning when the system prompt is overridden +- Better progress indicator for apply_diff tools (thanks @qdaxb!) +- Fix terminal carriage return handling for correct progress bar display (thanks @Yikai-Liao!) + +## [3.13.2] - 2025-04-18 + +- Allow custom URLs for Gemini provider + +## [3.13.1] - 2025-04-18 + +- Support Gemini 2.5 Flash thinking mode (thanks @monotykamary) +- Make auto-approval toggle on/off states more obvious (thanks @sachasayan) +- Add telemetry for shell integration errors +- Fix the path of files dragging into the chat textarea on Windows (thanks @NyxJae) + +## [3.13.0] - 2025-04-17 + +- UI improvements to task header, chat view, history preview, and welcome view (thanks @sachasayan!) +- Add append_to_file tool for appending content to files (thanks @samhvw8!) +- Add Gemini 2.5 Flash Preview to Gemini and Vertex providers (thanks @nbihan-mediware!) +- Fix image support in Bedrock (thanks @Smartsheet-JB-Brown!) +- Make diff edits more resilient to models passing in incorrect parameters + +## [3.12.3] - 2025-04-17 + +- Fix character escaping issues in Gemini diff edits +- Support dragging and dropping tabs into the chat box (thanks @NyxJae!) +- Make sure slash commands only fire at the beginning of the chat box (thanks @logosstone!) + +## [3.12.2] - 2025-04-16 + +- Add OpenAI o3 & 4o-mini (thanks @PeterDaveHello!) +- Improve file/folder context mention UI (thanks @elianiva!) +- Improve diff error telemetry + +## [3.12.1] - 2025-04-16 + +- Bugfix to Edit button visibility in the select dropdowns + +## [3.12.0] - 2025-04-15 + +- Add xAI provider and expose reasoning effort options for Grok on OpenRouter (thanks Cline!) +- Make diff editing config per-profile and improve pre-diff string normalization +- Make checkpoints faster and more reliable +- Add a search bar to mode and profile select dropdowns (thanks @samhvw8!) +- Add telemetry for code action usage, prompt enhancement usage, and consecutive mistake errors +- Suppress zero cost values in the task header (thanks @do-it!) +- Make JSON parsing safer to avoid crashing the webview on bad input +- Allow users to bind a keyboard shortcut for accepting suggestions or input in the chat view (thanks @axkirillov!) + +## [3.11.17] - 2025-04-14 + +- Improvements to OpenAI cache reporting and cost estimates (thanks @monotykamary and Cline!) +- Visual improvements to the auto-approve toggles (thanks @sachasayan!) +- Bugfix to diff apply logic (thanks @avtc for the test case!) and telemetry to track errors going forward +- Fix race condition in capturing short-running terminal commands (thanks @KJ7LNW!) +- Fix eslint error (thanks @nobu007!) + +## [3.11.16] - 2025-04-14 + +- Add gpt-4.1, gpt-4.1-mini, and gpt-4.1-nano to the OpenAI provider +- Include model ID in environment details and when exporting tasks (thanks @feifei325!) + +## [3.11.15] - 2025-04-13 + +- Add ability to filter task history by workspace (thanks @samhvw8!) +- Fix Node.js version in the .tool-versions file (thanks @bogdan0083!) +- Fix duplicate suggested mentions for open tabs (thanks @samhvw8!) +- Fix Bedrock ARN validation and token expiry issue when using profiles (thanks @vagadiya!) +- Add Anthropic option to pass API token as Authorization header instead of X-Api-Key (thanks @mecab!) +- Better documentation for adding new settings (thanks @KJ7LNW!) +- Localize package.json (thanks @samhvw8!) +- Add option to hide the welcome message and fix the background color for the new profile dialog (thanks @zhangtony239!) +- Restore the focus ring for the VSCodeButton component (thanks @pokutuna!) + +## [3.11.14] - 2025-04-11 + +- Support symbolic links in rules folders to directories and other symbolic links (thanks @taisukeoe!) +- Stronger enforcement of the setting to always read full files instead of doing partial reads + +## [3.11.13] - 2025-04-11 + +- Loads of terminal improvements: command delay, PowerShell counter, and ZSH EOL mark (thanks @KJ7LNW!) +- Add file context tracking system (thanks @samhvw8 and @canvrno!) +- Improved display of diff errors + easy copying for investigation +- Fixes to .vscodeignore (thanks @franekp!) +- Fix a zh-CN translation for model capabilities (thanks @zhangtony239!) +- Rename Amazon Bedrock to Amazon Bedrock (thanks @ronyblum!) +- Update extension title and description (thanks @StevenTCramer!) + +## [3.11.12] - 2025-04-09 + +- Make Grok3 streaming work with OpenAI Compatible (thanks @amittell!) +- Tweak diff editing logic to make it more tolerant of model errors + +## [3.11.11] - 2025-04-09 + +- Fix highlighting interaction with mode/profile dropdowns (thanks @atlasgong!) +- Add the ability to set Host header and legacy OpenAI API in the OpenAI-compatible provider for better proxy support +- Improvements to TypeScript, C++, Go, Java, Python tree-sitter parsers (thanks @KJ7LNW!) +- Fixes to terminal working directory logic (thanks @KJ7LNW!) +- Improve readFileTool XML output format (thanks @KJ7LNW!) +- Add o1-pro support (thanks @arthurauffray!) +- Follow symlinked rules files/directories to allow for more flexible rule setups +- Focus Roo Code in the sidebar when running tasks in the sidebar via the API +- Improve subtasks UI + +## [3.11.10] - 2025-04-08 + +- Fix bug where nested .roo/rules directories are not respected properly (thanks @taisukeoe!) +- Handle long command output more efficiently in the chat row (thanks @samhvw8!) +- Fix cache usage tracking for OpenAI-compatible providers +- Add custom translation instructions for zh-CN (thanks @System233!) +- Code cleanup after making rate-limits per-profile (thanks @ross!) + +## [3.11.9] - 2025-04-07 + +- Rate-limit setting updated to be per-profile (thanks @ross and @olweraltuve!) +- You can now place multiple rules files in the .roo/rules/ and .roo/rules-{mode}/ folders (thanks @upamune!) +- Prevent unnecessary autoscroll when buttons appear (thanks @shtse8!) +- Add Gemini 2.5 Pro Preview to Vertex AI (thanks @nbihan-mediware!) +- Tidy up following ClineProvider refactor (thanks @diarmidmackenzie!) +- Clamp negative line numbers when reading files (thanks @KJ7LNW!) +- Enhance Rust tree-sitter parser with advanced language structures (thanks @KJ7LNW!) +- Persist settings on api.setConfiguration (thanks @gtaylor!) +- Add deep links to settings sections +- Add command to focus Roo Code input field (thanks @axkirillov!) +- Add resize and hover actions to the browser (thanks @SplittyDev!) +- Add resumeTask and isTaskInHistory to the API (thanks @franekp!) +- Fix bug displaying boolean/numeric suggested answers +- Dynamic Vite port detection for webview development (thanks @KJ7LNW!) + +## [3.11.8] - 2025-04-05 + +- Improve combineApiRequests performance to reduce gray screens of death (thanks @kyle-apex!) +- Add searchable dropdown to API config profiles on the settings screen (thanks @samhvw8!) +- Add workspace tracking to history items in preparation for future filtering (thanks @samhvw8!) +- Fix search highlighting UI in history search (thanks @samhvw8!) +- Add support for .roorules and give deprecation warning for .clinerules (thanks @upamune!) +- Fix nodejs version format in .tool-versions file (thanks @upamune!) + +## [3.11.7] - 2025-04-04 + +- Improve file tool context formatting and diff error guidance +- Improve zh-TW localization (thanks @PeterDaveHello!) +- Implement reference counting for McpHub disposal +- Update buttons to be more consistent (thanks @kyle-apex!) +- Improve zh-CN localization (thanks @System233!) + +## [3.11.6] - 2025-04-04 + +- Add the gemini 2.5 pro preview model with upper bound pricing + +## [3.11.5] - 2025-04-03 + +- Add prompt caching for Amazon Bedrock (thanks @Smartsheet-JB-Brown!) +- Add support for configuring the current working directory of MCP servers (thanks @shoopapa!) +- Add profile management functions to API (thanks @gtaylor!) +- Improvements to diff editing functionality, tests, and error messages (thanks @p12tic!) +- Fix for follow-up questions grabbing the focus (thanks @diarmidmackenzie!) +- Show menu buttons when popping the extension out into a new tab (thanks @benny123tw!) + +## [3.11.4] - 2025-04-02 + +- Correctly post state to webview when the current task is cleared (thanks @wkordalski!) +- Fix unit tests to run properly on Windows (thanks @StevenTCramer!) +- Tree-sitter enhancements: TSX, TypeScript, JSON, and Markdown support (thanks @KJ7LNW!) +- Fix issue with line number stripping for deletions in apply_diff +- Update history selection mode button spacing (thanks @kyle-apex!) +- Limit dropdown menu height to 80% of the viewport (thanks @axmo!) +- Update dependencies via `npm audit fix` (thanks @PeterDaveHello!) +- Enable model select when api fails (thanks @kyle-apex!) +- Fix issue where prompts and settings tabs were not scrollable when accessed from dropdown menus +- Update AWS region dropdown menu to the most recent data (thanks @Smartsheet-JB-Brown!) +- Fix prompt enhancement for Bedrock (thanks @Smartsheet-JB-Brown!) +- Allow processes to access the Roo Code API via a unix socket +- Improve zh-TW Traditional Chinese translations (thanks @PeterDaveHello!) +- Add support for Azure AI Inference Service with DeepSeek-V3 model (thanks @thomasjeung!) +- Fix off-by-one error in tree-sitter line numbers +- Remove the experimental unified diff +- Make extension icon more visible in different themes + +## [3.11.3] - 2025-03-31 + +- Revert mention changes in case they're causing performance issues/crashes + +## [3.11.2] - 2025-03-31 + +- Fix bug in loading Requesty key balance +- Fix bug with Bedrock inference profiles +- Update the webview when changing settings via the API +- Refactor webview messages code (thanks @diarmidmackenzie!) + +## [3.11.1] - 2025-03-30 + +- Relax provider profiles schema and add telemetry + +## [3.11.0] - 2025-03-30 + +- Replace single-block-diff with multi-block-diff fast editing strategy +- Support project-level MCP config in .roo/mcp.json (thanks @aheizi!) +- Show OpenRouter and Requesty key balance on the settings screen +- Support import/export of settings +- Add pinning and sorting for API configuration dropdown (thanks @jwcraig!) +- Add Gemini 2.5 Pro to GCP Vertex AI provider (thanks @nbihan-mediware!) +- Smarter retry logic for Gemini +- Fix Gemini command escaping +- Support @-mentions of files with spaces in the name (thanks @samhvw8!) +- Improvements to partial file reads (thanks @KJ7LNW!) +- Fix list_code_definition_names to support files (thanks @KJ7LNW!) +- Refactor tool-calling logic to make the code a lot easier to work with (thanks @diarmidmackenzie, @bramburn, @KJ7LNW, and everyone else who helped!) +- Prioritize “Add to Context” in the code actions and include line numbers (thanks @samhvw8!) +- Add an activation command that other extensions can use to interface with Roo Code (thanks @gtaylor!) +- Preserve language characters in file @-mentions (thanks @aheizi!) +- Browser tool improvements (thanks @afshawnlotfi!) +- Display info about partial reads in the chat row +- Link to the settings page from the auto-approve toolbar +- Link to provider docs from the API options +- Fix switching profiles to ensure only the selected profile is switched (thanks @feifei325!) +- Allow custom o3-mini- model from OpenAI-compatible providers (thanks @snoyiatk!) +- Edit suggested answers before accepting them (thanks @samhvw8!) + +## [3.10.5] - 2025-03-25 + +- Updated value of max tokens for gemini-2.5-pro-03-25 to 65,536 (thanks @linegel!) +- Fix logic around when we fire task completion events + +## [3.10.4] - 2025-03-25 + +- Dynamically fetch instructions for creating/editing custom modes and MCP servers (thanks @diarmidmackenzie!) +- Added Gemini 2.5 Pro model to Google Gemini provider (thanks @samsilveira!) +- Add settings to control whether to auto-approve reads and writes outside of the workspace +- Update UX for chat text area (thanks @chadgauth!) +- Support a custom storage path for tasks (thanks @Chenjiayuan195!) +- Add a New Task command in the Command Palette (thanks @qdaxb!) +- Add R1 support checkbox to Open AI compatible provider to support QWQ (thanks @teddyOOXX!) +- Support test declarations in TypeScript tree-sitter queries (thanks @KJ7LNW!) +- Add Bedrock support for application-inference-profile (thanks @maekawataiki!) +- Rename and migrate global MCP and modes files (thanks @StevenTCramer!) +- Add watchPaths option to McpHub for file change detection (thanks @01Rian!) +- Read image responses from MCP calls (thanks @nevermorec!) +- Add taskCreated event to API and subscribe to Cline events earlier (thanks @wkordalski!) +- Fixes to numeric formatting suffix internationalization (thanks @feifei325!) +- Fix open tab support in the context mention suggestions (thanks @aheizi!) +- Better display of OpenRouter “overloaded” error messages +- Fix browser tool visibility in system prompt preview (thanks @cannuri!) +- Fix the supportsPromptCache value for OpenAI models (thanks @PeterDaveHello!) +- Fix readme links to docs (thanks @kvokka!) +- Run ‘npm audit fix’ on all of our libraries + +## [3.10.3] - 2025-03-23 + +- Update the welcome page to provide 1-click OAuth flows with LLM routers (thanks @dtrugman!) +- Switch to a more direct method of tracking OpenRouter tokens/spend +- Make partial file reads backwards-compatible with custom system prompts and give users more control over the chunk size +- Fix issues where questions and suggestions weren’t showing up for non-streaming models and were hard to read in some themes +- A variety of fixes and improvements to experimental multi-block diff (thanks @KJ7LNW!) +- Fix opacity of drop-down menus in settings (thanks @KJ7LNW!) +- Fix bugs with reading and mentioning binary files like PDFs +- Fix the pricing information for OpenRouter free models (thanks @Jdo300!) +- Fix an issue with our unit tests on Windows (thanks @diarmidmackenzie!) +- Fix a maxTokens issue for the Outbound provider (thanks @pugazhendhi-m!) +- Fix a line number issue with partial file reads (thanks @samhvw8!) + +## [3.10.2] - 2025-03-21 + +- Fixes to context mentions on Windows +- Fixes to German translations (thanks @cannuri!) +- Fixes to telemetry banner internationalization +- Sonnet 3.7 non-thinking now correctly uses 8192 max output tokens + +## [3.10.1] - 2025-03-20 + +- Make the suggested responses optional to not break overridden system prompts + +## [3.10.0] - 2025-03-20 + +- Suggested responses to questions (thanks samhvw8!) +- Support for reading large files in chunks (thanks samhvw8!) +- More consistent @-mention lookups of files and folders +- Consolidate code actions into a submenu (thanks samhvw8!) +- Fix MCP error logging (thanks aheizi!) +- Improvements to search_files tool formatting and logic (thanks KJ7LNW!) +- Fix changelog formatting in GitHub Releases (thanks pdecat!) +- Add fake provider for integration tests (thanks franekp!) +- Reflect Cross-region inference option in ap-xx region (thanks Yoshino-Yukitaro!) +- Fix bug that was causing task history to be lost when using WSL + +## [3.9.2] - 2025-03-19 + +- Update GitHub Actions workflow to automatically create GitHub Releases (thanks @pdecat!) +- Correctly persist the text-to-speech speed state (thanks @heyseth!) +- Fixes to French translations (thanks @arthurauffray!) +- Optimize build time for local development (thanks @KJ7LNW!) +- VSCode theme fixes for select, dropdown and command components +- Bring back the ability to manually enter a model name in the model picker +- Fix internationalization of the announcement title and the browser + +## [3.9.1] - 2025-03-18 + +- Pass current language to system prompt correctly so Roo thinks and speaks in the selected language + +## [3.9.0] - 2025-03-18 + +- Internationalize Roo Code into Catalan, German, Spanish, French, Hindi, Italian, Japanese, Korean, Polish, Portuguese, Turkish, Vietnamese, Simplified Chinese, and Traditional Chinese (thanks @feifei325!) +- Bring back support for MCP over SSE (thanks @aheizi!) +- Add a text-to-speech option to have Roo talk to you as it works (thanks @heyseth!) +- Choose a specific provider when using OpenRouter (thanks PhunkyBob!) +- Support batch deletion of task history (thanks @aheizi!) +- Internationalize Human Relay, adjust the layout, and make it work on the welcome screen (thanks @NyxJae!) +- Fix shell integration race condition (thanks @KJ7LNW!) +- Fix display updating for Bedrock custom ARNs that are prompt routers (thanks @Smartsheet-JB-Brown!) +- Fix to exclude search highlighting when copying items from task history (thanks @im47cn!) +- Fix context mentions to work with multiple-workspace projects (thanks @teddyOOXX!) +- Fix to task history saving when running multiple Roos (thanks @samhvw8!) +- Improve task deletion when underlying files are missing (thanks @GitlyHallows!) +- Improve support for NixOS & direnv (thanks @wkordalski!) +- Fix wheel scrolling when Roo is opened in editor tabs (thanks @GitlyHallows!) +- Don’t automatically mention the file when using the "Add to context" code action (thanks @qdaxb!) +- Expose task stack in `RooCodeAPI` (thanks @franekp!) +- Give the models visibility into the current task's API cost + +## [3.8.6] - 2025-03-13 + +- Revert SSE MCP support while we debug some config validation issues + +## [3.8.5] - 2025-03-12 + +- Refactor terminal architecture to address critical issues with the current design (thanks @KJ7LNW!) +- MCP over SSE (thanks @aheizi!) +- Support for remote browser connections (thanks @afshawnlotfi!) +- Preserve parent-child relationship when cancelling subtasks (thanks @cannuri!) +- Custom baseUrl for Google AI Studio Gemini (thanks @dqroid!) +- PowerShell-specific command handling (thanks @KJ7LNW!) +- OpenAI-compatible DeepSeek/QwQ reasoning support (thanks @lightrabbit!) +- Anthropic-style prompt caching in the OpenAI-compatible provider (thanks @dleen!) +- Add Deepseek R1 for Amazon Bedrock (thanks @ATempsch!) +- Fix MarkdownBlock text color for Dark High Contrast theme (thanks @cannuri!) +- Add gemini-2.0-pro-exp-02-05 model to vertex (thanks @shohei-ihaya!) +- Bring back progress status for multi-diff edits (thanks @qdaxb!) +- Refactor alert dialog styles to use the correct vscode theme (thanks @cannuri!) +- Custom ARNs in Amazon Bedrock (thanks @Smartsheet-JB-Brown!) +- Update MCP servers directory path for platform compatibility (thanks @hannesrudolph!) +- Fix browser system prompt inclusion rules (thanks @cannuri!) +- Publish git tags to GitHub from CI (thanks @pdecat!) +- Fixes to OpenAI-style cost calculations (thanks @dtrugman!) +- Fix to allow using an excluded directory as your working directory (thanks @Szpadel!) +- Kotlin language support in list_code_definition_names tool (thanks @kohii!) +- Better handling of diff application errors (thanks @qdaxb!) +- Update Bedrock prices to the latest (thanks @Smartsheet-JB-Brown!) +- Fixes to OpenRouter custom baseUrl support +- Fix usage tracking for SiliconFlow and other providers that include usage on every chunk +- Telemetry for checkpoint save/restore/diff and diff strategies + +## [3.8.4] - 2025-03-09 + +- Roll back multi-diff progress indicator temporarily to fix a double-confirmation in saving edits +- Add an option in the prompts tab to save tokens by disabling the ability to ask Roo to create/edit custom modes for you (thanks @hannesrudolph!) + +## [3.8.3] - 2025-03-09 + +- Fix VS Code LM API model picker truncation issue + +## [3.8.2] - 2025-03-08 + +- Create an auto-approval toggle for subtask creation and completion (thanks @shaybc!) +- Show a progress indicator when using the multi-diff editing strategy (thanks @qdaxb!) +- Add o3-mini support to the OpenAI-compatible provider (thanks @yt3trees!) +- Fix encoding issue where unreadable characters were sometimes getting added to the beginning of files +- Fix issue where settings dropdowns were getting truncated in some cases + +## [3.8.1] - 2025-03-07 + +- Show the reserved output tokens in the context window visualization +- Improve the UI of the configuration profile dropdown (thanks @DeXtroTip!) +- Fix bug where custom temperature could not be unchecked (thanks @System233!) +- Fix bug where decimal prices could not be entered for OpenAI-compatible providers (thanks @System233!) +- Fix bug with enhance prompt on Sonnet 3.7 with a high thinking budget (thanks @moqimoqidea!) +- Fix bug with the context window management for thinking models (thanks @ReadyPlayerEmma!) +- Fix bug where checkpoints were no longer enabled by default +- Add extension and VSCode versions to telemetry + +## [3.8.0] - 2025-03-07 + +- Add opt-in telemetry to help us improve Roo Code faster (thanks Cline!) +- Fix terminal overload / gray screen of death, and other terminal issues +- Add a new experimental diff editing strategy that applies multiple diff edits at once (thanks @qdaxb!) +- Add support for a .rooignore to prevent Roo Code from read/writing certain files, with a setting to also exclude them from search/lists (thanks Cline!) +- Update the new_task tool to return results to the parent task on completion, supporting better orchestration (thanks @shaybc!) +- Support running Roo in multiple editor windows simultaneously (thanks @samhvw8!) +- Make checkpoints asynchronous and exclude more files to speed them up +- Redesign the settings page to make it easier to navigate +- Add credential-based authentication for Vertex AI, enabling users to easily switch between Google Cloud accounts (thanks @eonghk!) +- Update the DeepSeek provider with the correct baseUrl and track caching correctly (thanks @olweraltuve!) +- Add a new “Human Relay” provider that allows you to manually copy information to a Web AI when needed, and then paste the AI's response back into Roo Code (thanks @NyxJae)! +- Add observability for OpenAI providers (thanks @refactorthis!) +- Support speculative decoding for LM Studio local models (thanks @adamwlarson!) +- Improve UI for mode/provider selectors in chat +- Improve styling of the task headers (thanks @monotykamary!) +- Improve context mention path handling on Windows (thanks @samhvw8!) + +## [3.7.12] - 2025-03-03 + +- Expand max tokens of thinking models to 128k, and max thinking budget to over 100k (thanks @monotykamary!) +- Fix issue where keyboard mode switcher wasn't updating API profile (thanks @aheizi!) +- Use the count_tokens API in the Anthropic provider for more accurate context window management +- Default middle-out compression to on for OpenRouter +- Exclude MCP instructions from the prompt if the mode doesn't support MCP +- Add a checkbox to disable the browser tool +- Show a warning if checkpoints are taking too long to load +- Update the warning text for the VS LM API +- Correctly populate the default OpenRouter model on the welcome screen + +## [3.7.11] - 2025-03-02 + +- Don't honor custom max tokens for non thinking models +- Include custom modes in mode switching keyboard shortcut +- Support read-only modes that can run commands + +## [3.7.10] - 2025-03-01 + +- Add Gemini models on Vertex AI (thanks @ashktn!) +- Keyboard shortcuts to switch modes (thanks @aheizi!) +- Add support for Mermaid diagrams (thanks Cline!) + +## [3.7.9] - 2025-03-01 + +- Delete task confirmation enhancements +- Smarter context window management +- Prettier thinking blocks +- Fix maxTokens defaults for Claude 3.7 Sonnet models +- Terminal output parsing improvements (thanks @KJ7LNW!) +- UI fix to dropdown hover colors (thanks @SamirSaji!) +- Add support for Claude Sonnet 3.7 thinking via Vertex AI (thanks @lupuletic!) + +## [3.7.8] - 2025-02-27 + +- Add Vertex AI prompt caching support for Claude models (thanks @aitoroses and @lupuletic!) +- Add gpt-4.5-preview +- Add an advanced feature to customize the system prompt + +## [3.7.7] - 2025-02-27 + +- Graduate checkpoints out of beta +- Fix enhance prompt button when using Thinking Sonnet +- Add tooltips to make what buttons do more obvious + +## [3.7.6] - 2025-02-26 + +- Handle really long text better in the ChatRow similar to TaskHeader (thanks @joemanley201!) +- Support multiple files in drag-and-drop +- Truncate search_file output to avoid crashing the extension +- Better OpenRouter error handling (no more "Provider Error") +- Add slider to control max output tokens for thinking models + +## [3.7.5] - 2025-02-26 + +- Fix context window truncation math (see [#1173](https://github.com/RooCodeInc/Roo-Code/issues/1173)) +- Fix various issues with the model picker (thanks @System233!) +- Fix model input / output cost parsing (thanks @System233!) +- Add drag-and-drop for files +- Enable the "Thinking Budget" slider for Claude 3.7 Sonnet on OpenRouter + +## [3.7.4] - 2025-02-25 + +- Fix a bug that prevented the "Thinking" setting from properly updating when switching profiles. + +## [3.7.3] - 2025-02-25 + +- Support for ["Thinking"](https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking) Sonnet 3.7 when using the Anthropic provider. + +## [3.7.2] - 2025-02-24 + +- Fix computer use and prompt caching for OpenRouter's `anthropic/claude-3.7-sonnet:beta` (thanks @cte!) +- Fix sliding window calculations for Sonnet 3.7 that were causing a context window overflow (thanks @cte!) +- Encourage diff editing more strongly in the system prompt (thanks @hannesrudolph!) + +## [3.7.1] - 2025-02-24 + +- Add Amazon Bedrock support for Sonnet 3.7 and update some defaults to Sonnet 3.7 instead of 3.5 + +## [3.7.0] - 2025-02-24 + +- Introducing Roo Code 3.7, with support for the new Claude Sonnet 3.7. Because who cares about skipping version numbers anymore? Thanks @lupuletic and @cte for the PRs! + +## [3.3.26] - 2025-02-27 + +- Adjust the default prompt for Debug mode to focus more on diagnosis and to require user confirmation before moving on to implementation + +## [3.3.25] - 2025-02-21 + +- Add a "Debug" mode that specializes in debugging tricky problems (thanks [Ted Werbel](https://x.com/tedx_ai/status/1891514191179309457) and [Carlos E. Perez](https://x.com/IntuitMachine/status/1891516362486337739)!) +- Add an experimental "Power Steering" option to significantly improve adherence to role definitions and custom instructions + +## [3.3.24] - 2025-02-20 + +- Fixed a bug with region selection preventing Amazon Bedrock profiles from being saved (thanks @oprstchn!) +- Updated the price of gpt-4o (thanks @marvijo-code!) + +## [3.3.23] - 2025-02-20 + +- Handle errors more gracefully when reading custom instructions from files (thanks @joemanley201!) +- Bug fix to hitting "Done" on settings page with unsaved changes (thanks @System233!) + +## [3.3.22] - 2025-02-20 + +- Improve the Provider Settings configuration with clear Save buttons and warnings about unsaved changes (thanks @System233!) +- Correctly parse `` reasoning tags from Ollama models (thanks @System233!) +- Add support for setting custom preferred languages on the Prompts tab, as well as adding Catalan to the list of languages (thanks @alarno!) +- Add a button to delete MCP servers (thanks @hannesrudolph!) +- Fix a bug where the button to copy the system prompt preview always copied the Code mode version +- Fix a bug where the .roomodes file was not automatically created when adding custom modes from the Prompts tab +- Allow setting a wildcard (`*`) to auto-approve all command execution (use with caution!) + +## [3.3.21] - 2025-02-17 + +- Fix input box revert issue and configuration loss during profile switch (thanks @System233!) +- Fix default preferred language for zh-cn and zh-tw (thanks @System233!) +- Fix Mistral integration (thanks @d-oit!) +- Feature to mention `@terminal` to pull terminal output into context (thanks Cline!) +- Fix system prompt to make sure Roo knows about all available modes +- Enable streaming mode for OpenAI o1 + +## [3.3.20] - 2025-02-14 + +- Support project-specific custom modes in a .roomodes file +- Add more Mistral models (thanks @d-oit and @bramburn!) +- By popular request, make it so Ask mode can't write to Markdown files and is purely for chatting with +- Add a setting to control the number of open editor tabs to tell the model about (665 is probably too many!) +- Fix race condition bug with entering API key on the welcome screen + +## [3.3.19] - 2025-02-12 + +- Fix a bug where aborting in the middle of file writes would not revert the write +- Honor the VS Code theme for dialog backgrounds +- Make it possible to clear out the default custom instructions for built-in modes +- Add a help button that links to our new documentation site (which we would love help from the community to improve!) +- Switch checkpoints logic to use a shadow git repository to work around issues with hot reloads and polluting existing repositories (thanks Cline for the inspiration!) + +## [3.3.18] - 2025-02-11 + +- Add a per-API-configuration model temperature setting (thanks @joemanley201!) +- Add retries for fetching usage stats from OpenRouter (thanks @jcbdev!) +- Fix bug where disabled MCP servers would not show up in the settings on initialization (thanks @MuriloFP!) +- Add the Requesty provider and clean up a lot of shared model picker code (thanks @samhvw8!) +- Add a button on the Prompts tab to copy the full system prompt to the clipboard (thanks @mamertofabian!) +- Fix issue where Ollama/LMStudio URLs would flicker back to previous while entering them in settings +- Fix logic error where automatic retries were waiting twice as long as intended +- Rework the checkpoints code to avoid conflicts with file locks on Windows (sorry for the hassle!) + +## [3.3.17] - 2025-02-09 + +- Fix the restore checkpoint popover +- Unset git config that was previously set incorrectly by the checkpoints feature + +## [3.3.16] - 2025-02-09 + +- Support Volcano Ark platform through the OpenAI-compatible provider +- Fix jumpiness while entering API config by updating on blur instead of input +- Add tooltips on checkpoint actions and fix an issue where checkpoints were overwriting existing git name/email settings - thanks for the feedback! + +## [3.3.15] - 2025-02-08 + +- Improvements to MCP initialization and server restarts (thanks @MuriloFP and @hannesrudolph!) +- Add a copy button to the recent tasks (thanks @hannesrudolph!) +- Improve the user experience for adding a new API profile +- Another significant fix to API profile switching on the settings screen +- Opt-in experimental version of checkpoints in the advanced settings + +## [3.3.14] + +- Should have skipped floor 13 like an elevator. This fixes the broken 3.3.13 release by reverting some changes to the deployment scripts. + +## [3.3.13] + +- Ensure the DeepSeek r1 model works with Ollama (thanks @sammcj!) +- Enable context menu commands in the terminal (thanks @samhvw8!) +- Improve sliding window truncation strategy for models that do not support prompt caching (thanks @nissa-seru!) +- First step of a more fundamental fix to the bugs around switching API profiles. If you've been having issues with this please try again and let us know if works any better! More to come soon, including fixing the laggy text entry in provider settings. + +## [3.3.12] + +- Bug fix to changing a mode's API configuration on the prompts tab +- Add new Gemini models + +## [3.3.11] + +- Safer shell profile path check to avoid an error on Windows +- Autocomplete for slash commands + +## [3.3.10] + +- Add shortcuts to the currently open tabs in the "Add File" section of @-mentions (thanks @olup!) +- Fix pricing for o1-mini (thanks @hesara!) +- Fix context window size calculation (thanks @MuriloFP!) +- Improvements to experimental unified diff strategy and selection logic in code actions (thanks @nissa-seru!) +- Enable markdown formatting in o3 and o1 (thanks @nissa-seru!) +- Improved terminal shell detection logic (thanks @canvrno for the original and @nissa-seru for the port!) +- Fix occasional errors when switching between API profiles (thanks @samhvw8!) +- Visual improvements to the list of modes on the prompts tab +- Fix double-scrollbar in provider dropdown +- Visual cleanup to the list of modes on the prompts tab +- Improvements to the default prompts for Architect and Ask mode +- Allow switching between modes with slash messages like `/ask why is the sky blue?` + +## [3.3.9] + +- Add o3-mini-high and o3-mini-low + +## [3.3.8] + +- Fix o3-mini in the Glama provider (thanks @Punkpeye!) +- Add the option to omit instructions for creating MCP servers from the system prompt (thanks @samhvw8!) +- Fix a bug where renaming API profiles without actually changing the name would delete them (thanks @samhvw8!) + +## [3.3.7] + +- Support for o3-mini (thanks @shpigunov!) +- Code Action improvements to allow selecting code and adding it to context, plus bug fixes (thanks @samhvw8!) +- Ability to include a message when approving or rejecting tool use (thanks @napter!) +- Improvements to chat input box styling (thanks @psv2522!) +- Capture reasoning from more variants of DeepSeek R1 (thanks @Szpadel!) +- Use an exponential backoff for API retries (if delay after first error is 5s, delay after second consecutive error will be 10s, then 20s, etc) +- Add a slider in advanced settings to enable rate limiting requests to avoid overloading providers (i.e. wait at least 10 seconds between API requests) +- Prompt tweaks to make Roo better at creating new custom modes for you + +## [3.3.6] + +- Add a "new task" tool that allows Roo to start new tasks with an initial message and mode +- Fix a bug that was preventing the use of qwen-max and potentially other OpenAI-compatible providers (thanks @Szpadel!) +- Add support for perplexity/sonar-reasoning (thanks @Szpadel!) +- Visual fixes to dropdowns (thanks @psv2522!) +- Add the [Unbound](https://getunbound.ai/) provider (thanks @vigneshsubbiah16!) + +## [3.3.5] + +- Make information about the conversation's context window usage visible in the task header for humans and in the environment for models (thanks @MuriloFP!) +- Add checkboxes to auto-approve mode switch requests (thanks @MuriloFP!) +- Add new experimental editing tools `insert_content` (for inserting blocks of text at a line number) and `search_and_replace` (for replacing all instances of a phrase or regex) to complement diff editing and whole file editing (thanks @samhvw8!) +- Improved DeepSeek R1 support by capturing reasoning from DeepSeek API as well as more OpenRouter variants, not using system messages, and fixing a crash on empty chunks. Still depends on the DeepSeek API staying up but we'll be in a better place when it does! (thanks @Szpadel!) + +## [3.3.4] + +- Add per-server MCP network timeout configuration ranging from 15 seconds to an hour +- Speed up diff editing (thanks @hannesrudolph and @KyleHerndon!) +- Add option to perform explain/improve/fix code actions either in the existing task or a new task (thanks @samhvw8!) + +## [3.3.3] + +- Throw errors sooner when a mode tries to write a restricted file +- Styling improvements to the mode/configuration dropdowns (thanks @psv2522!) + +## [3.3.2] + +- Add a dropdown to select the API configuration for a mode in the Prompts tab +- Fix bug where always allow wasn't showing up for MCP tools +- Improve OpenRouter DeepSeek-R1 integration by setting temperature to the recommended 0.6 and displaying the reasoning output (thanks @Szpadel - it's really fascinating to watch!) +- Allow specifying a custom OpenRouter base URL (thanks @dairui1!) +- Make the UI for nested settings nicer (thanks @PretzelVector!) + +## [3.3.1] + +- Fix issue where the terminal management system was creating unnecessary new terminals (thanks @evan-fannin!) +- Fix bug where the saved API provider for a mode wasn't being selected after a mode switch command + +## [3.3.0] + +- Native VS Code code actions support with quick fixes and refactoring options +- Modes can now request to switch to other modes when needed +- Ask and Architect modes can now edit markdown files +- Custom modes can now be restricted to specific file patterns (for example, a technical writer who can only edit markdown files 👋) +- Support for configuring the Bedrock provider with AWS Profiles +- New Roo Code community Discord at https://roocode.com/discord! + +## [3.2.8] + +- Fixed bug opening custom modes settings JSON +- Reverts provider key entry back to checking onInput instead of onChange to hopefully address issues entering API keys (thanks @samhvw8!) +- Added explicit checkbox to use Azure for OpenAI compatible providers (thanks @samhvw8!) +- Fixed Glama usage reporting (thanks @punkpeye!) +- Added Llama 3.3 70B Instruct model to the Amazon Bedrock provider options (thanks @Premshay!) + +## [3.2.7] + +- Fix bug creating new configuration profiles + +## [3.2.6] + +- Fix bug with role definition overrides for built-in modes + +## [3.2.5] + +- Added gemini flash thinking 01-21 model and a few visual fixes (thanks @monotykamary!) + +## [3.2.4] + +- Only allow use of the diff tool if it's enabled in settings + +## [3.2.3] + +- Fix bug where language selector wasn't working + +## [3.2.0 - 3.2.2] + +- **Name Change From Roo Cline to Roo Code:** We're excited to announce our new name! After growing beyond 50,000 installations, we've rebranded from Roo Cline to Roo Code to better reflect our identity as we chart our own course. + +- **Custom Modes:** Create your own personas for Roo Code! While our built-in modes (Code, Architect, Ask) are still here, you can now shape entirely new ones: + - Define custom prompts + - Choose which tools each mode can access + - Create specialized assistants for any workflow + - Just type "Create a new mode for " or visit the Prompts tab in the top menu to get started + +Join us at https://www.reddit.com/r/RooCode to share your custom modes and be part of our next chapter! + +## [3.1.7] + +- DeepSeek-R1 support (thanks @philipnext!) +- Experimental new unified diff algorithm can be enabled in settings (thanks @daniel-lxs!) +- More fixes to configuration profiles (thanks @samhvw8!) + +## [3.1.6] + +- Add Mistral (thanks Cline!) +- Fix bug with VSCode LM configuration profile saving (thanks @samhvw8!) + +## [3.1.4 - 3.1.5] + +- Bug fixes to the auto approve menu + +## [3.1.3] + +- Add auto-approve chat bar (thanks Cline!) +- Fix bug with VS Code Language Models integration + +## [3.1.2] + +- Experimental support for VS Code Language Models including Copilot (thanks @RaySinner / @julesmons!) +- Fix bug related to configuration profile switching (thanks @samhvw8!) +- Improvements to fuzzy search in mentions, history, and model lists (thanks @samhvw8!) +- PKCE support for Glama (thanks @punkpeye!) +- Use 'developer' message for o1 system prompt + +## [3.1.1] + +- Visual fixes to chat input and settings for the light+ themes + +## [3.1.0] + +- You can now customize the role definition and instructions for each chat mode (Code, Architect, and Ask), either through the new Prompts tab in the top menu or mode-specific .clinerules-mode files. Prompt Enhancements have also been revamped: the "Enhance Prompt" button now works with any provider and API configuration, giving you the ability to craft messages with fully customizable prompts for even better results. +- Add a button to copy markdown out of the chat + +## [3.0.3] + +- Update required vscode engine to ^1.84.0 to match cline + +## [3.0.2] + +- A couple more tiny tweaks to the button alignment in the chat input + +## [3.0.1] + +- Fix the reddit link and a small visual glitch in the chat input + +## [3.0.0] + +- This release adds chat modes! Now you can ask Roo Code questions about system architecture or the codebase without immediately jumping into writing code. You can even assign different API configuration profiles to each mode if you prefer to use different models for thinking vs coding. Would love feedback in the new Roo Code Reddit! https://www.reddit.com/r/RooCode + +## [2.2.46] + +- Only parse @-mentions in user input (not in files) + +## [2.2.45] + +- Save different API configurations to quickly switch between providers and settings (thanks @samhvw8!) + +## [2.2.44] + +- Automatically retry failed API requests with a configurable delay (thanks @RaySinner!) + +## [2.2.43] + +- Allow deleting single messages or all subsequent messages + +## [2.2.42] + +- Add a Git section to the context mentions + +## [2.2.41] + +- Checkbox to disable streaming for OpenAI-compatible providers + +## [2.2.40] + +- Add the Glama provider (thanks @punkpeye!) + +## [2.2.39] + +- Add toggle to enable/disable the MCP-related sections of the system prompt (thanks @daniel-lxs!) + +## [2.2.38] + +- Add a setting to control the number of terminal output lines to pass to the model when executing commands + +## [2.2.36 - 2.2.37] + +- Add a button to delete user messages + +## [2.2.35] + +- Allow selection of multiple browser viewport sizes and adjusting screenshot quality + +## [2.2.34] + +- Add the DeepSeek provider + +## [2.2.33] + +- "Enhance prompt" button (OpenRouter models only for now) +- Support listing models for OpenAI compatible providers (thanks @samhvw8!) + +## [2.2.32] + +- More efficient workspace tracker + +## [2.2.31] + +- Improved logic for auto-approving chained commands + +## [2.2.30] + +- Fix bug with auto-approving commands + +## [2.2.29] + +- Add configurable delay after auto-writes to allow diagnostics to catch up + +## [2.2.28] + +- Use createFileSystemWatcher to more reliably update list of files to @-mention + +## [2.2.27] + +- Add the current time to the system prompt and improve browser screenshot quality (thanks @libertyteeth!) + +## [2.2.26] + +- Tweaks to preferred language (thanks @yongjer) + +## [2.2.25] + +- Add a preferred language dropdown + +## [2.2.24] + +- Default diff editing to on for new installs + +## [2.2.23] + +- Fix context window for gemini-2.0-flash-thinking-exp-1219 (thanks @student20880) + +## [2.2.22] + +- Add gemini-2.0-flash-thinking-exp-1219 + +## [2.2.21] + +- Take predicted file length into account when detecting omissions + +## [2.2.20] + +- Make fuzzy diff matching configurable (and default to off) + +## [2.2.19] + +- Add experimental option to use a bigger browser (1280x800) + +## [2.2.18] + +- More targeted styling fix for Gemini chats + +## [2.2.17] + +- Improved regex for auto-execution of chained commands + +## [2.2.16] + +- Incorporate Premshay's [PR](https://github.com/RooCodeInc/Roo-Code/pull/60) to add support for Amazon Nova and Meta Llama Models via Bedrock (3, 3.1, 3.2) and unified Bedrock calls using BedrockClient and Bedrock Runtime API + +## [2.2.14 - 2.2.15] + +- Make diff editing more robust to transient errors / fix bugs + +## [2.2.13] + +- Fixes to sound playing and applying diffs + +## [2.2.12] + +- Better support for pure deletion and insertion diffs + +## [2.2.11] + +- Added settings checkbox for verbose diff debugging + +## [2.2.6 - 2.2.10] + +- More fixes to search/replace diffs + +## [2.2.5] + +- Allow MCP servers to be enabled/disabled + +## [2.2.4] + +- Tweak the prompt to encourage diff edits when they're enabled + +## [2.2.3] + +- Clean up the settings screen + +## [2.2.2] + +- Add checkboxes to auto-approve MCP tools + +## [2.2.1] + +- Fix another diff editing indentation bug + +## [2.2.0] + +- Incorporate MCP changes from Cline 2.2.0 + +## [2.1.21] + +- Larger text area input + ability to drag images into it + +## [2.1.20] + +- Add Gemini 2.0 + +## [2.1.19] + +- Better error handling for diff editing + +## [2.1.18] + +- Diff editing bugfix to handle Windows line endings + +## [2.1.17] + +- Switch to search/replace diffs in experimental diff editing mode + +## [2.1.16] + +- Allow copying prompts from the history screen + +## [2.1.15] + +- Incorporate dbasclpy's [PR](https://github.com/RooCodeInc/Roo-Code/pull/54) to add support for gemini-exp-1206 +- Make it clear that diff editing is very experimental + +## [2.1.14] + +- Fix bug where diffs were not being applied correctly and try Aider's [unified diff prompt](https://github.com/Aider-AI/aider/blob/3995accd0ca71cea90ef76d516837f8c2731b9fe/aider/coders/udiff_prompts.py#L75-L105) +- If diffs are enabled, automatically reject write_to_file commands that lead to truncated output + +## [2.1.13] + +- Fix https://github.com/RooCodeInc/Roo-Code/issues/50 where sound effects were not respecting settings + +## [2.1.12] + +- Incorporate JoziGila's [PR](https://github.com/cline/cline/pull/158) to add support for editing through diffs + +## [2.1.11] + +- Incorporate lloydchang's [PR](https://github.com/RooCodeInc/Roo-Code/pull/42) to add support for OpenRouter compression + +## [2.1.10] + +- Incorporate HeavenOSK's [PR](https://github.com/cline/cline/pull/818) to add sound effects to Cline + +## [2.1.9] + +- Add instructions for using .clinerules on the settings screen + +## [2.1.8] + +- Roo Cline now allows configuration of which commands are allowed without approval! + +## [2.1.7] + +- Updated extension icon and metadata + +## [2.2.0] + +- Add support for Model Context Protocol (MCP), enabling Cline to use custom tools like web-search tool or GitHub tool +- Add MCP server management tab accessible via the server icon in the menu bar +- Add ability for Cline to dynamically create new MCP servers based on user requests (e.g., "add a tool that gets the latest npm docs") + +## [2.1.6] + +- Roo Cline now runs in all VSCode-compatible editors + +## [2.1.5] + +- Fix bug in browser action approval + +## [2.1.4] + +- Roo Cline now can run side-by-side with Cline + +## [2.1.3] + +- Roo Cline now allows browser actions without approval when `alwaysAllowBrowser` is true + +## [2.1.2] + +- Support for auto-approval of write operations and command execution +- Support for .clinerules custom instructions diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 2263257cd6..20ff599a35 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -272,7 +272,7 @@ export class ClineProvider public isViewLaunched = false public settingsImportedAt?: number - public readonly latestAnnouncementId = "aug-2026-v3.76.0-dcg-providers-terminal" // v3.76.0 destructive command guard, provider improvements, and terminal execution fix + public readonly latestAnnouncementId = "aug-2026-v3.78.0-models-nanogpt-reliability" // v3.78.0 new models, NanoGPT, and provider/task reliability public readonly providerSettingsManager: ProviderSettingsManager public readonly customModesManager: CustomModesManager diff --git a/src/package.json b/src/package.json index 9be6390cbc..180e3f7e2e 100644 --- a/src/package.json +++ b/src/package.json @@ -3,7 +3,7 @@ "displayName": "%extension.displayName%", "description": "%extension.description%", "publisher": "ZooCodeOrganization", - "version": "3.76.0", + "version": "3.78.0", "icon": "assets/icons/icon.png", "galleryBanner": { "color": "#617A91", diff --git a/webview-ui/src/components/chat/__tests__/Announcement.spec.tsx b/webview-ui/src/components/chat/__tests__/Announcement.spec.tsx index b99ff02ea1..170f2e8b6a 100644 --- a/webview-ui/src/components/chat/__tests__/Announcement.spec.tsx +++ b/webview-ui/src/components/chat/__tests__/Announcement.spec.tsx @@ -13,7 +13,7 @@ vi.mock("@src/utils/vscode", () => ({ vi.mock("@roo/package", () => ({ Package: { - version: "3.74.0", + version: "3.78.0", }, })) @@ -41,11 +41,11 @@ vi.mock("@src/i18n/TranslationContext", () => ({ const translations: Record = { "chat:announcement.release.heading": "What's New:", "chat:announcement.release.highlight1": - "More OpenAI controls — use Fast priority mode with OpenAI Codex and choose higher reasoning effort for OpenAI-compatible models.", + "Three major new models have arrived — use the brand-new Gemini 3.7 Flash, GLM 5.3, and Qwen3.8 Max models, plus updated DeepSeek V4 reasoning, pricing, and provider coverage.", "chat:announcement.release.highlight2": - "More reliable providers and models — improved router metadata handling, Ollama model refresh, Bedrock proxy support, and Friendli reasoning controls.", + "Connect to NanoGPT — use dynamic model discovery, streaming and prompt completions, and routing preferences for speed, price, latency, throughput, tool support, and caching.", "chat:announcement.release.highlight3": - "Smoother settings and developer workflows — settings now preserve unsaved edits, short terminal commands complete cleanly, architect plans use workspace-relative paths, and remaining user-facing Roo branding is updated to Zoo.", + "More reliable providers and tasks — fixes improve Azure OpenAI endpoint setup, Kimi Code output limits, task-history title preservation, and Zoo settings import/export.", "chat:announcement.handoff.heading": "The Roo Code plugin is not going away.", } @@ -62,20 +62,20 @@ describe("Announcement", () => { it("renders the announcement title and highlights", () => { render() - expect(screen.getByText("Zoo Code 3.74.0 Released")).toBeInTheDocument() + expect(screen.getByText("Zoo Code 3.78.0 Released")).toBeInTheDocument() expect( screen.getByText( - "More OpenAI controls — use Fast priority mode with OpenAI Codex and choose higher reasoning effort for OpenAI-compatible models.", + "Three major new models have arrived — use the brand-new Gemini 3.7 Flash, GLM 5.3, and Qwen3.8 Max models, plus updated DeepSeek V4 reasoning, pricing, and provider coverage.", ), ).toBeInTheDocument() expect( screen.getByText( - "More reliable providers and models — improved router metadata handling, Ollama model refresh, Bedrock proxy support, and Friendli reasoning controls.", + "Connect to NanoGPT — use dynamic model discovery, streaming and prompt completions, and routing preferences for speed, price, latency, throughput, tool support, and caching.", ), ).toBeInTheDocument() expect( screen.getByText( - "Smoother settings and developer workflows — settings now preserve unsaved edits, short terminal commands complete cleanly, architect plans use workspace-relative paths, and remaining user-facing Roo branding is updated to Zoo.", + "More reliable providers and tasks — fixes improve Azure OpenAI endpoint setup, Kimi Code output limits, task-history title preservation, and Zoo settings import/export.", ), ).toBeInTheDocument() }) diff --git a/webview-ui/src/i18n/locales/ca/chat.json b/webview-ui/src/i18n/locales/ca/chat.json index 79e665951c..d5b63ea886 100644 --- a/webview-ui/src/i18n/locales/ca/chat.json +++ b/webview-ui/src/i18n/locales/ca/chat.json @@ -344,9 +344,9 @@ "support": "Dona suport a Zoo Code fent-nos una estrella a GitHub.", "release": { "heading": "Novetats:", - "highlight1": "Executa tasques més llargues i sense interrupcions amb Destructive Command Guard (DCG) — DCG bloqueja les ordres perilloses mentre permet que Zoo continuï treballant sense que hagis de prémer contínuament els botons d'aprovació.", - "highlight2": "Millors controls i fiabilitat dels proveïdors — tria la velocitat de resposta d'OpenAI Codex, utilitza configuracions de DeepSeek actualitzades i mantén les tasques en execució aïllades dels canvis de perfil.", - "highlight3": "Correcció crítica de l'execució al terminal — Zoo ara espera que les ordres del terminal acabin abans d'iniciar el pas següent." + "highlight1": "Han arribat tres grans models nous — utilitza els nous Gemini 3.7 Flash, GLM 5.3 i Qwen3.8 Max, a més de millores en el raonament, els preus i la cobertura de proveïdors de DeepSeek V4.", + "highlight2": "Connecta't a NanoGPT — utilitza el descobriment dinàmic de models, streaming i completions de prompts, i preferències d'encaminament per velocitat, preu, latència, rendiment, compatibilitat amb eines i memòria cau.", + "highlight3": "Proveïdors i tasques més fiables — les correccions milloren la configuració dels endpoints d'Azure OpenAI, els límits de sortida de Kimi Code, la conservació dels títols de l'historial de tasques i la importació/exportació de configuració de Zoo." }, "cloudAgents": { "heading": "Novetats al núvol:", diff --git a/webview-ui/src/i18n/locales/de/chat.json b/webview-ui/src/i18n/locales/de/chat.json index 95dda79659..ad94856234 100644 --- a/webview-ui/src/i18n/locales/de/chat.json +++ b/webview-ui/src/i18n/locales/de/chat.json @@ -344,9 +344,9 @@ "support": "Bitte unterstütze Zoo Code, indem du uns auf GitHub einen Stern gibst.", "release": { "heading": "Was ist neu:", - "highlight1": "Führe mit Destructive Command Guard (DCG) längere Aufgaben ohne Unterbrechung aus — DCG blockiert gefährliche Befehle, während Zoo weiterarbeitet, ohne dass du ständig Freigabeschaltflächen drücken musst.", - "highlight2": "Bessere Anbietersteuerung und Zuverlässigkeit — wähle die Antwortgeschwindigkeit von OpenAI Codex, nutze aktualisierte DeepSeek-Konfigurationen und halte laufende Aufgaben von Profiländerungen isoliert.", - "highlight3": "Kritische Fehlerbehebung bei der Terminalausführung — Zoo wartet jetzt, bis Terminalbefehle beendet sind, bevor der nächste Schritt beginnt." + "highlight1": "Drei bedeutende neue Modelle sind da — nutze die brandneuen Modelle Gemini 3.7 Flash, GLM 5.3 und Qwen3.8 Max sowie aktualisiertes Reasoning, Preise und Anbieterabdeckung für DeepSeek V4.", + "highlight2": "Verbinde dich mit NanoGPT — nutze dynamische Modellerkennung, Streaming und Prompt-Vervollständigung sowie Routing-Einstellungen für Geschwindigkeit, Preis, Latenz, Durchsatz, Tool-Unterstützung und Caching.", + "highlight3": "Zuverlässigere Anbieter und Aufgaben — Korrekturen verbessern die Einrichtung von Azure-OpenAI-Endpunkten, Kimi-Code-Ausgabelimits, die Beibehaltung von Titeln im Aufgabenverlauf sowie den Import und Export von Zoo-Einstellungen." }, "cloudAgents": { "heading": "Neu in der Cloud:", diff --git a/webview-ui/src/i18n/locales/en/chat.json b/webview-ui/src/i18n/locales/en/chat.json index e1cfa96066..89f6c2f488 100644 --- a/webview-ui/src/i18n/locales/en/chat.json +++ b/webview-ui/src/i18n/locales/en/chat.json @@ -363,9 +363,9 @@ "support": "Please support Zoo Code by starring us on GitHub.", "release": { "heading": "What's New:", - "highlight1": "Run longer, uninterrupted tasks with Destructive Command Guard (DCG) — DCG blocks dangerous commands while letting Zoo keep working without you continuously pressing approval buttons.", - "highlight2": "Better provider controls and reliability — choose OpenAI Codex response speed, use updated DeepSeek configurations, and keep running tasks isolated from profile changes.", - "highlight3": "Critical terminal execution fix — Zoo now waits for terminal commands to finish before starting the next step." + "highlight1": "Three major new models have arrived — use the brand-new Gemini 3.7 Flash, GLM 5.3, and Qwen3.8 Max models, plus updated DeepSeek V4 reasoning, pricing, and provider coverage.", + "highlight2": "Connect to NanoGPT — use dynamic model discovery, streaming and prompt completions, and routing preferences for speed, price, latency, throughput, tool support, and caching.", + "highlight3": "More reliable providers and tasks — fixes improve Azure OpenAI endpoint setup, Kimi Code output limits, task-history title preservation, and Zoo settings import/export." }, "cloudAgents": { "heading": "New in the Cloud:", diff --git a/webview-ui/src/i18n/locales/es/chat.json b/webview-ui/src/i18n/locales/es/chat.json index 593628823c..7876845932 100644 --- a/webview-ui/src/i18n/locales/es/chat.json +++ b/webview-ui/src/i18n/locales/es/chat.json @@ -344,9 +344,9 @@ "support": "Apoya a Zoo Code dándonos una estrella en GitHub.", "release": { "heading": "Novedades:", - "highlight1": "Ejecuta tareas más largas y sin interrupciones con Destructive Command Guard (DCG) — DCG bloquea comandos peligrosos mientras permite que Zoo siga trabajando sin que tengas que pulsar continuamente los botones de aprobación.", - "highlight2": "Mejores controles y fiabilidad de proveedores — elige la velocidad de respuesta de OpenAI Codex, usa configuraciones actualizadas de DeepSeek y mantén las tareas en ejecución aisladas de los cambios de perfil.", - "highlight3": "Corrección crítica de ejecución en terminal — Zoo ahora espera a que terminen los comandos del terminal antes de iniciar el siguiente paso." + "highlight1": "Han llegado tres importantes modelos nuevos — usa los flamantes Gemini 3.7 Flash, GLM 5.3 y Qwen3.8 Max, además de mejoras en el razonamiento, los precios y la cobertura de proveedores de DeepSeek V4.", + "highlight2": "Conéctate a NanoGPT — usa descubrimiento dinámico de modelos, streaming y completado de prompts, y preferencias de enrutamiento por velocidad, precio, latencia, rendimiento, compatibilidad con herramientas y caché.", + "highlight3": "Proveedores y tareas más fiables — las correcciones mejoran la configuración de endpoints de Azure OpenAI, los límites de salida de Kimi Code, la conservación de títulos del historial de tareas y la importación/exportación de ajustes de Zoo." }, "cloudAgents": { "heading": "Novedades en la Nube:", diff --git a/webview-ui/src/i18n/locales/fr/chat.json b/webview-ui/src/i18n/locales/fr/chat.json index f23c3b064d..032d43ce27 100644 --- a/webview-ui/src/i18n/locales/fr/chat.json +++ b/webview-ui/src/i18n/locales/fr/chat.json @@ -344,9 +344,9 @@ "support": "Soutiens Zoo Code en nous donnant une étoile sur GitHub.", "release": { "heading": "Nouveautés :", - "highlight1": "Exécute des tâches plus longues sans interruption avec Destructive Command Guard (DCG) — DCG bloque les commandes dangereuses tout en laissant Zoo travailler sans que tu aies à appuyer continuellement sur les boutons d'approbation.", - "highlight2": "Meilleurs contrôles et fiabilité des providers — choisis la vitesse de réponse d'OpenAI Codex, utilise les configurations DeepSeek mises à jour et isole les tâches en cours des changements de profil.", - "highlight3": "Correction critique de l'exécution dans le terminal — Zoo attend désormais la fin des commandes du terminal avant de commencer l'étape suivante." + "highlight1": "Trois nouveaux modèles majeurs sont arrivés — utilise les tout nouveaux Gemini 3.7 Flash, GLM 5.3 et Qwen3.8 Max, ainsi que les améliorations du raisonnement, des tarifs et de la couverture des providers de DeepSeek V4.", + "highlight2": "Connecte-toi à NanoGPT — profite de la découverte dynamique des modèles, du streaming et de la complétion des prompts, avec des préférences de routage pour la vitesse, le prix, la latence, le débit, la prise en charge des outils et le cache.", + "highlight3": "Providers et tâches plus fiables — les correctifs améliorent la configuration des endpoints Azure OpenAI, les limites de sortie de Kimi Code, la conservation des titres dans l'historique des tâches et l'import/export des paramètres Zoo." }, "cloudAgents": { "heading": "Nouveautés dans le Cloud :", diff --git a/webview-ui/src/i18n/locales/hi/chat.json b/webview-ui/src/i18n/locales/hi/chat.json index 7cb593af63..94a805f328 100644 --- a/webview-ui/src/i18n/locales/hi/chat.json +++ b/webview-ui/src/i18n/locales/hi/chat.json @@ -344,9 +344,9 @@ "support": "कृपया GitHub पर हमें स्टार देकर Zoo Code का समर्थन करें।", "release": { "heading": "नया क्या है:", - "highlight1": "Destructive Command Guard (DCG) के साथ लंबे, बिना रुकावट वाले tasks चलाएँ — DCG खतरनाक commands को block करता है और Zoo को लगातार approval buttons दबाए बिना काम करते रहने देता है।", - "highlight2": "बेहतर provider controls और reliability — OpenAI Codex response speed चुनें, updated DeepSeek configurations उपयोग करें और चल रहे tasks को profile changes से अलग रखें।", - "highlight3": "Critical terminal execution fix — Zoo अब अगला step शुरू करने से पहले terminal commands के पूरा होने का इंतज़ार करता है।" + "highlight1": "तीन बड़े नए models आ गए हैं — बिल्कुल नए Gemini 3.7 Flash, GLM 5.3 और Qwen3.8 Max models का उपयोग करें, साथ ही DeepSeek V4 के updated reasoning, pricing और provider coverage का लाभ लें।", + "highlight2": "NanoGPT से connect करें — dynamic model discovery, streaming और prompt completions के साथ speed, price, latency, throughput, tool support और caching के लिए routing preferences का उपयोग करें।", + "highlight3": "अधिक reliable providers और tasks — fixes Azure OpenAI endpoint setup, Kimi Code output limits, task-history title preservation और Zoo settings import/export को बेहतर बनाते हैं।" }, "cloudAgents": { "heading": "क्लाउड में नया:", diff --git a/webview-ui/src/i18n/locales/id/chat.json b/webview-ui/src/i18n/locales/id/chat.json index 5d0ebfec30..d58d80db00 100644 --- a/webview-ui/src/i18n/locales/id/chat.json +++ b/webview-ui/src/i18n/locales/id/chat.json @@ -373,9 +373,9 @@ "support": "Dukung Zoo Code dengan memberi kami bintang di GitHub.", "release": { "heading": "Yang Baru:", - "highlight1": "Jalankan task yang lebih lama tanpa gangguan dengan Destructive Command Guard (DCG) — DCG memblokir perintah berbahaya sambil membiarkan Zoo terus bekerja tanpa kamu terus-menerus menekan tombol persetujuan.", - "highlight2": "Kontrol dan keandalan provider yang lebih baik — pilih kecepatan respons OpenAI Codex, gunakan konfigurasi DeepSeek terbaru, dan pisahkan task yang sedang berjalan dari perubahan profil.", - "highlight3": "Perbaikan penting eksekusi terminal — Zoo kini menunggu perintah terminal selesai sebelum memulai langkah berikutnya." + "highlight1": "Tiga model baru utama telah hadir — gunakan model terbaru Gemini 3.7 Flash, GLM 5.3, dan Qwen3.8 Max, ditambah pembaruan reasoning, harga, dan cakupan provider DeepSeek V4.", + "highlight2": "Hubungkan ke NanoGPT — gunakan penemuan model dinamis, streaming dan penyelesaian prompt, serta preferensi routing untuk kecepatan, harga, latensi, throughput, dukungan tool, dan caching.", + "highlight3": "Provider dan task yang lebih andal — perbaikan meningkatkan pengaturan endpoint Azure OpenAI, batas output Kimi Code, penyimpanan judul riwayat task, serta impor/ekspor pengaturan Zoo." }, "cloudAgents": { "heading": "Baru di Cloud:", diff --git a/webview-ui/src/i18n/locales/it/chat.json b/webview-ui/src/i18n/locales/it/chat.json index 417ac8b427..7c4c657b35 100644 --- a/webview-ui/src/i18n/locales/it/chat.json +++ b/webview-ui/src/i18n/locales/it/chat.json @@ -344,9 +344,9 @@ "support": "Sostieni Zoo Code lasciandoci una stella su GitHub.", "release": { "heading": "Novità:", - "highlight1": "Esegui task più lunghi e senza interruzioni con Destructive Command Guard (DCG) — DCG blocca i comandi pericolosi lasciando che Zoo continui a lavorare senza dover premere continuamente i pulsanti di approvazione.", - "highlight2": "Controlli e affidabilità dei provider migliorati — scegli la velocità di risposta di OpenAI Codex, usa configurazioni DeepSeek aggiornate e mantieni i task in esecuzione isolati dalle modifiche ai profili.", - "highlight3": "Correzione critica dell'esecuzione nel terminale — Zoo ora attende il completamento dei comandi del terminale prima di iniziare il passaggio successivo." + "highlight1": "Sono arrivati tre importanti nuovi modelli — usa i nuovissimi Gemini 3.7 Flash, GLM 5.3 e Qwen3.8 Max, oltre agli aggiornamenti di reasoning, prezzi e copertura dei provider per DeepSeek V4.", + "highlight2": "Connettiti a NanoGPT — usa la scoperta dinamica dei modelli, streaming e completamenti dei prompt, con preferenze di routing per velocità, prezzo, latenza, throughput, supporto agli strumenti e caching.", + "highlight3": "Provider e task più affidabili — le correzioni migliorano la configurazione degli endpoint Azure OpenAI, i limiti di output di Kimi Code, la conservazione dei titoli nella cronologia dei task e l'importazione/esportazione delle impostazioni Zoo." }, "cloudAgents": { "heading": "Novità nel Cloud:", diff --git a/webview-ui/src/i18n/locales/ja/chat.json b/webview-ui/src/i18n/locales/ja/chat.json index 6888e2ae65..f2f17b3fa5 100644 --- a/webview-ui/src/i18n/locales/ja/chat.json +++ b/webview-ui/src/i18n/locales/ja/chat.json @@ -344,9 +344,9 @@ "support": "GitHubでスターを付けて Zoo Code を応援してください。", "release": { "heading": "新機能:", - "highlight1": "Destructive Command Guard(DCG)で長時間のタスクを中断なく実行 — DCG が危険なコマンドをブロックするため、承認ボタンを何度も押さなくても Zoo が作業を続けられます。", - "highlight2": "プロバイダーの制御と信頼性を向上 — OpenAI Codex の応答速度を選択し、更新された DeepSeek 設定を使用しながら、実行中のタスクをプロファイル変更から分離できます。", - "highlight3": "ターミナル実行の重大な問題を修正 — Zoo はターミナルコマンドの完了を待ってから次のステップを開始するようになりました。" + "highlight1": "注目の新モデルが3つ登場 — 最新の Gemini 3.7 Flash、GLM 5.3、Qwen3.8 Max に加え、DeepSeek V4 の reasoning、価格、プロバイダー対応も更新されました。", + "highlight2": "NanoGPT に接続 — 動的なモデル検出、ストリーミング、Prompt 補完に加え、速度、価格、レイテンシ、スループット、ツール対応、キャッシュに基づくルーティング設定を利用できます。", + "highlight3": "プロバイダーとタスクの信頼性を向上 — Azure OpenAI エンドポイント設定、Kimi Code の出力上限、タスク履歴タイトルの保持、Zoo 設定のインポート/エクスポートを改善しました。" }, "cloudAgents": { "heading": "クラウドの新機能:", diff --git a/webview-ui/src/i18n/locales/ko/chat.json b/webview-ui/src/i18n/locales/ko/chat.json index 9ba870a8df..090bb1a706 100644 --- a/webview-ui/src/i18n/locales/ko/chat.json +++ b/webview-ui/src/i18n/locales/ko/chat.json @@ -344,9 +344,9 @@ "support": "GitHub에서 별표를 눌러 Zoo Code를 응원해 주세요.", "release": { "heading": "새로운 기능:", - "highlight1": "Destructive Command Guard(DCG)로 더 긴 task를 중단 없이 실행하세요 — DCG가 위험한 명령을 차단하므로 승인 버튼을 계속 누르지 않아도 Zoo가 작업을 이어갈 수 있습니다.", - "highlight2": "향상된 provider 제어와 안정성 — OpenAI Codex 응답 속도를 선택하고, 업데이트된 DeepSeek 구성을 사용하며, 실행 중인 task를 프로필 변경과 격리할 수 있습니다.", - "highlight3": "중요한 터미널 실행 문제 수정 — 이제 Zoo는 터미널 명령이 끝날 때까지 기다린 후 다음 단계를 시작합니다." + "highlight1": "주요 신규 모델 3종이 출시되었습니다 — 완전히 새로운 Gemini 3.7 Flash, GLM 5.3, Qwen3.8 Max 모델과 업데이트된 DeepSeek V4 reasoning, 가격 및 provider 지원을 사용해 보세요.", + "highlight2": "NanoGPT에 연결하세요 — 동적 모델 검색, 스트리밍 및 prompt completion과 함께 속도, 가격, 지연 시간, 처리량, 도구 지원, 캐싱을 기준으로 한 라우팅 설정을 사용할 수 있습니다.", + "highlight3": "더 안정적인 provider와 task — Azure OpenAI endpoint 설정, Kimi Code 출력 제한, task 기록 제목 보존, Zoo 설정 가져오기/내보내기가 개선되었습니다." }, "cloudAgents": { "heading": "클라우드의 새로운 기능:", diff --git a/webview-ui/src/i18n/locales/nl/chat.json b/webview-ui/src/i18n/locales/nl/chat.json index 4c4c3ff40e..0f1ce14084 100644 --- a/webview-ui/src/i18n/locales/nl/chat.json +++ b/webview-ui/src/i18n/locales/nl/chat.json @@ -317,9 +317,9 @@ "support": "Steun Zoo Code door ons een ster te geven op GitHub.", "release": { "heading": "Wat is nieuw:", - "highlight1": "Voer langere taken zonder onderbreking uit met Destructive Command Guard (DCG) — DCG blokkeert gevaarlijke opdrachten terwijl Zoo doorwerkt zonder dat je voortdurend op goedkeuringsknoppen hoeft te drukken.", - "highlight2": "Betere providerbediening en betrouwbaarheid — kies de reactiesnelheid van OpenAI Codex, gebruik bijgewerkte DeepSeek-configuraties en houd actieve taken geïsoleerd van profielwijzigingen.", - "highlight3": "Kritieke oplossing voor terminaluitvoering — Zoo wacht nu tot terminalopdrachten klaar zijn voordat de volgende stap begint." + "highlight1": "Drie belangrijke nieuwe modellen zijn gearriveerd — gebruik de gloednieuwe Gemini 3.7 Flash-, GLM 5.3- en Qwen3.8 Max-modellen, plus bijgewerkte reasoning, prijzen en providerondersteuning voor DeepSeek V4.", + "highlight2": "Maak verbinding met NanoGPT — gebruik dynamische modeldetectie, streaming en promptaanvulling, plus routeringsvoorkeuren voor snelheid, prijs, latentie, doorvoer, toolondersteuning en caching.", + "highlight3": "Betrouwbaardere providers en taken — oplossingen verbeteren de instelling van Azure OpenAI-endpoints, Kimi Code-uitvoerlimieten, het behouden van titels in de taakgeschiedenis en het importeren/exporteren van Zoo-instellingen." }, "cloudAgents": { "heading": "Nieuw in de Cloud:", diff --git a/webview-ui/src/i18n/locales/pl/chat.json b/webview-ui/src/i18n/locales/pl/chat.json index c673f86d9a..53ae2013e1 100644 --- a/webview-ui/src/i18n/locales/pl/chat.json +++ b/webview-ui/src/i18n/locales/pl/chat.json @@ -344,9 +344,9 @@ "support": "Wesprzyj Zoo Code, dając nam gwiazdkę na GitHub.", "release": { "heading": "Co nowego:", - "highlight1": "Uruchamiaj dłuższe zadania bez przerw dzięki Destructive Command Guard (DCG) — DCG blokuje niebezpieczne polecenia, a Zoo może dalej pracować bez ciągłego naciskania przycisków zatwierdzania.", - "highlight2": "Lepsze sterowanie providerami i niezawodność — wybieraj szybkość odpowiedzi OpenAI Codex, korzystaj ze zaktualizowanych konfiguracji DeepSeek i izoluj uruchomione zadania od zmian profilu.", - "highlight3": "Krytyczna poprawka wykonywania poleceń w terminalu — Zoo czeka teraz na zakończenie poleceń terminala przed rozpoczęciem następnego kroku." + "highlight1": "Pojawiły się trzy ważne nowe modele — korzystaj z zupełnie nowych Gemini 3.7 Flash, GLM 5.3 i Qwen3.8 Max oraz zaktualizowanego reasoning, cen i obsługi providerów dla DeepSeek V4.", + "highlight2": "Połącz się z NanoGPT — korzystaj z dynamicznego wykrywania modeli, streamingu i uzupełniania promptów oraz preferencji routingu według szybkości, ceny, opóźnienia, przepustowości, obsługi narzędzi i cache.", + "highlight3": "Bardziej niezawodni providerzy i zadania — poprawki usprawniają konfigurację endpointów Azure OpenAI, limity wyjścia Kimi Code, zachowywanie tytułów historii zadań oraz import/eksport ustawień Zoo." }, "cloudAgents": { "heading": "Nowości w chmurze:", diff --git a/webview-ui/src/i18n/locales/pt-BR/chat.json b/webview-ui/src/i18n/locales/pt-BR/chat.json index 5de714b00a..4769341a7b 100644 --- a/webview-ui/src/i18n/locales/pt-BR/chat.json +++ b/webview-ui/src/i18n/locales/pt-BR/chat.json @@ -344,9 +344,9 @@ "support": "Apoie o Zoo Code nos dando uma estrela no GitHub.", "release": { "heading": "Novidades:", - "highlight1": "Execute tarefas mais longas e sem interrupções com o Destructive Command Guard (DCG) — o DCG bloqueia comandos perigosos enquanto permite que o Zoo continue trabalhando sem você precisar apertar continuamente os botões de aprovação.", - "highlight2": "Melhores controles e confiabilidade dos providers — escolha a velocidade de resposta do OpenAI Codex, use configurações atualizadas do DeepSeek e mantenha tarefas em execução isoladas de alterações de perfil.", - "highlight3": "Correção crítica da execução no terminal — agora o Zoo espera os comandos do terminal terminarem antes de iniciar a próxima etapa." + "highlight1": "Três novos modelos importantes chegaram — use os novíssimos Gemini 3.7 Flash, GLM 5.3 e Qwen3.8 Max, além das atualizações de reasoning, preços e cobertura de providers do DeepSeek V4.", + "highlight2": "Conecte-se ao NanoGPT — use descoberta dinâmica de modelos, streaming e conclusão de prompts, com preferências de roteamento por velocidade, preço, latência, throughput, suporte a ferramentas e cache.", + "highlight3": "Providers e tarefas mais confiáveis — as correções melhoram a configuração de endpoints do Azure OpenAI, os limites de saída do Kimi Code, a preservação de títulos no histórico de tarefas e a importação/exportação das configurações do Zoo." }, "cloudAgents": { "heading": "Novidades na Nuvem:", diff --git a/webview-ui/src/i18n/locales/ru/chat.json b/webview-ui/src/i18n/locales/ru/chat.json index 180b8243ac..de34a0e0b8 100644 --- a/webview-ui/src/i18n/locales/ru/chat.json +++ b/webview-ui/src/i18n/locales/ru/chat.json @@ -318,9 +318,9 @@ "support": "Поддержите Zoo Code, поставив нам звезду на GitHub.", "release": { "heading": "Что нового:", - "highlight1": "Выполняйте длительные задачи без перерывов с Destructive Command Guard (DCG) — DCG блокирует опасные команды, а Zoo продолжает работать без необходимости постоянно нажимать кнопки подтверждения.", - "highlight2": "Улучшенное управление провайдерами и надёжность — выбирайте скорость ответа OpenAI Codex, используйте обновлённые конфигурации DeepSeek и изолируйте выполняемые задачи от изменений профиля.", - "highlight3": "Критическое исправление выполнения команд в терминале — теперь Zoo ждёт завершения команд терминала перед началом следующего шага." + "highlight1": "Появились три важных новых модели — используйте совершенно новые Gemini 3.7 Flash, GLM 5.3 и Qwen3.8 Max, а также обновлённые reasoning, цены и поддержку провайдеров для DeepSeek V4.", + "highlight2": "Подключайтесь к NanoGPT — используйте динамическое обнаружение моделей, streaming и дополнение Prompt, а также настройки маршрутизации по скорости, цене, задержке, пропускной способности, поддержке инструментов и кешированию.", + "highlight3": "Более надёжные провайдеры и задачи — исправления улучшают настройку endpoint Azure OpenAI, лимиты вывода Kimi Code, сохранение заголовков истории задач и импорт/экспорт настроек Zoo." }, "cloudAgents": { "heading": "Новое в облаке:", diff --git a/webview-ui/src/i18n/locales/tr/chat.json b/webview-ui/src/i18n/locales/tr/chat.json index 02cff682c4..752e5bff9f 100644 --- a/webview-ui/src/i18n/locales/tr/chat.json +++ b/webview-ui/src/i18n/locales/tr/chat.json @@ -345,9 +345,9 @@ "support": "Lütfen GitHub'da bize yıldız vererek Zoo Code'u destekle.", "release": { "heading": "Yenilikler:", - "highlight1": "Destructive Command Guard (DCG) ile daha uzun görevleri kesintisiz çalıştır — DCG tehlikeli komutları engellerken Zoo'nun sürekli onay düğmelerine basmana gerek kalmadan çalışmasını sağlar.", - "highlight2": "Daha iyi provider denetimleri ve güvenilirlik — OpenAI Codex yanıt hızını seç, güncellenmiş DeepSeek yapılandırmalarını kullan ve çalışan görevleri profil değişikliklerinden yalıt.", - "highlight3": "Kritik terminal yürütme düzeltmesi — Zoo artık bir sonraki adıma başlamadan önce terminal komutlarının bitmesini bekliyor." + "highlight1": "Üç önemli yeni model geldi — yepyeni Gemini 3.7 Flash, GLM 5.3 ve Qwen3.8 Max modellerini, ayrıca güncellenmiş DeepSeek V4 reasoning, fiyatlandırma ve provider kapsamını kullan.", + "highlight2": "NanoGPT'ye bağlan — dinamik model keşfi, streaming ve Prompt tamamlama ile hız, fiyat, gecikme, throughput, araç desteği ve caching için yönlendirme tercihlerini kullan.", + "highlight3": "Daha güvenilir provider'lar ve görevler — düzeltmeler Azure OpenAI endpoint kurulumunu, Kimi Code çıktı sınırlarını, görev geçmişi başlıklarının korunmasını ve Zoo ayarlarının içe/dışa aktarımını iyileştiriyor." }, "cloudAgents": { "heading": "Cloud'daki yenilikler:", diff --git a/webview-ui/src/i18n/locales/vi/chat.json b/webview-ui/src/i18n/locales/vi/chat.json index e3d933c300..3caa0e8d3d 100644 --- a/webview-ui/src/i18n/locales/vi/chat.json +++ b/webview-ui/src/i18n/locales/vi/chat.json @@ -345,9 +345,9 @@ "support": "Hãy ủng hộ Zoo Code bằng cách tặng sao cho chúng tôi trên GitHub.", "release": { "heading": "Có gì mới:", - "highlight1": "Chạy các task dài hơn mà không bị gián đoạn với Destructive Command Guard (DCG) — DCG chặn các lệnh nguy hiểm trong khi để Zoo tiếp tục làm việc mà bạn không cần liên tục nhấn nút phê duyệt.", - "highlight2": "Khả năng điều khiển và độ tin cậy của provider tốt hơn — chọn tốc độ phản hồi OpenAI Codex, dùng cấu hình DeepSeek mới nhất và tách biệt các task đang chạy khỏi thay đổi profile.", - "highlight3": "Sửa lỗi nghiêm trọng khi thực thi terminal — Zoo giờ sẽ chờ lệnh terminal hoàn tất trước khi bắt đầu bước tiếp theo." + "highlight1": "Ba model mới quan trọng đã xuất hiện — sử dụng các model hoàn toàn mới Gemini 3.7 Flash, GLM 5.3 và Qwen3.8 Max, cùng reasoning, giá và phạm vi provider được cập nhật cho DeepSeek V4.", + "highlight2": "Kết nối với NanoGPT — sử dụng khám phá model động, streaming và hoàn thành Prompt, cùng tùy chọn định tuyến theo tốc độ, giá, độ trễ, throughput, hỗ trợ tool và caching.", + "highlight3": "Provider và task đáng tin cậy hơn — các bản sửa lỗi cải thiện thiết lập endpoint Azure OpenAI, giới hạn đầu ra Kimi Code, giữ nguyên tiêu đề lịch sử task và nhập/xuất cài đặt Zoo." }, "cloudAgents": { "heading": "Mới trên Cloud:", diff --git a/webview-ui/src/i18n/locales/zh-CN/chat.json b/webview-ui/src/i18n/locales/zh-CN/chat.json index 8509072b99..76989eb473 100644 --- a/webview-ui/src/i18n/locales/zh-CN/chat.json +++ b/webview-ui/src/i18n/locales/zh-CN/chat.json @@ -345,9 +345,9 @@ "support": "请在 GitHub 上为 Zoo Code 点星支持我们。", "release": { "heading": "新增功能:", - "highlight1": "使用 Destructive Command Guard(DCG)长时间不间断地运行任务 — DCG 会拦截危险命令,让 Zoo 无需你持续点击批准按钮也能继续工作。", - "highlight2": "更好的提供商控制和可靠性 — 选择 OpenAI Codex 响应速度、使用更新后的 DeepSeek 配置,并让运行中的任务不受配置文件更改影响。", - "highlight3": "关键终端执行问题修复 — Zoo 现在会等待终端命令结束后再开始下一步。" + "highlight1": "三款重磅新模型现已推出 — 使用全新的 Gemini 3.7 Flash、GLM 5.3 和 Qwen3.8 Max 模型,以及更新后的 DeepSeek V4 推理、定价和提供商覆盖。", + "highlight2": "连接 NanoGPT — 使用动态模型发现、流式传输和 Prompt 补全,并按速度、价格、延迟、吞吐量、工具支持和缓存设置路由偏好。", + "highlight3": "更可靠的提供商和任务 — 修复改进了 Azure OpenAI endpoint 设置、Kimi Code 输出限制、任务历史标题保留以及 Zoo 设置的导入/导出。" }, "cloudAgents": { "heading": "云端新功能:", diff --git a/webview-ui/src/i18n/locales/zh-TW/chat.json b/webview-ui/src/i18n/locales/zh-TW/chat.json index 2b0c7c2366..e096c27af4 100644 --- a/webview-ui/src/i18n/locales/zh-TW/chat.json +++ b/webview-ui/src/i18n/locales/zh-TW/chat.json @@ -366,9 +366,9 @@ "support": "請在 GitHub 上為 Zoo Code 加星支持我們。", "release": { "heading": "新增功能:", - "highlight1": "使用 Destructive Command Guard(DCG)長時間不中斷地執行任務 — DCG 會封鎖危險指令,讓 Zoo 不需你持續按下核准按鈕也能繼續工作。", - "highlight2": "更好的供應商控制與可靠性 — 選擇 OpenAI Codex 回應速度、使用更新後的 DeepSeek 設定,並讓執行中的任務不受設定檔變更影響。", - "highlight3": "關鍵終端機執行問題修正 — Zoo 現在會等待終端機指令結束後再開始下一步。" + "highlight1": "三款重磅新模型現已推出 — 使用全新的 Gemini 3.7 Flash、GLM 5.3 和 Qwen3.8 Max 模型,以及更新後的 DeepSeek V4 推理、定價與供應商支援。", + "highlight2": "連接 NanoGPT — 使用動態模型探索、串流與 Prompt 補全,並依速度、價格、延遲、吞吐量、工具支援和快取設定路由偏好。", + "highlight3": "更可靠的供應商與任務 — 修正改善了 Azure OpenAI endpoint 設定、Kimi Code 輸出限制、任務歷史標題保留,以及 Zoo 設定的匯入/匯出。" }, "cloudAgents": { "heading": "雲端的新功能:", From d52f659b9a44ede6db597a0e4da932b720869189 Mon Sep 17 00:00:00 2001 From: edelauna <54631123+edelauna@users.noreply.github.com> Date: Sun, 16 Aug 2026 15:19:07 +0000 Subject: [PATCH 14/66] fix(task): recover stale delegated children after restart (#1210) * fix(task): recover stale delegated children after restart * fix(task): make delegated recovery durable * test(e2e): verify persistence across VS Code restart * test(e2e): verify persistence across VS Code restart * fix(task-persistence): harden delegation repair recovery * test(e2e): stabilize restart persistence smoke test * fix(task): serialize concurrent history restoration --------- Co-authored-by: Roomote --- .github/workflows/e2e.yml | 6 + .../fixtures/restart-persistence.json | 18 + apps/vscode-e2e/src/restart/phaseProtocol.ts | 107 ++++ .../src/restart/scenarioWorkspace.ts | 58 ++ .../src/restart/vscodeCoordinator.ts | 90 +++ apps/vscode-e2e/src/runTest.ts | 62 +- apps/vscode-e2e/src/suite/index.ts | 2 +- .../src/suite/restart-persistence.test.ts | 119 ++++ .../src/suite/resume-eviction-race.test.ts | 50 ++ src/__tests__/single-open-invariant.spec.ts | 85 +++ src/core/task-persistence/TaskHistoryStore.ts | 466 +++++++++++++-- .../TaskHistoryStore.reconciliation.spec.ts | 554 +++++++++++++++++- .../__tests__/TaskHistoryStore.spec.ts | 40 ++ src/core/webview/ClineProvider.ts | 26 +- src/eslint-suppressions.json | 5 - src/shared/globalFileNames.ts | 1 + 16 files changed, 1590 insertions(+), 99 deletions(-) create mode 100644 apps/vscode-e2e/fixtures/restart-persistence.json create mode 100644 apps/vscode-e2e/src/restart/phaseProtocol.ts create mode 100644 apps/vscode-e2e/src/restart/scenarioWorkspace.ts create mode 100644 apps/vscode-e2e/src/restart/vscodeCoordinator.ts create mode 100644 apps/vscode-e2e/src/suite/restart-persistence.test.ts diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 2d1819b4e1..02d38ddfa0 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -150,6 +150,12 @@ jobs: if: github.event_name != 'pull_request' || steps.e2e-marker.outputs.cache-hit != 'true' run: xvfb-run -a pnpm --filter @roo-code/vscode-e2e test:ci:mock + - name: Run mocked restart-persistence E2E test + # Reuse the runner built by the full mocked suite; this direct invocation avoids + # test:run's dotenv loading and does not repeat the bundle or webview build. + if: github.event_name != 'pull_request' || steps.e2e-marker.outputs.cache-hit != 'true' + run: TEST_FILE=restart-persistence.test USE_MOCK=true xvfb-run -a pnpm --filter @roo-code/vscode-e2e exec node ./out/runTest.js + - name: Explain skipped mocked E2E pass marker if: steps.e2e-marker.outputs.cache-hit != 'true' && steps.run-e2e.outcome == 'success' && steps.vscode-fallback.outputs.used == 'true' run: echo "Skipping mocked E2E pass marker because tests ran against a stale cached VS Code binary (VS Code download endpoints unreachable)." diff --git a/apps/vscode-e2e/fixtures/restart-persistence.json b/apps/vscode-e2e/fixtures/restart-persistence.json new file mode 100644 index 0000000000..240b91da20 --- /dev/null +++ b/apps/vscode-e2e/fixtures/restart-persistence.json @@ -0,0 +1,18 @@ +{ + "fixtures": [ + { + "match": { + "userMessage": "RESTART_PERSISTENCE_SMOKE" + }, + "response": { + "toolCalls": [ + { + "name": "attempt_completion", + "arguments": "{\"result\":\"RESTART_PERSISTENCE_MARKER\"}", + "id": "call_restart_persistence_done" + } + ] + } + } + ] +} diff --git a/apps/vscode-e2e/src/restart/phaseProtocol.ts b/apps/vscode-e2e/src/restart/phaseProtocol.ts new file mode 100644 index 0000000000..06ddc5f508 --- /dev/null +++ b/apps/vscode-e2e/src/restart/phaseProtocol.ts @@ -0,0 +1,107 @@ +import * as path from "path" +import * as fs from "fs/promises" + +import { createWriteStream } from "fs" + +export const PHASE_RESULT_VERSION = 1 as const + +export type RestartPhase = "create" | "verify" +export type PhaseStatus = "passed" | "failed" + +export type PhaseError = { + message: string + stack?: string +} + +export type PhaseResult = { + version: typeof PHASE_RESULT_VERSION + phase: RestartPhase + status: PhaseStatus + values?: Record + error?: PhaseError +} + +const phaseResultNames: Record = { + create: "01-create.json", + verify: "02-verify.json", +} + +export function getPhaseResultPath(resultsDir: string, phase: RestartPhase): string { + const resolvedResultsDir = path.resolve(resultsDir) + const resultPath = path.resolve(resolvedResultsDir, phaseResultNames[phase]) + if (path.dirname(resultPath) !== resolvedResultsDir) { + throw new Error(`Phase result path escaped the results directory: ${phase}`) + } + return resultPath +} + +export function serializePhaseError(error: unknown): PhaseError { + if (error instanceof Error) { + return { + message: error.message.slice(0, 2_000), + ...(error.stack && { stack: error.stack.slice(0, 4_000) }), + } + } + + return { message: String(error).slice(0, 2_000) } +} + +function isRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null +} + +export function validatePhaseResult(value: unknown): asserts value is PhaseResult { + if (!isRecord(value) || value.version !== PHASE_RESULT_VERSION) { + throw new Error("Invalid phase result version") + } + if (value.phase !== "create" && value.phase !== "verify") { + throw new Error("Invalid phase result phase") + } + if (value.status !== "passed" && value.status !== "failed") { + throw new Error("Invalid phase result status") + } + if (value.values !== undefined) { + if (!isRecord(value.values) || Object.values(value.values).some((entry) => typeof entry !== "string")) { + throw new Error("Phase result values must be string-valued") + } + } + if (value.error !== undefined) { + if (!isRecord(value.error) || typeof value.error.message !== "string") { + throw new Error("Invalid phase result error") + } + if (value.error.stack !== undefined && typeof value.error.stack !== "string") { + throw new Error("Invalid phase result error stack") + } + } +} + +export async function writePhaseResult(resultsDir: string, result: PhaseResult): Promise { + validatePhaseResult(result) + const targetPath = getPhaseResultPath(resultsDir, result.phase) + const temporaryPath = `${targetPath}.${process.pid}.${Date.now()}.tmp` + try { + await writeJsonAtomically(temporaryPath, result) + await fs.rename(temporaryPath, targetPath) + } finally { + await fs.rm(temporaryPath, { force: true }) + } +} + +async function writeJsonAtomically(filePath: string, value: PhaseResult): Promise { + await fs.mkdir(path.dirname(filePath), { recursive: true }) + await new Promise((resolve, reject) => { + const stream = createWriteStream(filePath, { encoding: "utf8" }) + stream.once("error", reject) + stream.once("finish", resolve) + stream.end(JSON.stringify(value)) + }) +} + +export async function readPhaseResult(resultsDir: string, phase: RestartPhase): Promise { + const result = JSON.parse(await fs.readFile(getPhaseResultPath(resultsDir, phase), "utf8")) as unknown + validatePhaseResult(result) + if (result.phase !== phase) { + throw new Error(`Phase result does not match requested phase: ${phase}`) + } + return result +} diff --git a/apps/vscode-e2e/src/restart/scenarioWorkspace.ts b/apps/vscode-e2e/src/restart/scenarioWorkspace.ts new file mode 100644 index 0000000000..9ce49deaf0 --- /dev/null +++ b/apps/vscode-e2e/src/restart/scenarioWorkspace.ts @@ -0,0 +1,58 @@ +import * as os from "os" +import * as path from "path" +import * as fs from "fs/promises" + +const SCENARIO_ROOT_PREFIX = "roo-vscode-e2e-restart-" + +export type ScenarioWorkspace = { + root: string + workspace: string + userData: string + extensions: string + results: string +} + +function childPath(root: string, name: string): string { + const resolvedRoot = path.resolve(root) + const resolvedChild = path.resolve(resolvedRoot, name) + if (path.dirname(resolvedChild) !== resolvedRoot) { + throw new Error(`Scenario path escaped its root: ${name}`) + } + return resolvedChild +} + +export async function createScenarioWorkspace(): Promise { + const root = await fs.mkdtemp(path.join(os.tmpdir(), SCENARIO_ROOT_PREFIX)) + const scenarioWorkspace: ScenarioWorkspace = { + root, + workspace: childPath(root, "workspace"), + userData: childPath(root, "user-data"), + extensions: childPath(root, "extensions"), + results: childPath(root, "results"), + } + + await Promise.all( + [ + scenarioPath(scenarioWorkspace, "workspace"), + scenarioPath(scenarioWorkspace, "userData"), + scenarioPath(scenarioWorkspace, "extensions"), + scenarioPath(scenarioWorkspace, "results"), + ].map((directory) => fs.mkdir(directory, { recursive: true })), + ) + + return scenarioWorkspace +} + +function scenarioPath(scenarioWorkspace: ScenarioWorkspace, key: "workspace" | "userData" | "extensions" | "results") { + return scenarioWorkspace[key] +} + +export async function removeScenarioWorkspace(scenarioWorkspace: ScenarioWorkspace): Promise { + const root = path.resolve(scenarioWorkspace.root) + const tempRoot = path.resolve(os.tmpdir()) + if (path.dirname(root) !== tempRoot || !path.basename(root).startsWith(SCENARIO_ROOT_PREFIX)) { + throw new Error(`Refusing to remove an unowned scenario root: ${scenarioWorkspace.root}`) + } + + await fs.rm(root, { recursive: true, force: true }) +} diff --git a/apps/vscode-e2e/src/restart/vscodeCoordinator.ts b/apps/vscode-e2e/src/restart/vscodeCoordinator.ts new file mode 100644 index 0000000000..9400aaaaf4 --- /dev/null +++ b/apps/vscode-e2e/src/restart/vscodeCoordinator.ts @@ -0,0 +1,90 @@ +import { spawn } from "child_process" +import * as path from "path" + +import { readPhaseResult, type RestartPhase, type PhaseResult } from "./phaseProtocol" +import type { ScenarioWorkspace } from "./scenarioWorkspace" + +export type RestartCoordinatorOptions = { + vscodeExecutablePath: string + extensionDevelopmentPath: string + extensionTestsPath: string + scenario: string + workspace: ScenarioWorkspace + environment: NodeJS.ProcessEnv + expectedExitPolicies: readonly ExpectedExitPolicy[] +} + +export type ExpectedExitPolicy = { + phase: RestartPhase + termination: "graceful-quit" + code: number + signal: NodeJS.Signals | null +} + +function phaseEnvironment(options: RestartCoordinatorOptions, phase: RestartPhase): NodeJS.ProcessEnv { + return { + ...options.environment, + E2E_PHASE: phase, + E2E_SCENARIO: options.scenario, + E2E_RESULTS_DIR: options.workspace.results, + } +} + +function phaseArguments(options: RestartCoordinatorOptions): string[] { + return [ + options.workspace.workspace, + `--user-data-dir=${options.workspace.userData}`, + `--extensions-dir=${options.workspace.extensions}`, + "--no-sandbox", + "--disable-gpu-sandbox", + "--disable-updates", + "--skip-welcome", + "--skip-release-notes", + "--disable-workspace-trust", + `--extensionTestsPath=${options.extensionTestsPath}`, + `--extensionDevelopmentPath=${options.extensionDevelopmentPath}`, + ] +} + +async function runPhase(options: RestartCoordinatorOptions, phase: RestartPhase): Promise { + const args = phaseArguments(options) + console.log(`[restart:${phase}] spawning VS Code: ${path.basename(options.vscodeExecutablePath)}`) + + const child = spawn(options.vscodeExecutablePath, args, { + env: phaseEnvironment(options, phase), + shell: process.platform === "win32", + stdio: ["ignore", "pipe", "pipe"], + }) + + child.stdout?.on("data", (chunk: Buffer) => process.stdout.write(`[restart:${phase}] ${chunk}`)) + child.stderr?.on("data", (chunk: Buffer) => process.stderr.write(`[restart:${phase}] ${chunk}`)) + + const exit = await new Promise<{ code: number | null; signal: NodeJS.Signals | null }>((resolve, reject) => { + child.once("error", reject) + child.once("close", (code, signal) => resolve({ code, signal })) + }) + + const result = await readPhaseResult(options.workspace.results, phase) + if (result.status !== "passed") { + throw new Error(`[restart:${phase}] phase result was not passed: ${result.error?.message ?? "unknown failure"}`) + } + + const expectedExit = options.expectedExitPolicies.find((policy) => policy.phase === phase) + const isExpectedNonzeroExit = + exit.code !== 0 && + expectedExit !== undefined && + expectedExit.termination === "graceful-quit" && + exit.code === expectedExit.code && + exit.signal === expectedExit.signal + const isSuccessfulExit = exit.code === 0 && exit.signal === null + if (!isSuccessfulExit && !isExpectedNonzeroExit) { + throw new Error(`[restart:${phase}] VS Code exited with ${exit.code ?? exit.signal}`) + } + + return result +} + +export async function runRestartScenario(options: RestartCoordinatorOptions): Promise { + await runPhase(options, "create") + await runPhase(options, "verify") +} diff --git a/apps/vscode-e2e/src/runTest.ts b/apps/vscode-e2e/src/runTest.ts index 482e73e945..8162f34068 100644 --- a/apps/vscode-e2e/src/runTest.ts +++ b/apps/vscode-e2e/src/runTest.ts @@ -3,7 +3,7 @@ import * as os from "os" import * as fs from "fs/promises" import { readFileSync } from "fs" -import { runTests } from "@vscode/test-electron" +import { downloadAndUnzipVSCode, runTests } from "@vscode/test-electron" import { LLMock } from "@copilotkit/aimock" import { addApplyDiffResultFixtures } from "./fixtures/apply-diff" @@ -21,6 +21,8 @@ import { addSearchFilesResultFixtures } from "./fixtures/search-files" import { addSubtaskFixtures } from "./fixtures/subtasks" import { addUseMcpToolResultFixtures } from "./fixtures/use-mcp-tool" import { addWriteToFileResultFixtures } from "./fixtures/write-to-file" +import { createScenarioWorkspace, removeScenarioWorkspace } from "./restart/scenarioWorkspace" +import { runRestartScenario } from "./restart/vscodeCoordinator" function getCliFlagValue(flag: string) { return process.argv.find((arg, index) => process.argv[index - 1] === flag) @@ -43,6 +45,14 @@ function isBedrockTargetedRun(testFile?: string, testGrep?: string) { return testGrep?.toLowerCase().includes("bedrock") ?? false } +function isRestartPersistenceTargetedRun(testFile?: string, testGrep?: string): boolean { + if (testFile?.toLowerCase().includes("restart-persistence")) { + return true + } + + return testGrep?.toLowerCase().includes("restart persistence") ?? false +} + async function main() { const isRecord = process.env.AIMOCK_RECORD === "true" const testGrep = getCliFlagValue("--grep") || process.env.TEST_GREP @@ -50,6 +60,7 @@ async function main() { const isDeepSeekTest = isDeepSeekTargetedRun(testFile, testGrep) const isGeminiTest = testFile?.toLowerCase().includes("gemini.test") ?? false const isBedrockTest = isBedrockTargetedRun(testFile, testGrep) + const isRestartPersistenceTest = isRestartPersistenceTargetedRun(testFile, testGrep) if (isRecord && isDeepSeekTest && !process.env.DEEPSEEK_API_KEY) { throw new Error("AIMOCK_RECORD=true requires DEEPSEEK_API_KEY to record DeepSeek fixtures") @@ -83,11 +94,14 @@ async function main() { const extensionTestsPath = path.resolve(__dirname, "./suite/index") let testWorkspace: string | undefined + let scenarioWorkspace: Awaited> | undefined try { - // Create a temporary workspace folder for tests before installing fixtures that - // need workspace-specific paths. - testWorkspace = await fs.mkdtemp(path.join(os.tmpdir(), "roo-test-workspace-")) + // Create a temporary workspace folder for regular tests. Restart scenarios own + // all of their paths under the dedicated scenario root below. + if (!isRestartPersistenceTest) { + testWorkspace = await fs.mkdtemp(path.join(os.tmpdir(), "roo-test-workspace-")) + } if (useMock) { const fixturesDir = path.resolve(__dirname, "../fixtures") @@ -173,13 +187,36 @@ async function main() { const pkg = JSON.parse(readFileSync(path.resolve(__dirname, "../package.json"), "utf-8")) const vscodeVersion = process.env.VSCODE_VERSION || pkg.devDependencies["@types/vscode"] - await runTests({ - extensionDevelopmentPath, - extensionTestsPath, - launchArgs: [testWorkspace], - extensionTestsEnv, - version: vscodeVersion, - }) + if (isRestartPersistenceTest) { + scenarioWorkspace = await createScenarioWorkspace() + const vscodeExecutablePath = await downloadAndUnzipVSCode({ + version: vscodeVersion, + extensionDevelopmentPath, + }) + await runRestartScenario({ + vscodeExecutablePath, + extensionDevelopmentPath, + extensionTestsPath, + scenario: "restart-persistence", + workspace: scenarioWorkspace, + environment: extensionTestsEnv, + expectedExitPolicies: [ + { phase: "create", termination: "graceful-quit", code: 1, signal: null }, + { phase: "verify", termination: "graceful-quit", code: 1, signal: null }, + ], + }) + } else { + if (!testWorkspace) { + throw new Error("Regular E2E runs require a temporary test workspace") + } + await runTests({ + extensionDevelopmentPath, + extensionTestsPath, + launchArgs: [testWorkspace], + extensionTestsEnv, + version: vscodeVersion, + }) + } } catch (error) { console.error("Failed to run tests", error) process.exitCode = 1 @@ -187,6 +224,9 @@ async function main() { if (testWorkspace) { await fs.rm(testWorkspace, { recursive: true, force: true }) } + if (scenarioWorkspace) { + await removeScenarioWorkspace(scenarioWorkspace) + } await mock?.stop() } } diff --git a/apps/vscode-e2e/src/suite/index.ts b/apps/vscode-e2e/src/suite/index.ts index 63d29ec28c..e93d73bd37 100644 --- a/apps/vscode-e2e/src/suite/index.ts +++ b/apps/vscode-e2e/src/suite/index.ts @@ -72,7 +72,7 @@ export async function run() { testFiles = await glob(`**/${specificFile}`, { cwd }) console.log(`Running specific test file: ${specificFile}`) } else { - testFiles = await glob("**/**.test.js", { cwd }) + testFiles = await glob("**/**.test.js", { cwd, ignore: "**/suite/restart-persistence.test.js" }) } if (testFiles.length === 0) { diff --git a/apps/vscode-e2e/src/suite/restart-persistence.test.ts b/apps/vscode-e2e/src/suite/restart-persistence.test.ts new file mode 100644 index 0000000000..29e7fa3ddd --- /dev/null +++ b/apps/vscode-e2e/src/suite/restart-persistence.test.ts @@ -0,0 +1,119 @@ +import * as assert from "assert" +import * as vscode from "vscode" + +import { RooCodeEventName, type RooCodeAPI } from "@roo-code/types" + +import { + PHASE_RESULT_VERSION, + readPhaseResult, + serializePhaseError, + type PhaseResult, + writePhaseResult, +} from "../restart/phaseProtocol" +import { waitFor, waitUntilCompleted } from "./utils" + +const SCENARIO = "restart-persistence" +const MARKER = "RESTART_PERSISTENCE_MARKER" + +function getResultsDir(): string { + const resultsDir = process.env.E2E_RESULTS_DIR + if (!resultsDir) throw new Error("E2E_RESULTS_DIR is required") + return resultsDir +} + +async function quitGracefully(): Promise { + await vscode.commands.executeCommand("workbench.action.quit") +} + +async function runCreate(api: RooCodeAPI): Promise { + let taskId: string | undefined + let createPhasePassed = false + let sawMarker = false + const messageHandler = ({ message }: { message: { type: string; text?: string; partial?: boolean } }) => { + if (message.type === "say" && message.partial === false && message.text?.includes(MARKER)) { + sawMarker = true + } + } + api.on(RooCodeEventName.Message, messageHandler) + + try { + taskId = await api.startNewTask({ + configuration: { mode: "ask", alwaysAllowModeSwitch: true, autoApprovalEnabled: true }, + text: `${SCENARIO}: RESTART_PERSISTENCE_SMOKE`, + }) + await waitUntilCompleted({ api, taskId }) + assert.strictEqual(sawMarker, true, `Completion should include ${MARKER}`) + const historyItem = await api.getTaskHistoryItem(taskId) + assert.ok(historyItem, "Completed task should have a history item") + assert.ok(historyItem.task.includes("RESTART_PERSISTENCE_SMOKE"), "History title should include the marker") + const conversationLength = await api.getTaskApiConversationHistoryLength(taskId) + assert.ok(conversationLength > 0, "Completed task should persist API conversation history") + + const result: PhaseResult = { + version: PHASE_RESULT_VERSION, + phase: "create", + status: "passed", + values: { taskId }, + } + await writePhaseResult(getResultsDir(), result) + createPhasePassed = true + await quitGracefully() + } catch (error) { + await writePhaseResult(getResultsDir(), { + version: PHASE_RESULT_VERSION, + phase: "create", + status: "failed", + error: serializePhaseError(error), + }) + throw error + } finally { + api.off(RooCodeEventName.Message, messageHandler) + if (!createPhasePassed && taskId && api.getCurrentTaskStack().includes(taskId)) await api.cancelCurrentTask() + } +} + +async function runVerify(api: RooCodeAPI): Promise { + try { + const createResult = await readPhaseResult(getResultsDir(), "create") + assert.strictEqual(createResult.status, "passed") + const taskId = createResult.values?.taskId + assert.ok(taskId, "Create phase should record a task ID") + + await waitFor(() => api.isReady()) + assert.strictEqual(await api.isTaskInHistory(taskId), true, "Task should be present after restart") + const historyItem = await api.getTaskHistoryItem(taskId) + assert.ok(historyItem, "Task history item should be available after restart") + assert.ok(historyItem.task.includes("RESTART_PERSISTENCE_SMOKE"), "History title should persist after restart") + const conversationLength = await api.getTaskApiConversationHistoryLength(taskId) + assert.ok(conversationLength > 0, "API conversation history should be available after restart") + + await writePhaseResult(getResultsDir(), { + version: PHASE_RESULT_VERSION, + phase: "verify", + status: "passed", + values: { taskId, conversationLength: String(conversationLength) }, + }) + await quitGracefully() + } catch (error) { + await writePhaseResult(getResultsDir(), { + version: PHASE_RESULT_VERSION, + phase: "verify", + status: "failed", + error: serializePhaseError(error), + }) + throw error + } +} + +suite("Restart persistence", () => { + test("persists completed task across a fresh extension host", async () => { + const api = globalThis.api + if (process.env.E2E_PHASE === "create") { + await runCreate(api) + } else if (process.env.E2E_PHASE === "verify") { + await runVerify(api) + } else { + throw new Error(`Unknown E2E_PHASE: ${process.env.E2E_PHASE ?? "unset"}`) + } + }) +}) diff --git a/apps/vscode-e2e/src/suite/resume-eviction-race.test.ts b/apps/vscode-e2e/src/suite/resume-eviction-race.test.ts index 53f33cb4e5..d888978483 100644 --- a/apps/vscode-e2e/src/suite/resume-eviction-race.test.ts +++ b/apps/vscode-e2e/src/suite/resume-eviction-race.test.ts @@ -2,6 +2,7 @@ import * as assert from "assert" import { setDefaultSuiteTimeout } from "./test-utils" import { waitUntilCompleted, waitFor } from "./utils" +import { SCHED_COMPLETED_PROMPT } from "../fixtures/subtasks" // Regression test for the "Work #1 (no message)" title-clobber bug reported // against Zoo Code v3.76.0 (Discord, 2026-08-06). @@ -93,4 +94,53 @@ suite("Resume eviction race (title clobber regression)", function () { `Title must not change during resume eviction. Got: "${afterEviction.task}"`, ) }) + + test("concurrent resumes of one history item do not block the next task", async () => { + const api = globalThis.api + + // Persist a resumable history item, then remove its live instance so both + // resume calls begin from the same "not current" state. This mirrors two + // showTaskWithId messages arriving before either restoration has installed + // its replacement instance. + const historyTaskId = await waitUntilCompleted({ + api, + start: () => + api.startNewTask({ + configuration: { + mode: "ask", + autoApprovalEnabled: true, + enableCheckpoints: false, + }, + text: SCHED_COMPLETED_PROMPT, + }), + }) + + while (api.getCurrentTaskStack().length > 0) { + await api.clearCurrentTask() + } + + // Before the fix, both calls can construct and schedule distinct Task + // instances for historyTaskId. TaskRegistry.push() replaces the first map + // entry without disposing that instance, so its resume ask retains the + // scheduler's only permit while the visible replacement is queued. + await Promise.all([api.resumeTask(historyTaskId), api.resumeTask(historyTaskId)]) + await waitFor(() => api.getCurrentTaskStack().at(-1) === historyTaskId) + + // Starting a fresh task must evict the restored history task and acquire the + // scheduler permit. A leaked first restoration makes this wait time out. + const nextTaskId = await waitUntilCompleted({ + api, + start: () => + api.startNewTask({ + configuration: { + mode: "ask", + autoApprovalEnabled: true, + enableCheckpoints: false, + }, + text: SCHED_COMPLETED_PROMPT, + }), + }) + + assert.notStrictEqual(nextTaskId, historyTaskId, "A fresh task should start after duplicate history resumes") + }) }) diff --git a/src/__tests__/single-open-invariant.spec.ts b/src/__tests__/single-open-invariant.spec.ts index 9eeec8a960..954261b145 100644 --- a/src/__tests__/single-open-invariant.spec.ts +++ b/src/__tests__/single-open-invariant.spec.ts @@ -34,6 +34,9 @@ vi.mock("../core/task/Task", () => { public parentTask?: unknown public apiConfiguration: unknown public rootTask?: unknown + public abort = false + public abandoned = false + public abortTask = vi.fn().mockResolvedValue(undefined) constructor(opts: { historyItem?: { id: string } parentTask?: unknown @@ -294,6 +297,88 @@ describe("Single-open-task invariant", () => { expect(removeClineFromStack).not.toHaveBeenCalled() }) + it("serializes concurrent history resumes before mutating the task registry", async () => { + let releaseFirstEviction!: () => void + const firstEvictionGate = new Promise((resolve) => { + releaseFirstEviction = resolve + }) + const registry = new TaskRegistry() + const evictCurrentTask = vi.fn().mockImplementation(async () => { + if (evictCurrentTask.mock.calls.length === 1) { + await firstEvictionGate + } + const current = registry.current + if (current) { + registry.remove(current.taskId) + } + }) + const schedulespy = vi.fn().mockResolvedValue(undefined) + + const provider = { + historyTaskCreationQueue: Promise.resolve(), + getCurrentTask: vi.fn(() => registry.current), + taskRegistry: registry, + taskHistoryStore: { get: vi.fn(() => undefined) }, + evictCurrentTask, + addClineToStack: vi.fn().mockImplementation(async (task: Task) => registry.push(task)), + log: vi.fn(), + customModesManager: { getCustomModes: vi.fn().mockResolvedValue([]) }, + providerSettingsManager: { + getModeConfigId: vi.fn().mockResolvedValue(undefined), + listConfig: vi.fn().mockResolvedValue([]), + }, + getState: vi.fn().mockResolvedValue({ + apiConfiguration: { apiProvider: "anthropic", consecutiveMistakeLimit: 0 }, + enableCheckpoints: true, + checkpointTimeout: 60, + experiments: {}, + cloudUserInfo: null, + taskSyncEnabled: false, + }), + getPendingEditOperation: vi.fn().mockReturnValue(undefined), + clearPendingEditOperation: vi.fn(), + taskScheduler: { schedule: schedulespy }, + taskEventListeners: new WeakMap(), + performPreparationTasks: vi.fn().mockResolvedValue(undefined), + context: { extension: { packageJSON: {} }, globalStorageUri: { fsPath: "/tmp" } }, + contextProxy: { + extensionUri: {}, + getValue: vi.fn(), + setValue: vi.fn(), + setProviderSettings: vi.fn(), + getProviderSettings: vi.fn(() => ({})), + }, + postStateToWebview: vi.fn(), + } as unknown as ClineProvider + + const historyItem = { + id: "hist-concurrent-1", + number: 1, + ts: Date.now(), + task: "Task", + tokensIn: 0, + tokensOut: 0, + totalCost: 0, + workspace: "/tmp", + } + + const firstResume = privateClineProvider.createTaskWithHistoryItem.call(provider, historyItem) + const secondResume = privateClineProvider.createTaskWithHistoryItem.call(provider, historyItem) + + await vi.waitFor(() => expect(evictCurrentTask).toHaveBeenCalledTimes(1)) + expect(provider.getState).not.toHaveBeenCalled() + + releaseFirstEviction() + const [firstTask, secondTask] = await Promise.all([firstResume, secondResume]) + + expect(firstTask).not.toBe(secondTask) + expect(firstTask.abortTask).toHaveBeenCalledWith(true) + expect(evictCurrentTask).toHaveBeenCalledTimes(1) + expect(registry.taskIds).toEqual([historyItem.id]) + expect(registry.current).toBe(secondTask) + expect(schedulespy).toHaveBeenCalledTimes(2) + }) + it("IPC StartNewTask path closes current before new task", async () => { const removeClineFromStack = vi.fn().mockResolvedValue(undefined) const createTask = vi.fn().mockResolvedValue({ taskId: "ipc-1" }) diff --git a/src/core/task-persistence/TaskHistoryStore.ts b/src/core/task-persistence/TaskHistoryStore.ts index c6c3c6910f..e4707ee0a9 100644 --- a/src/core/task-persistence/TaskHistoryStore.ts +++ b/src/core/task-persistence/TaskHistoryStore.ts @@ -1,7 +1,9 @@ import * as fs from "fs/promises" import * as fsSync from "fs" import * as path from "path" +import crypto from "crypto" +import deepEqual from "fast-deep-equal" import type { HistoryItem } from "@roo-code/types" import { GlobalFileNames } from "../../shared/globalFileNames" @@ -40,6 +42,34 @@ interface HistoryIndex { entries: HistoryItem[] } +/** + * Durable intent for the one repair that spans an active delegated child and + * its parent. Task files remain authoritative; this file only records the + * guarded target transition that must be completed after a crash. + */ +interface DelegationRepairIntent { + version: 1 + operationId: string + parentTaskId: string + childTaskId: string + expected: { + parent: { + status: "delegated" + awaitingChildId: string + delegatedToId?: string + } + child: { + status: "active" + parentTaskId?: string + rootTaskId?: string + } + } + target: { + childStatus: "interrupted" + parentStatus: "active" + } +} + /** * TaskHistoryStore encapsulates all task history persistence logic. * @@ -68,6 +98,7 @@ export class TaskHistoryStore { private readonly globalStoragePath: string private readonly onWrite?: (items: HistoryItem[]) => Promise private cache: Map = new Map() + private taskFileMtimes: Map = new Map() private writeLock: Promise = Promise.resolve() private indexWriteTimer: ReturnType | null = null private fsWatcher: fsSync.FSWatcher | null = null @@ -109,15 +140,26 @@ export class TaskHistoryStore { await this.loadIndex() // 2. Reconcile cache against actual task directories on disk - await this.reconcile() + await this.reconcile({ forceRefresh: true }) + // Capture which active tasks were present in persisted state before replay can + // change any statuses. Reconciliation must not treat a replay-repaired parent + // as an orphaned active child in the same startup pass. + const persistedActiveIds = this.getPersistedActiveIds() - // 3. Repair delegation inconsistencies left by a previous crash - await this.reconcileDelegationState() + // 3. Complete any two-record repair interrupted after its intent was durable. + try { + await this.replayDelegationRepairIntent() + } catch (error) { + console.error("[TaskHistoryStore] Failed to replay delegation repair intent:", error) + } + + // 4. Repair delegation inconsistencies left by a previous crash + await this.reconcileDelegationState(persistedActiveIds) - // 4. Start fs.watch for cross-instance reactivity + // 5. Start fs.watch for cross-instance reactivity this.startWatcher() - // 5. Start periodic reconciliation as a defensive fallback + // 6. Start periodic reconciliation as a defensive fallback this.startPeriodicReconciliation() } finally { // Mark initialization as complete so callers awaiting `initialized` can proceed @@ -239,6 +281,7 @@ export class TaskHistoryStore { async delete(taskId: string): Promise { return this.withLock(async () => { this.cache.delete(taskId) + this.taskFileMtimes.delete(taskId) // Remove per-task file (best-effort) try { @@ -264,6 +307,7 @@ export class TaskHistoryStore { return this.withLock(async () => { for (const taskId of taskIds) { this.cache.delete(taskId) + this.taskFileMtimes.delete(taskId) try { const filePath = await this.getTaskFilePath(taskId) @@ -290,7 +334,7 @@ export class TaskHistoryStore { * - Tasks on disk but missing from cache: read and add * - Tasks in cache but missing from disk: remove */ - async reconcile(): Promise { + async reconcile(options: { forceRefresh?: boolean } = {}): Promise { // Run through the write lock to prevent interleaving with upsert/delete return this.withLock(async () => { const tasksDir = await this.getTasksDir() @@ -309,18 +353,32 @@ export class TaskHistoryStore { const cacheIds = new Set(this.cache.keys()) let changed = false - // Tasks on disk but not in cache: read their history_item.json + // Task files are authoritative during startup. Later watcher and periodic + // reconciliations use mtime change detection to avoid rewriting the index when + // nothing changed on disk. for (const taskId of onDiskIds) { - if (!cacheIds.has(taskId)) { - try { - const item = await this.readTaskFile(taskId) - if (item) { + try { + const taskFilePath = await this.getTaskFilePath(taskId) + const { mtimeMs } = await fs.stat(taskFilePath) + if ( + !options.forceRefresh && + this.cache.has(taskId) && + this.taskFileMtimes.get(taskId) === mtimeMs + ) { + continue + } + + const item = await this.readTaskFile(taskId) + if (item) { + const previous = this.cache.get(taskId) + this.taskFileMtimes.set(taskId, mtimeMs) + if (!deepEqual(previous, item)) { this.cache.set(taskId, item) changed = true } - } catch { - // Corrupted or missing file, skip } + } catch { + // Corrupted or missing file, skip } } @@ -328,6 +386,7 @@ export class TaskHistoryStore { for (const taskId of cacheIds) { if (!onDiskIds.has(taskId)) { this.cache.delete(taskId) + this.taskFileMtimes.delete(taskId) changed = true } } @@ -355,23 +414,43 @@ export class TaskHistoryStore { * - Parent `delegated` with no `awaitingChildId` → parent → `active` (invalid state) * - Parent `delegated`, child not found → parent → `active` (orphaned delegation) * - Parent `delegated`, child `completed` → parent → `active` (interrupted handoff) + * - Parent `delegated`, child `active` → child → `interrupted`, parent → `active` * - * A parent awaiting an `active`, `interrupted`, or `delegated` child is left as-is — the child is resumable. + * A parent awaiting an `interrupted` or `delegated` child is left as-is — the child is + * resumable. An `active` child is treated as orphaned during startup recovery because + * no live task session exists to own it. */ - private async reconcileDelegationState(): Promise { - return this.withLock(async () => { - let repairsInThisPass: number - do { - repairsInThisPass = 0 - // Rebuild the lookup map each pass so repairs from the previous pass - // are visible when evaluating chained delegations. - const byId = new Map(Array.from(this.cache.values()).map((i) => [i.id, i])) - - for (const [, item] of byId) { - if (item.status !== "delegated") { - continue - } + private async reconcileDelegationState(persistedActiveIds: ReadonlySet): Promise { + return this.withLock(() => this.reconcileDelegationStateCore(persistedActiveIds)) + } + + /** + * Reconcile delegation state while the store lock is already held. + * + * Callers that do not hold the lock must use `reconcileDelegationState()`. + * Migration uses this core method so its cache/file/index updates and the + * follow-up repair remain one serialized operation without re-entering the + * non-reentrant lock. + */ + private async reconcileDelegationStateCore(persistedActiveIds: ReadonlySet): Promise { + // Only statuses loaded from persistence represent sessions that could have + // been orphaned by a crash. A delegated parent repaired to active earlier in + // this pass remains resumable and must not be mistaken for a second orphaned + // child in a delegation chain. The snapshot is intentionally captured before + // repair-intent replay and remains unchanged for the entire reconciliation. + let repairsInThisPass: number + do { + repairsInThisPass = 0 + // Rebuild the lookup map each pass so repairs from the previous pass + // are visible when evaluating chained delegations. + const byId = new Map(Array.from(this.cache.values()).map((i) => [i.id, i])) + + for (const [, item] of byId) { + if (item.status !== "delegated") { + continue + } + try { if (!item.awaitingChildId) { await this.upsertCore( { ...item, status: "active", awaitingChildId: undefined, delegatedToId: undefined }, @@ -400,6 +479,16 @@ export class TaskHistoryStore { `[TaskHistoryStore] Reconciled orphaned delegation: task ${item.id} → active (child ${item.awaitingChildId} not found)`, ) repairsInThisPass++ + } else if ((child.status ?? "active") === "active" && persistedActiveIds.has(child.id)) { + // An active child persisted across startup cannot have a live task session + // behind it. Mark it interrupted before releasing the parent's delegation + // link so the normal resume/re-delegate flow can take over. This is an + // administrative recovery, not a runtime delegation transition. + await this.repairActiveDelegation(item, child) + console.warn( + `[TaskHistoryStore] Reconciled orphaned active child: child ${child.id} → interrupted, task ${item.id} → active`, + ) + repairsInThisPass++ } else if (child.status === "completed") { await this.upsertCore( { @@ -418,12 +507,271 @@ export class TaskHistoryStore { ) repairsInThisPass++ } - // child.status === "active", "interrupted", or "delegated" → leave as-is this pass + } catch (error) { + console.error(`[TaskHistoryStore] Failed to reconcile delegation for task ${item.id}:`, error) } - } while (repairsInThisPass > 0) + // child.status === "interrupted" or "delegated" → leave as-is this pass + } + } while (repairsInThisPass > 0) + } + + private getPersistedActiveIds(): ReadonlySet { + return new Set( + Array.from(this.cache.values()) + .filter((item) => (item.status ?? "active") === "active") + .map((item) => item.id), + ) + } + + /** + * Replay the durable active-child repair intent, if one was left by a crash. + * The expected fields are guards: an intent may update only the missing side + * when the other side is already at its target, or when both records still + * describe the original delegated handoff. + * + * This method acquires the store's non-reentrant promise-chain lock. It must be + * called outside an existing `withLock` callback; locked callers must use the + * corresponding core methods directly instead of awaiting this method. + */ + private async replayDelegationRepairIntent(): Promise { + return this.withLock(async () => { + const intent = await this.readDelegationRepairIntent() + if (!intent) { + return + } + + const child = this.cache.get(intent.childTaskId) + const parent = this.cache.get(intent.parentTaskId) + if (!child || !parent) { + await this.quarantineDelegationRepairIntent( + intent, + `missing ${!child ? "child" : "parent"} task record`, + ) + return + } + + const childAtTarget = child.status === intent.target.childStatus + const parentMatchesTargetState = + parent.status === intent.target.parentStatus && + parent.awaitingChildId === undefined && + parent.delegatedToId === undefined + const childMatchesExpected = this.matchesDelegationRepairChildPreconditions(intent, child) + const parentMatchesExpected = this.matchesDelegationRepairParentPreconditions(intent, parent) + + if ((!childAtTarget && !childMatchesExpected) || (!parentMatchesTargetState && !parentMatchesExpected)) { + await this.quarantineDelegationRepairIntent(intent, "task state no longer matches its guards") + return + } + + const repairedChild = childAtTarget ? child : { ...child, status: intent.target.childStatus } + const repairedParent = parentMatchesTargetState + ? parent + : { + ...parent, + status: intent.target.parentStatus, + awaitingChildId: undefined, + delegatedToId: undefined, + } + + if (!childAtTarget) await this.writeTaskFile(repairedChild) + if (!parentMatchesTargetState) await this.writeTaskFile(repairedParent) + + this.cache.set(repairedChild.id, repairedChild) + this.cache.set(repairedParent.id, repairedParent) + + // The journal is retained until the write-through callback succeeds. + if (this.onWrite) { + await this.onWrite(this.getAll()) + } + await this.removeDelegationRepairIntent() + // Task files are authoritative and the intent is the recovery journal. + // Clean up the journal before scheduling the derived index: a crash after + // cleanup but before the index write is safe because startup rebuilds the + // index from task files, while the reverse ordering could make the index + // appear durable before recovery metadata is settled. + this.scheduleIndexWrite() }) } + /** + * Start and complete a guarded active-child repair while already holding the + * store lock. The intent is durable before either task file is touched. + */ + private async repairActiveDelegation(parent: HistoryItem, child: HistoryItem): Promise { + const intent: DelegationRepairIntent = { + version: 1, + operationId: crypto.randomUUID(), + parentTaskId: parent.id, + childTaskId: child.id, + expected: { + parent: { + status: "delegated", + awaitingChildId: child.id, + delegatedToId: parent.delegatedToId, + }, + child: { + status: "active", + parentTaskId: child.parentTaskId, + rootTaskId: child.rootTaskId, + }, + }, + target: { childStatus: "interrupted", parentStatus: "active" }, + } + + await this.writeDelegationRepairIntent(intent) + await this.applyDelegationRepairIntent(intent, child, parent) + } + + private async applyDelegationRepairIntent( + intent: DelegationRepairIntent, + child: HistoryItem, + parent: HistoryItem, + ): Promise { + const repairedChild = { ...child, status: intent.target.childStatus } + const repairedParent = { + ...parent, + status: intent.target.parentStatus, + awaitingChildId: undefined, + delegatedToId: undefined, + } + + await this.writeTaskFile(repairedChild) + await this.writeTaskFile(repairedParent) + + this.cache.set(repairedChild.id, repairedChild) + this.cache.set(repairedParent.id, repairedParent) + + if (this.onWrite) { + await this.onWrite(this.getAll()) + } + await this.removeDelegationRepairIntent() + // The index is derived state; keep the intent until authoritative task-file + // writes and write-through have completed, then schedule the index update. + this.scheduleIndexWrite() + } + + private matchesDelegationRepairParentPreconditions(intent: DelegationRepairIntent, parent: HistoryItem): boolean { + return ( + parent.status === intent.expected.parent.status && + parent.awaitingChildId === intent.expected.parent.awaitingChildId && + parent.delegatedToId === intent.expected.parent.delegatedToId + ) + } + + private matchesDelegationRepairChildPreconditions(intent: DelegationRepairIntent, child: HistoryItem): boolean { + return ( + (child.status ?? "active") === intent.expected.child.status && + child.parentTaskId === intent.expected.child.parentTaskId && + child.rootTaskId === intent.expected.child.rootTaskId + ) + } + + private async readDelegationRepairIntent(): Promise { + const intentPath = await this.getDelegationRepairIntentPath() + let parsed: unknown + try { + parsed = JSON.parse(await fs.readFile(intentPath, "utf8")) as unknown + } catch (error) { + if (this.isFileNotFoundError(error)) { + return null + } + await this.quarantineDelegationRepairIntent(null, "malformed JSON") + return null + } + + if (!this.isDelegationRepairIntent(parsed)) { + await this.quarantineDelegationRepairIntent(null, "malformed intent") + return null + } + return parsed + } + + private isDelegationRepairIntent(value: unknown): value is DelegationRepairIntent { + if (!value || typeof value !== "object") { + return false + } + const candidate = value as Record + const expected = candidate.expected + const expectedRecord = expected && typeof expected === "object" ? (expected as Record) : null + const expectedParent = + expectedRecord?.parent && typeof expectedRecord.parent === "object" + ? (expectedRecord.parent as Record) + : null + const expectedChild = + expectedRecord?.child && typeof expectedRecord.child === "object" + ? (expectedRecord.child as Record) + : null + const target = candidate.target + const targetRecord = target && typeof target === "object" ? (target as Record) : null + return ( + candidate.version === 1 && + typeof candidate.operationId === "string" && + this.isSafeTaskId(candidate.parentTaskId) && + this.isSafeTaskId(candidate.childTaskId) && + candidate.parentTaskId !== candidate.childTaskId && + !!expectedParent && + expectedParent.status === "delegated" && + typeof expectedParent.awaitingChildId === "string" && + expectedParent.awaitingChildId === candidate.childTaskId && + (expectedParent.delegatedToId === undefined || typeof expectedParent.delegatedToId === "string") && + !!expectedChild && + expectedChild.status === "active" && + (expectedChild.parentTaskId === undefined || typeof expectedChild.parentTaskId === "string") && + (expectedChild.rootTaskId === undefined || typeof expectedChild.rootTaskId === "string") && + !!targetRecord && + targetRecord.childStatus === "interrupted" && + targetRecord.parentStatus === "active" + ) + } + + private async writeDelegationRepairIntent(intent: DelegationRepairIntent): Promise { + await safeWriteJson(await this.getDelegationRepairIntentPath(), intent) + } + + private async removeDelegationRepairIntent(): Promise { + try { + await fs.unlink(await this.getDelegationRepairIntentPath()) + } catch (error) { + console.warn("[TaskHistoryStore] Failed to remove completed delegation repair intent:", error) + } + } + + private async quarantineDelegationRepairIntent( + intent: DelegationRepairIntent | null, + reason: string, + ): Promise { + const intentPath = await this.getDelegationRepairIntentPath() + const quarantinePath = `${intentPath}.quarantine-${Date.now()}-${Math.random().toString(36).slice(2)}` + try { + await fs.rename(intentPath, quarantinePath) + } catch (error) { + console.warn("[TaskHistoryStore] Failed to quarantine delegation repair intent:", error) + } + console.warn( + `[TaskHistoryStore] Ignored ${intent ? `stale delegation repair intent ${intent.operationId}` : "malformed delegation repair intent"}: ${reason}`, + ) + } + + private isSafeTaskId(value: unknown): value is string { + return ( + typeof value === "string" && + value.length > 0 && + value !== "." && + value !== ".." && + !value.includes("/") && + !value.includes("\\") + ) + } + + private isFileNotFoundError(error: unknown): boolean { + return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT" + } + + private async getDelegationRepairIntentPath(): Promise { + const tasksDir = await this.getTasksDir() + return path.join(tasksDir, GlobalFileNames.delegationRepairIntent) + } + // ────────────────────────────── Cache invalidation ────────────────────────────── /** @@ -438,6 +786,7 @@ export class TaskHistoryStore { } else { this.cache.delete(taskId) } + this.taskFileMtimes.delete(taskId) } catch { this.cache.delete(taskId) } @@ -466,40 +815,43 @@ export class TaskHistoryStore { return } - for (const item of taskHistoryEntries) { - if (!item.id) { - continue - } - - // Check if task directory exists on disk + await this.withLock(async () => { const tasksDir = await this.getTasksDir() - const taskDir = path.join(tasksDir, item.id) - try { - await fs.access(taskDir) - } catch { - // Task directory doesn't exist; skip this entry as it's orphaned in globalState - continue - } + for (const item of taskHistoryEntries) { + if (!item.id) { + continue + } - // Write history_item.json if it doesn't exist yet - const filePath = path.join(taskDir, GlobalFileNames.historyItem) - try { - await fs.access(filePath) - // File already exists, skip (don't overwrite existing per-task files) - } catch { - // File doesn't exist, write it - await safeWriteJson(filePath, item) - this.cache.set(item.id, item) + // Check if task directory exists on disk + const taskDir = path.join(tasksDir, item.id) + + try { + await fs.access(taskDir) + } catch { + // Task directory doesn't exist; skip this entry as it's orphaned in globalState + continue + } + + // Write history_item.json if it doesn't exist yet + const filePath = path.join(taskDir, GlobalFileNames.historyItem) + try { + await fs.access(filePath) + // File already exists, skip (don't overwrite existing per-task files) + } catch { + // File doesn't exist, write it + await safeWriteJson(filePath, item) + this.cache.set(item.id, item) + } } - } - // Write the index - await this.writeIndex() + // Write the index + await this.writeIndex() - // Repair any delegation inconsistencies introduced by the migrated entries. - // reconcileDelegationState() is idempotent so running it again is safe. - await this.reconcileDelegationState() + // Repair any delegation inconsistencies introduced by the migrated entries. + // Run the lock-free core because migration already holds the store lock. + await this.reconcileDelegationStateCore(this.getPersistedActiveIds()) + }) } // ────────────────────────────── Private: Index management ────────────────────────────── diff --git a/src/core/task-persistence/__tests__/TaskHistoryStore.reconciliation.spec.ts b/src/core/task-persistence/__tests__/TaskHistoryStore.reconciliation.spec.ts index 2888c0f7b2..e788b5d96a 100644 --- a/src/core/task-persistence/__tests__/TaskHistoryStore.reconciliation.spec.ts +++ b/src/core/task-persistence/__tests__/TaskHistoryStore.reconciliation.spec.ts @@ -6,18 +6,23 @@ import * as os from "os" import type { HistoryItem } from "@roo-code/types" +import { GlobalFileNames } from "../../../shared/globalFileNames" import { TaskHistoryStore, assertValidTransition } from "../TaskHistoryStore" vi.mock("../../../utils/storage", () => ({ getStorageBasePath: vi.fn().mockImplementation((defaultPath: string) => defaultPath), })) -vi.mock("../../../utils/safeWriteJson", () => ({ - safeWriteJson: vi.fn().mockImplementation(async (filePath: string, data: any) => { - await fs.mkdir(path.dirname(filePath), { recursive: true }) - await fs.writeFile(filePath, JSON.stringify(data, null, "\t"), "utf8") - }), -})) +const writeJson = async (filePath: string, data: unknown): Promise => { + await fs.mkdir(path.dirname(filePath), { recursive: true }) + await fs.writeFile(filePath, JSON.stringify(data, null, "\t"), "utf8") +} + +const safeWriteJsonMock = vi.hoisted(() => vi.fn()) + +vi.mock("../../../utils/safeWriteJson", () => ({ safeWriteJson: safeWriteJsonMock })) + +safeWriteJsonMock.mockImplementation(writeJson) function makeItem(overrides: Partial = {}): HistoryItem { return { @@ -32,6 +37,28 @@ function makeItem(overrides: Partial = {}): HistoryItem { } } +function makeRepairIntent(parent: HistoryItem, child: HistoryItem): object { + return { + version: 1, + operationId: "delegation-repair-test", + parentTaskId: parent.id, + childTaskId: child.id, + expected: { + parent: { + status: "delegated", + awaitingChildId: child.id, + delegatedToId: parent.delegatedToId, + }, + child: { + status: "active", + parentTaskId: child.parentTaskId, + rootTaskId: child.rootTaskId, + }, + }, + target: { childStatus: "interrupted", parentStatus: "active" }, + } +} + // ───────────────────────────────────────────────────────────────────────────── // assertValidTransition — pure function tests // ───────────────────────────────────────────────────────────────────────────── @@ -117,6 +144,12 @@ describe("assertValidTransition", () => { describe("TaskHistoryStore reconcileDelegationState", () => { let tmpDir: string let store: TaskHistoryStore + const disposables = new Set() + + function registerStore(nextStore: TaskHistoryStore): TaskHistoryStore { + disposables.add(nextStore) + return nextStore + } async function seedItems(items: HistoryItem[]): Promise { const tasksDir = path.join(tmpDir, "tasks") @@ -130,11 +163,13 @@ describe("TaskHistoryStore reconcileDelegationState", () => { beforeEach(async () => { tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "reconcile-test-")) - store = new TaskHistoryStore(tmpDir) + store = registerStore(new TaskHistoryStore(tmpDir)) }) afterEach(async () => { - store.dispose() + safeWriteJsonMock.mockImplementation(writeJson) + for (const disposable of disposables) disposable.dispose() + disposables.clear() await fs.rm(tmpDir, { recursive: true, force: true }).catch(() => {}) }) @@ -185,16 +220,397 @@ describe("TaskHistoryStore reconcileDelegationState", () => { expect(repaired?.completionResultSummary).toBe("Task completed (recovered after interruption)") }) - it("leaves delegated parent alone when child is still active", async () => { - const child = makeItem({ id: "child-4", status: "active" }) - const parent = makeItem({ id: "parent-4", status: "delegated", awaitingChildId: "child-4" }) + it("repairs a delegated parent with an active orphaned child", async () => { + const child = makeItem({ + id: "child-4", + status: "active", + parentTaskId: "parent-4", + rootTaskId: "parent-4", + childIds: ["grandchild-4"], + }) + const parent = makeItem({ + id: "parent-4", + status: "delegated", + awaitingChildId: "child-4", + delegatedToId: "child-4", + childIds: ["child-4"], + }) + await seedItems([parent, child]) + + await store.initialize() + + const repairedParent = store.get("parent-4") + const repairedChild = store.get("child-4") + expect(repairedChild).toMatchObject({ + id: "child-4", + status: "interrupted", + parentTaskId: "parent-4", + rootTaskId: "parent-4", + childIds: ["grandchild-4"], + }) + expect(repairedParent).toMatchObject({ + id: "parent-4", + status: "active", + childIds: ["child-4"], + }) + expect(repairedParent?.awaitingChildId).toBeUndefined() + expect(repairedParent?.delegatedToId).toBeUndefined() + + const tasksDir = path.join(tmpDir, "tasks") + const persistedChild = JSON.parse( + await fs.readFile(path.join(tasksDir, "child-4", "history_item.json"), "utf8"), + ) as HistoryItem + const persistedParent = JSON.parse( + await fs.readFile(path.join(tasksDir, "parent-4", "history_item.json"), "utf8"), + ) as HistoryItem + expect(persistedChild).toMatchObject({ + id: "child-4", + status: "interrupted", + parentTaskId: "parent-4", + rootTaskId: "parent-4", + childIds: ["grandchild-4"], + }) + expect(persistedParent).toMatchObject({ id: "parent-4", status: "active" }) + expect(persistedParent.awaitingChildId).toBeUndefined() + expect(persistedParent.delegatedToId).toBeUndefined() + }) + + it("repairs a delegated child with an omitted status as implicit active", async () => { + const child = makeItem({ + id: "child-implicit-active", + parentTaskId: "parent-implicit-active", + rootTaskId: "parent-implicit-active", + }) + const parent = makeItem({ + id: "parent-implicit-active", + status: "delegated", + awaitingChildId: child.id, + delegatedToId: child.id, + }) + await seedItems([parent, child]) + + await store.initialize() + + expect(store.get(child.id)).toMatchObject({ id: child.id, status: "interrupted" }) + expect(store.get(parent.id)).toMatchObject({ id: parent.id, status: "active" }) + expect(store.get(parent.id)?.awaitingChildId).toBeUndefined() + expect(store.get(parent.id)?.delegatedToId).toBeUndefined() + + const persistedChild = JSON.parse( + await fs.readFile(path.join(tmpDir, "tasks", child.id, GlobalFileNames.historyItem), "utf8"), + ) as HistoryItem + expect(persistedChild.status).toBe("interrupted") + }) + + it("replays an intent after a child-only write and removes it after completion", async () => { + const child = makeItem({ id: "child-replay", status: "active", parentTaskId: "parent-replay" }) + const parent = makeItem({ + id: "parent-replay", + status: "delegated", + awaitingChildId: child.id, + delegatedToId: child.id, + }) + await seedItems([parent, child]) + const intentPath = path.join(tmpDir, "tasks", GlobalFileNames.delegationRepairIntent) + await fs.writeFile(intentPath, JSON.stringify(makeRepairIntent(parent, child))) + await fs.writeFile( + path.join(tmpDir, "tasks", child.id, GlobalFileNames.historyItem), + JSON.stringify({ ...child, status: "interrupted" }), + ) + + await store.initialize() + + expect(store.get(child.id)?.status).toBe("interrupted") + expect(store.get(parent.id)?.status).toBe("active") + const persistedChild = JSON.parse( + await fs.readFile(path.join(tmpDir, "tasks", child.id, GlobalFileNames.historyItem), "utf8"), + ) as HistoryItem + const persistedParent = JSON.parse( + await fs.readFile(path.join(tmpDir, "tasks", parent.id, GlobalFileNames.historyItem), "utf8"), + ) as HistoryItem + expect(persistedChild).toMatchObject({ id: child.id, status: "interrupted" }) + expect(persistedParent).toMatchObject({ id: parent.id, status: "active" }) + expect(persistedParent.awaitingChildId).toBeUndefined() + expect(persistedParent.delegatedToId).toBeUndefined() + await expect(fs.access(intentPath)).rejects.toThrow() + }) + + it("replays an intent after a failure before the child write", async () => { + const child = makeItem({ + id: "child-fault-before-child", + status: "active", + parentTaskId: "parent-fault-before-child", + }) + const parent = makeItem({ + id: "parent-fault-before-child", + status: "delegated", + awaitingChildId: child.id, + delegatedToId: child.id, + }) + await seedItems([parent, child]) + safeWriteJsonMock.mockImplementation(async (filePath, data) => { + if (filePath.includes(child.id) && filePath.endsWith(GlobalFileNames.historyItem)) + throw new Error("fault before child write") + await writeJson(filePath, data) + }) + await expect(store.initialize()).resolves.toBeUndefined() + store.dispose() + safeWriteJsonMock.mockImplementation(writeJson) + const replayedStore = registerStore(new TaskHistoryStore(tmpDir)) + await replayedStore.initialize() + expect(replayedStore.get(child.id)?.status).toBe("interrupted") + expect(replayedStore.get(parent.id)?.status).toBe("active") + const persistedChild = JSON.parse( + await fs.readFile(path.join(tmpDir, "tasks", child.id, GlobalFileNames.historyItem), "utf8"), + ) as HistoryItem + const persistedParent = JSON.parse( + await fs.readFile(path.join(tmpDir, "tasks", parent.id, GlobalFileNames.historyItem), "utf8"), + ) as HistoryItem + expect(persistedChild).toMatchObject({ id: child.id, status: "interrupted" }) + expect(persistedParent).toMatchObject({ id: parent.id, status: "active" }) + expect(persistedParent.awaitingChildId).toBeUndefined() + expect(persistedParent.delegatedToId).toBeUndefined() + }) + + it("replays an intent after a failure before the parent write", async () => { + const child = makeItem({ + id: "child-fault-before-parent", + status: "active", + parentTaskId: "parent-fault-before-parent", + }) + const parent = makeItem({ + id: "parent-fault-before-parent", + status: "delegated", + awaitingChildId: child.id, + delegatedToId: child.id, + }) + await seedItems([parent, child]) + safeWriteJsonMock.mockImplementation(async (filePath, data) => { + if (filePath.includes(parent.id) && filePath.endsWith(GlobalFileNames.historyItem)) + throw new Error("fault before parent write") + await writeJson(filePath, data) + }) + await expect(store.initialize()).resolves.toBeUndefined() + store.dispose() + safeWriteJsonMock.mockImplementation(writeJson) + const replayedStore = registerStore(new TaskHistoryStore(tmpDir)) + await replayedStore.initialize() + expect(replayedStore.get(child.id)?.status).toBe("interrupted") + expect(replayedStore.get(parent.id)?.status).toBe("active") + const persistedChild = JSON.parse( + await fs.readFile(path.join(tmpDir, "tasks", child.id, GlobalFileNames.historyItem), "utf8"), + ) as HistoryItem + const persistedParent = JSON.parse( + await fs.readFile(path.join(tmpDir, "tasks", parent.id, GlobalFileNames.historyItem), "utf8"), + ) as HistoryItem + expect(persistedChild).toMatchObject({ id: child.id, status: "interrupted" }) + expect(persistedParent).toMatchObject({ id: parent.id, status: "active" }) + expect(persistedParent.awaitingChildId).toBeUndefined() + expect(persistedParent.delegatedToId).toBeUndefined() + }) + + it("retains an intent when the callback fails after both writes", async () => { + const child = makeItem({ id: "child-fault-cleanup", status: "active", parentTaskId: "parent-fault-cleanup" }) + const parent = makeItem({ + id: "parent-fault-cleanup", + status: "delegated", + awaitingChildId: child.id, + delegatedToId: child.id, + }) + await seedItems([parent, child]) + store.dispose() + store = registerStore( + new TaskHistoryStore(tmpDir, { onWrite: vi.fn().mockRejectedValue(new Error("fault before cleanup")) }), + ) + await expect(store.initialize()).resolves.toBeUndefined() + const intentPath = path.join(tmpDir, "tasks", GlobalFileNames.delegationRepairIntent) + expect(await fs.readFile(intentPath, "utf8")).toContain(child.id) + store.dispose() + safeWriteJsonMock.mockImplementation(writeJson) + const replayedStore = registerStore(new TaskHistoryStore(tmpDir)) + await replayedStore.initialize() + expect(replayedStore.get(child.id)?.status).toBe("interrupted") + expect(replayedStore.get(parent.id)?.status).toBe("active") + const persistedChild = JSON.parse( + await fs.readFile(path.join(tmpDir, "tasks", child.id, GlobalFileNames.historyItem), "utf8"), + ) as HistoryItem + const persistedParent = JSON.parse( + await fs.readFile(path.join(tmpDir, "tasks", parent.id, GlobalFileNames.historyItem), "utf8"), + ) as HistoryItem + expect(persistedChild).toMatchObject({ id: child.id, status: "interrupted" }) + expect(persistedParent).toMatchObject({ id: parent.id, status: "active" }) + expect(persistedParent.awaitingChildId).toBeUndefined() + expect(persistedParent.delegatedToId).toBeUndefined() + await expect(fs.access(intentPath)).rejects.toThrow() + }) + + it("replays a both-at-target intent without writing task files", async () => { + const child = makeItem({ id: "child-at-target", status: "interrupted", parentTaskId: "parent-at-target" }) + const parent = makeItem({ id: "parent-at-target", status: "active" }) await seedItems([parent, child]) + const intentPath = path.join(tmpDir, "tasks", GlobalFileNames.delegationRepairIntent) + await fs.writeFile( + intentPath, + JSON.stringify(makeRepairIntent({ ...parent, status: "delegated", awaitingChildId: child.id }, child)), + ) + + const writeCalls: string[] = [] + safeWriteJsonMock.mockImplementation(async (filePath, data) => { + writeCalls.push(filePath) + await writeJson(filePath, data) + }) + await store.initialize() + + expect(writeCalls.filter((filePath) => filePath.endsWith(GlobalFileNames.historyItem))).toEqual([]) + await expect(fs.access(intentPath)).rejects.toThrow() + }) + + it("does not schedule the derived index before repair-intent cleanup succeeds", async () => { + const child = makeItem({ id: "child-deferred-index", status: "active", parentTaskId: "parent-deferred-index" }) + const parent = makeItem({ + id: "parent-deferred-index", + status: "delegated", + awaitingChildId: child.id, + delegatedToId: child.id, + }) + await seedItems([parent, child]) + const intentPath = path.join(tmpDir, "tasks", GlobalFileNames.delegationRepairIntent) + await fs.writeFile(intentPath, JSON.stringify(makeRepairIntent(parent, child))) + await store.reconcile({ forceRefresh: true }) + + const events: string[] = [] + const storeInternals = store as unknown as { + scheduleIndexWrite: () => void + removeDelegationRepairIntent: () => Promise + replayDelegationRepairIntent: () => Promise + } + vi.spyOn(storeInternals, "removeDelegationRepairIntent").mockImplementation(async () => { + events.push("cleanup") + await fs.unlink(intentPath) + }) + vi.spyOn(storeInternals, "scheduleIndexWrite").mockImplementation(() => { + events.push("schedule") + }) + + await storeInternals.replayDelegationRepairIntent() + + expect(events).toEqual(["cleanup", "schedule"]) + await expect(fs.access(intentPath)).rejects.toThrow() + }) + + it("quarantines malformed and stale intents without blocking unrelated startup", async () => { + const unrelated = makeItem({ id: "unrelated-startup", status: "active" }) + await seedItems([unrelated]) + const tasksDir = path.join(tmpDir, "tasks") + const intentPath = path.join(tasksDir, GlobalFileNames.delegationRepairIntent) + await fs.writeFile(intentPath, JSON.stringify({ malformed: true })) + + await store.initialize() + + expect(store.get(unrelated.id)?.status).toBe("active") + expect( + (await fs.readdir(tasksDir)).some((name) => + name.startsWith(`${GlobalFileNames.delegationRepairIntent}.quarantine-`), + ), + ).toBe(true) + await expect(fs.access(intentPath)).rejects.toThrow() + }) + + it("quarantines an intent with a missing task record without changing unrelated startup", async () => { + const unrelated = makeItem({ id: "unrelated-missing-intent", status: "active" }) + const missingChild = makeItem({ id: "missing-intent-child", status: "active" }) + const parent = makeItem({ id: "missing-intent-parent", status: "delegated", awaitingChildId: missingChild.id }) + await seedItems([unrelated]) + const tasksDir = path.join(tmpDir, "tasks") + const intentPath = path.join(tasksDir, GlobalFileNames.delegationRepairIntent) + await fs.writeFile(intentPath, JSON.stringify(makeRepairIntent(parent, missingChild))) + + await store.initialize() + + expect(store.get(unrelated.id)?.status).toBe("active") + expect(store.get(parent.id)).toBeUndefined() + expect( + (await fs.readdir(tasksDir)).some((name) => + name.startsWith(`${GlobalFileNames.delegationRepairIntent}.quarantine-`), + ), + ).toBe(true) + await expect(fs.access(intentPath)).rejects.toThrow() + }) + + it("quarantines an intent when the parent no longer matches its repair guard", async () => { + const child = makeItem({ + id: "mismatched-intent-child", + status: "interrupted", + parentTaskId: "mismatched-intent-parent", + }) + const parent = makeItem({ + id: "mismatched-intent-parent", + status: "completed", + awaitingChildId: child.id, + delegatedToId: child.id, + }) + await seedItems([parent, child]) + const tasksDir = path.join(tmpDir, "tasks") + const intentPath = path.join(tasksDir, GlobalFileNames.delegationRepairIntent) + await fs.writeFile(intentPath, JSON.stringify(makeRepairIntent({ ...parent, status: "delegated" }, child))) + const childPath = path.join(tasksDir, child.id, GlobalFileNames.historyItem) + const parentPath = path.join(tasksDir, parent.id, GlobalFileNames.historyItem) + const beforeChild = await fs.readFile(childPath, "utf8") + const beforeParent = await fs.readFile(parentPath, "utf8") + + await store.initialize() + + expect(store.get(child.id)?.status).toBe("interrupted") + expect(store.get(parent.id)?.status).toBe("completed") + expect(await fs.readFile(childPath, "utf8")).toBe(beforeChild) + expect(await fs.readFile(parentPath, "utf8")).toBe(beforeParent) + expect( + (await fs.readdir(tasksDir)).some((name) => + name.startsWith(`${GlobalFileNames.delegationRepairIntent}.quarantine-`), + ), + ).toBe(true) + await expect(fs.access(intentPath)).rejects.toThrow() + }) + + it("quarantines an intent when the child no longer matches its repair guard", async () => { + const child = makeItem({ + id: "child-mismatched-intent", + status: "completed", + parentTaskId: "mismatched-child-parent", + }) + const parent = makeItem({ + id: "parent-mismatched-child-intent", + status: "active", + }) + await seedItems([parent, child]) + const tasksDir = path.join(tmpDir, "tasks") + const intentPath = path.join(tasksDir, GlobalFileNames.delegationRepairIntent) + await fs.writeFile( + intentPath, + JSON.stringify( + makeRepairIntent( + { ...parent, status: "delegated", awaitingChildId: child.id, delegatedToId: child.id }, + { ...child, status: "active" }, + ), + ), + ) + const childPath = path.join(tasksDir, child.id, GlobalFileNames.historyItem) + const parentPath = path.join(tasksDir, parent.id, GlobalFileNames.historyItem) + const beforeChild = await fs.readFile(childPath, "utf8") + const beforeParent = await fs.readFile(parentPath, "utf8") await store.initialize() - const unchanged = store.get("parent-4") - expect(unchanged?.status).toBe("delegated") - expect(unchanged?.awaitingChildId).toBe("child-4") + expect(store.get(child.id)?.status).toBe("completed") + expect(store.get(parent.id)?.status).toBe("active") + expect(await fs.readFile(childPath, "utf8")).toBe(beforeChild) + expect(await fs.readFile(parentPath, "utf8")).toBe(beforeParent) + await expect(fs.access(intentPath)).rejects.toThrow() + expect( + (await fs.readdir(tasksDir)).some((name) => + name.startsWith(`${GlobalFileNames.delegationRepairIntent}.quarantine-`), + ), + ).toBe(true) }) it("repairs invalid delegation: delegated parent with no awaitingChildId → active (clears delegatedToId and awaitingChildId)", async () => { @@ -204,7 +620,7 @@ describe("TaskHistoryStore reconcileDelegationState", () => { status: "delegated", delegatedToId: "stale-child", awaitingChildId: "", - } as any) + }) await seedItems([parent]) await store.initialize() @@ -239,9 +655,9 @@ describe("TaskHistoryStore reconcileDelegationState", () => { expect(store.get("parent-b")?.status).toBe("active") }) - it("handles chained delegation (A→B→C): repairs B first, then A sees B as active and is left delegated", async () => { + it("repairs an orphaned link in a chained delegation without repairing its grandparent", async () => { // C doesn't exist (orphaned). B is delegated waiting for C → repaired to active. - // A is delegated waiting for B → left delegated (B is now active, resumable by user). + // A sees B as delegated in the persisted startup snapshot and remains delegated. const parentA = makeItem({ id: "parent-a-chain", status: "delegated", awaitingChildId: "parent-b-chain" }) const parentB = makeItem({ id: "parent-b-chain", @@ -254,9 +670,101 @@ describe("TaskHistoryStore reconcileDelegationState", () => { // B is repaired: its child (C) was missing expect(store.get("parent-b-chain")?.status).toBe("active") - // A stays delegated: its child (B) is now active, which is a valid state + // A stays delegated: B was repaired from delegated to active and remains + // resumable rather than being mistaken for an active orphan from disk. expect(store.get("parent-a-chain")?.status).toBe("delegated") expect(store.get("parent-a-chain")?.awaitingChildId).toBe("parent-b-chain") + expect(store.get("parent-b-chain")?.status).toBe("active") + expect(store.get("parent-b-chain")?.awaitingChildId).toBeUndefined() + }) + + it("does not repair a grandparent when replay repairs the middle node", async () => { + const grandparent = makeItem({ + id: "grandparent-replay-chain", + status: "delegated", + awaitingChildId: "parent-replay-chain", + delegatedToId: "parent-replay-chain", + }) + const parent = makeItem({ + id: "parent-replay-chain", + status: "delegated", + awaitingChildId: "child-replay-chain", + delegatedToId: "child-replay-chain", + parentTaskId: grandparent.id, + rootTaskId: grandparent.id, + }) + const child = makeItem({ + id: "child-replay-chain", + status: "active", + parentTaskId: parent.id, + rootTaskId: grandparent.id, + }) + await seedItems([grandparent, parent, child]) + const intentPath = path.join(tmpDir, "tasks", GlobalFileNames.delegationRepairIntent) + await fs.writeFile(intentPath, JSON.stringify(makeRepairIntent(parent, child))) + + await store.initialize() + + // Replay repairs B/C, but B was delegated at the persisted startup snapshot. + // A must remain delegated to the now-interrupted/resumable B. + expect(store.get(grandparent.id)).toMatchObject({ + id: grandparent.id, + status: "delegated", + awaitingChildId: parent.id, + delegatedToId: parent.id, + }) + expect(store.get(parent.id)).toMatchObject({ id: parent.id, status: "active" }) + expect(store.get(parent.id)?.awaitingChildId).toBeUndefined() + expect(store.get(parent.id)?.delegatedToId).toBeUndefined() + expect(store.get(child.id)).toMatchObject({ id: child.id, status: "interrupted" }) + + const persistedGrandparent = JSON.parse( + await fs.readFile(path.join(tmpDir, "tasks", grandparent.id, GlobalFileNames.historyItem), "utf8"), + ) as HistoryItem + const persistedParent = JSON.parse( + await fs.readFile(path.join(tmpDir, "tasks", parent.id, GlobalFileNames.historyItem), "utf8"), + ) as HistoryItem + const persistedChild = JSON.parse( + await fs.readFile(path.join(tmpDir, "tasks", child.id, GlobalFileNames.historyItem), "utf8"), + ) as HistoryItem + expect(persistedGrandparent).toMatchObject({ + id: grandparent.id, + status: "delegated", + awaitingChildId: parent.id, + delegatedToId: parent.id, + }) + expect(persistedParent).toMatchObject({ id: parent.id, status: "active" }) + expect(persistedParent.awaitingChildId).toBeUndefined() + expect(persistedParent.delegatedToId).toBeUndefined() + expect(persistedChild).toMatchObject({ id: child.id, status: "interrupted" }) + await expect(fs.access(intentPath)).rejects.toThrow() + }) + + it("is idempotent when recovering an active child", async () => { + const child = makeItem({ id: "child-active-idempotent", status: "active" }) + const parent = makeItem({ + id: "parent-active-idempotent", + status: "delegated", + awaitingChildId: child.id, + delegatedToId: child.id, + }) + await seedItems([parent, child]) + + await store.initialize() + const afterFirstParent = { ...store.get(parent.id) } + const afterFirstChild = { ...store.get(child.id) } + + store.dispose() + const store2 = registerStore(new TaskHistoryStore(tmpDir)) + await store2.initialize() + const afterSecondParent = { ...store2.get(parent.id) } + const afterSecondChild = { ...store2.get(child.id) } + store2.dispose() + + expect(afterFirstParent).toMatchObject({ status: "active" }) + expect(afterSecondParent).toEqual(afterFirstParent) + expect(afterFirstChild).toMatchObject({ status: "interrupted" }) + expect(afterSecondChild).toEqual(afterFirstChild) }) it("is idempotent: running initialize twice produces the same result", async () => { @@ -268,7 +776,7 @@ describe("TaskHistoryStore reconcileDelegationState", () => { const afterFirst = { ...store.get("parent-6") } store.dispose() - const store2 = new TaskHistoryStore(tmpDir) + const store2 = registerStore(new TaskHistoryStore(tmpDir)) await store2.initialize() const afterSecond = { ...store2.get("parent-6") } store2.dispose() @@ -296,7 +804,7 @@ describe("TaskHistoryStore reconcileDelegationState", () => { it("invokes onWrite callback after startup repairs", async () => { const onWrite = vi.fn().mockResolvedValue(undefined) store.dispose() - store = new TaskHistoryStore(tmpDir, { onWrite }) + store = registerStore(new TaskHistoryStore(tmpDir, { onWrite })) const parent = makeItem({ id: "parent-onwrite", status: "delegated", awaitingChildId: "nonexistent-child" }) await seedItems([parent]) @@ -407,7 +915,7 @@ describe("TaskHistoryStore upsert transition guard", () => { it("rejects delegated → completed transition", async () => { // Must include a live active child so reconciliation doesn't repair the parent to active - const child = makeItem({ id: "child-guard-2", status: "active" }) + const child = makeItem({ id: "child-guard-2", status: "interrupted" }) const item = makeItem({ id: "task-guard-2", status: "delegated", awaitingChildId: "child-guard-2" }) await seedItems([child, item]) store.dispose() @@ -470,8 +978,8 @@ describe("TaskHistoryStore upsert transition guard", () => { // Legacy items pre-dating the status field have status: undefined, which normalizes // to "active". Writing status: "active" must not throw as an invalid self-loop. const item = makeItem({ id: "task-guard-legacy" }) - delete (item as any).status - await seedItems([item]) + const { status: _status, ...legacyItem } = item + await seedItems([legacyItem]) store.dispose() store = new TaskHistoryStore(tmpDir) await store.initialize() diff --git a/src/core/task-persistence/__tests__/TaskHistoryStore.spec.ts b/src/core/task-persistence/__tests__/TaskHistoryStore.spec.ts index 3b7e9041a4..3188e9c505 100644 --- a/src/core/task-persistence/__tests__/TaskHistoryStore.spec.ts +++ b/src/core/task-persistence/__tests__/TaskHistoryStore.spec.ts @@ -373,6 +373,46 @@ describe("TaskHistoryStore", () => { expect(store.get("idem-task")).toBeDefined() }) + + it("serializes migration cache and index updates behind the store lock", async () => { + const tasksDir = path.join(tmpDir, "tasks") + const migrated = makeHistoryItem({ id: "migration-locked" }) + const concurrent = makeHistoryItem({ id: "migration-concurrent" }) + const migratedFile = path.join(tasksDir, migrated.id, GlobalFileNames.historyItem) + await fs.mkdir(path.dirname(migratedFile), { recursive: true }) + + let releaseMigrationWrite!: () => void + const migrationWriteCanFinish = new Promise((resolve) => { + releaseMigrationWrite = resolve + }) + let signalMigrationWriteStarted!: () => void + const migrationWriteStarted = new Promise((resolve) => { + signalMigrationWriteStarted = resolve + }) + const storeInternals = store as unknown as { writeIndex: () => Promise } + const originalWriteIndex = storeInternals.writeIndex.bind(store) + vi.spyOn(storeInternals, "writeIndex").mockImplementation(async () => { + signalMigrationWriteStarted() + await migrationWriteCanFinish + return originalWriteIndex() + }) + + const migration = store.migrateFromGlobalState([migrated]) + await migrationWriteStarted + const concurrentUpsert = store.upsert(concurrent) + + expect(store.get(concurrent.id)).toBeUndefined() + releaseMigrationWrite() + await Promise.all([migration, concurrentUpsert]) + + expect(store.get(migrated.id)).toEqual(migrated) + expect(store.get(concurrent.id)).toEqual(concurrent) + await store.flushIndex() + const index = JSON.parse(await fs.readFile(path.join(tasksDir, GlobalFileNames.historyIndex), "utf8")) as { + entries: HistoryItem[] + } + expect(index.entries.map((entry) => entry.id)).toEqual(expect.arrayContaining([migrated.id, concurrent.id])) + }) }) describe("flushIndex()", () => { diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 20ff599a35..2d3e425f12 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -198,6 +198,7 @@ export class ClineProvider private static readonly GLOBAL_STATE_WRITE_THROUGH_DEBOUNCE_MS = 5000 // 5 seconds public static readonly PENDING_OPERATION_TIMEOUT_MS = 30000 // 30 seconds private providerProfileMutationQueue = Promise.resolve() + private historyTaskCreationQueue = Promise.resolve() private runDelegationTransition(parentTaskId: string, fn: () => Promise): Promise { this.delegationTransitionLocks ??= new Map() @@ -1113,10 +1114,31 @@ export class ClineProvider await this.handleZooCodeCallback(token) } - public async createTaskWithHistoryItem( + public createTaskWithHistoryItem( historyItem: HistoryItem & { rootTask?: Task; parentTask?: Task }, options?: { startTask?: boolean }, - ) { + ): Promise { + // History navigation can arrive concurrently (for example, two rapid + // showTaskWithId messages). Serialize the full eviction/installation + // transition so both callers cannot observe the same previous registry + // state and schedule distinct Task instances for one history item. + // Fail forward so one rejected restoration does not poison the queue. + const previous = this.historyTaskCreationQueue ?? Promise.resolve() + const run = previous.then( + () => ClineProvider.prototype.createTaskWithHistoryItemUnlocked.call(this, historyItem, options), + () => ClineProvider.prototype.createTaskWithHistoryItemUnlocked.call(this, historyItem, options), + ) + this.historyTaskCreationQueue = run.then( + () => {}, + () => {}, + ) + return run + } + + private async createTaskWithHistoryItemUnlocked( + historyItem: HistoryItem & { rootTask?: Task; parentTask?: Task }, + options?: { startTask?: boolean }, + ): Promise { const isCliRuntime = process.env.ROO_CLI_RUNTIME === "1" // CLI injects runtime provider settings from command flags/env at startup. // Restoring provider profiles from task history can overwrite those diff --git a/src/eslint-suppressions.json b/src/eslint-suppressions.json index 569c846c29..87ff0dfec5 100644 --- a/src/eslint-suppressions.json +++ b/src/eslint-suppressions.json @@ -784,11 +784,6 @@ "count": 1 } }, - "core/task-persistence/__tests__/TaskHistoryStore.reconciliation.spec.ts": { - "@typescript-eslint/no-explicit-any": { - "count": 3 - } - }, "core/task-persistence/__tests__/TaskHistoryStore.spec.ts": { "@typescript-eslint/no-explicit-any": { "count": 4 diff --git a/src/shared/globalFileNames.ts b/src/shared/globalFileNames.ts index 0b54ff6809..7bfe18f4bc 100644 --- a/src/shared/globalFileNames.ts +++ b/src/shared/globalFileNames.ts @@ -6,4 +6,5 @@ export const GlobalFileNames = { taskMetadata: "task_metadata.json", historyItem: "history_item.json", historyIndex: "_index.json", + delegationRepairIntent: "_delegation_repair_intent.json", } From 73602a91c38989c9d282f4d9f7b82e6ecdcc694c Mon Sep 17 00:00:00 2001 From: Para <62068271+murd0cc@users.noreply.github.com> Date: Sun, 16 Aug 2026 20:48:58 +0300 Subject: [PATCH 15/66] fixed screenshots --- ...o-approve-followup-timeout-disabled-dark.png | Bin 205 -> 0 bytes .../model-info-service-tier-pricing-dark.png | Bin 18087 -> 0 bytes .../__screenshots__/screenshot (1).jpg | Bin 0 -> 43544 bytes .../__screenshots__/screenshot (2).jpg | Bin 0 -> 33097 bytes .../__screenshots__/screenshot (3).jpg | Bin 0 -> 43262 bytes 5 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/auto-approve-followup-timeout-disabled-dark.png delete mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/model-info-service-tier-pricing-dark.png create mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (1).jpg create mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (2).jpg create mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (3).jpg diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/auto-approve-followup-timeout-disabled-dark.png b/webview-ui/src/components/settings/__tests__/__screenshots__/auto-approve-followup-timeout-disabled-dark.png deleted file mode 100644 index db87f68911f60194136207b64222fe42540967af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 205 zcmeAS@N?(olHy`uVBq!ia0y~yVB!F>6*!oH* k|8@~+mw~Qf1G$Eofo~1NT#m%>1wau7Pgg&ebxsLQ04Fjnga7~l diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/model-info-service-tier-pricing-dark.png b/webview-ui/src/components/settings/__tests__/__screenshots__/model-info-service-tier-pricing-dark.png deleted file mode 100644 index 0a3bee53510b9ab9282bd0e1c910a2b2e58f0a66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18087 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 diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (1).jpg b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (1).jpg new file mode 100644 index 0000000000000000000000000000000000000000..7694412f7e4f468813057631c6873e0ec2dc0bc9 GIT binary patch literal 43544 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 z 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 literal 0 HcmV?d00001 diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (2).jpg b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (2).jpg new file mode 100644 index 0000000000000000000000000000000000000000..6eb5f1688cb6451fc2d75188d16107a4d61891ff GIT binary patch literal 33097 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≈z*2>`uAb_-Rp(*Px+twC$lr{M4!fHuf|E>sbpI>Ok1wp*XE!g zHhEiHA!YsaS`6hAbFE;H7|tU$CXKMWqvYoAWiQ0lc(4SlHsy?Rr%Q(vK7Fd^s(nze zVDqOHGUHi3LLqZX&JHDFoqbe#gGDr5&6P5O*pX8(-!%C)iCgsUm%#D1zJ<9RBnBaYb|l>DljevE6$4d=ERkuoU+C7Rf!F_Q)? z{3aT+&2g?>l`Xc*TNI8jDSYZ?k@}Sw%$;C%5Zn3~r`4vl{no7cmzlrFu@bH5JTql~NKkDsgyyDT#jZxBLHu=bh*m-(WpLj$EJ? z7S;a#p!XNLZ^pRj3dcopuQMo&L zWH?&5>FAZL9WMD+f^osW!^LP=mmfDMK<_4WzRCT`n{5(t{YX;r_>k;6RN&=j((fv0 zhh;5`&Xe=0%zQOBCm+UYWLQhEmQ0Vj`-ikc23&7l)9gTURH-3qoB0;%B{U-;;uTN= z`9gDWqt-M221}Dd*78em)%>=Mt%STt?1Z-h4{9>4!=KjEq0EKY`4;7{Z zm-+TcL0@}hH{zoOxFC&j`L2n#(+1n6k$rDGSLme|UagpoWPhvBMwfV!=$@n}IWhV5 zz_prMAc@Da?n#|Ql(9`&0YxN99z7m8$Bh^2j>dXxo!Rtba;ns|#YUTOUfVRo(C76B zcZzk)xv-z-JU)z1?`tauM*W)If6BKWM1t;p=A=l5cHisD@LR72k=na}b2iyn5Z)~l z$=p}3WL=9Ab7Wu`juYU$XDBfrX2xVd1I%h%;C8{s9JY5PDHCtN&HO3~_MfCUTP}tB zN0cgr)>&$7RtCLidL|+^9NTBs zj}?Gs&55A&kjQyAkZhb|XMBx|+S!YdGqG8mlQ996SIp)ET)VAsA2>e^@xvLVKLrpi zIGhJ{?mR)7qeFqE8sF@FZm=97ndY_j6sXi!Ay`C%Y?g@@}Wb6dN2bP;pZg zOGDgR^nu%VnM6m7LzV%cB!tpQ*mE4?EC_)|zdSmBwdZp}dO3%^9q3cYSe0&kIzHvV zQ38VHMfId}jmZ#>URBy7O*W?RY}^tq*e90xvf^xH`oX*iqT;53XVQi(k5kt0Q zKF@&LsN{a<{=s(alZiH|*KX~F3uueyH7J3i=wGSGZ69d$j2e9-o!;_u!^Bvt9AUtC z^InG{h1g)6i}GaQK2t#i;?kg4d_WxWC3@y35!t7QAJPra<6+7NaHjR1SV38PG zpaSp7HGIge4#gu`NEJOG{EgT43Z~vRxhPC7Y?(T5Zj^Yk`Z#A zfprltGLVx_<+78Q-nZ!j09765kaGsKNp5@`7 zTNL@K!CyUuyqdv&Q9nff^R4n(MlWe`nsB+tkX-CMhyr)bXdw(}>@QO2xc_jIqNeT4 zhx*eYZl1GBUa-iJf}PW}X~{|b3Nwb?O_9tgdHuY*7}5+uu6CFimj5D_)=_(c4}M-z zRO>?J05zA{*W0_~f_ThX7$Tq%&R_Pqn!hU%AlEvQ8~Px-CP`%_Cb{58;$Y3^sNBe7 z0I_2OcX)ZhzE(xLyErJWo_!{u1IqP+@HHXuv-4T-T#kY4wu0*H*;hz_{9@*nRj1!P z)JeSBWL>yhV4&{@Q&&Re8?3w9ek<{O^9B2o5xcu`Mx^OW@_fqUf_vqHx;n69Da*Q4 zRp`qH0(o)pyL}hY+sE9|hkG+?FP+HlfX3%XEMT62`n$t3o*OPM9MCz|kI7Y8!L+1T zb<#`@hq6Q|rUwYV4IVEhqMjV_7L@!o*v_A-C(+Wk*ioWOPISTe1FX)i)A@ah(C7}; zY75;yCIoxu?zQki4OGaBe^j}|3|zx59Lu4^7x1n9aTs@S+w+3A!AohnLtEPL&hze( zh@Se}iT*f#5O(0!kL|_~E9s44w*g13k%S;wPtAog)#D3W!#UG z(zjz`?qTjkRt)cOxLu^6Ir146x3_YqbJ(gzS8Dbh=b04X#?K33uS5g0E_2+|l@-W+ zxupt*FUS&oBWhRc*Glui_Vbn{*{x$d1f4D^kbE>Q9hPIVGJ?HK<=d7up zY6=oxi}4)X3VduPa1_{3rfYkagxch;fSAjjO^JEFanGTxrnq#Cbo4}0LyGr!f_dDNR=;H2#L<+7|rrX8OWR~~o8;K^0=(kzHm}?$5lgcs& z88dT_i33QtL>**?iffy~^m5oYyOnuterYff$UBWHI>^5sU+&3ane+@a=gXWHbF%XA zaS3AjQR*H$+cXwN!rE~;%@i+V@C9AeEwX@K?lOQVNQ|ok@1;+GsP z!lM{UGKIK8uEL5F^w+3K>Vap7 zg!|)g?>mHT+;j>lrI>75cg#UH_U$$e)eeDuw(QQpW?e4EXs1ZhrSqnwu1)T&6Qup3M&{d*FRXaCRV9Z{dGAO7a@?t zo0Ur#;CD@t+%?6_IN?RYi3nc$rhFU5pR7Ia3D{?Xqp(IWrKG(qFp zeYoSypLS)PX&o8ln=--IAHU)+w8Q@cF95mCCOwB(bjG*Kn@Y9J#o|vC1x$us0tZBu_(Df;^}S3E z#ahn}G1h^$+8eB8Pu~oS%d`2QpT-zkp@zSVVSg+(7TIbjdrOtp>EIP7>Qvj9L?+<- z@xgOsRpS>9y53sl-v{>hs<3sUp?@rQQQnuR&09x=rxlukYg>w0(!6yDE@$pF_!jt- z=>a;A~ByY~AsOficu_LK5x7_^oT9tUt zmo*0f_L%&m_-wq9ESC6Ez6qUYfgQ<~R)}^!6|K!uFizmK*VK~t=G8R5A`fGG5zzh7wbxgW#f?Q`J7Xun z>_X)R%R$M7I{D`jENL9buAWlC&a?0;N$vT5J0>##aI1s&HnQz#Kli_Gu-G+bT_-C| zcXAmG%iH*F(Z9Gy=s1;&nCJQq-|Jq8)L#zxpbew_2(Gc_pr)N`3idjm3mttM*d;|7IGD Zf7+t_muvQ)>;FKSmH!Xr3;Sl~KLAtF0oDKj literal 0 HcmV?d00001 diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (3).jpg b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (3).jpg new file mode 100644 index 0000000000000000000000000000000000000000..24cfa6692fdf0f428a7ffab2e2f99063c5561729 GIT binary patch literal 43262 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 Date: Sun, 16 Aug 2026 20:58:23 +0300 Subject: [PATCH 16/66] workaround - webview visual test throws error when deleting snapshots. --- ...to-approve-followup-timeout-disabled-dark.png | Bin 0 -> 1059 bytes .../model-info-service-tier-pricing-dark.png | Bin 0 -> 1059 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/auto-approve-followup-timeout-disabled-dark.png create mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/model-info-service-tier-pricing-dark.png diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/auto-approve-followup-timeout-disabled-dark.png b/webview-ui/src/components/settings/__tests__/__screenshots__/auto-approve-followup-timeout-disabled-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..7e43dd6d1d1745c33871bd8664c0da66725567bf GIT binary patch literal 1059 zcmex=>Qk2+&~3e1sIqZ z!LDazWnlrTt_8|7un4jWDH=Mm2?r*!D;0_uHBMZ}q3pErplHy=4=Tnkx|JhscGpMnOVgprDf$6l~v6xt!?cc zon4bAPnkMx`iz;g7A;<~blLJ1D_3pWyk+aQ?K^hvI&}ER(PPI?oIG{u@|COCuHU$M z>*1rvPo6$|{^I4UkDoq&`TFhqkDtFl{$gZchIk9^Gc3M&~ka)>xhT)6Qdr?PR-2hpUWi(FzVCJ$9Vg1iRy8F3zKBFkrR nk0JbZi-Cuk5g2*Qf(-TyKaO>2ELgCpOM_t)4~Z~f{(lny$fQ)l literal 0 HcmV?d00001 diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/model-info-service-tier-pricing-dark.png b/webview-ui/src/components/settings/__tests__/__screenshots__/model-info-service-tier-pricing-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..7e43dd6d1d1745c33871bd8664c0da66725567bf GIT binary patch literal 1059 zcmex=>Qk2+&~3e1sIqZ z!LDazWnlrTt_8|7un4jWDH=Mm2?r*!D;0_uHBMZ}q3pErplHy=4=Tnkx|JhscGpMnOVgprDf$6l~v6xt!?cc zon4bAPnkMx`iz;g7A;<~blLJ1D_3pWyk+aQ?K^hvI&}ER(PPI?oIG{u@|COCuHU$M z>*1rvPo6$|{^I4UkDoq&`TFhqkDtFl{$gZchIk9^Gc3M&~ka)>xhT)6Qdr?PR-2hpUWi(FzVCJ$9Vg1iRy8F3zKBFkrR nk0JbZi-Cuk5g2*Qf(-TyKaO>2ELgCpOM_t)4~Z~f{(lny$fQ)l literal 0 HcmV?d00001 From c427ecbf0fdfddef5ce784cb0cd67f251723b846 Mon Sep 17 00:00:00 2001 From: Para <62068271+murd0cc@users.noreply.github.com> Date: Sun, 16 Aug 2026 21:11:49 +0300 Subject: [PATCH 17/66] fixed format from jpeg to png --- ...approve-followup-timeout-disabled-dark.png | Bin 1059 -> 2682 bytes ...el-info-service-tier-pricing-dark copy.png | Bin 0 -> 2803 bytes .../__screenshots__/screenshot (1).jpg | Bin 43544 -> 0 bytes .../__screenshots__/screenshot (1).png | Bin 0 -> 149965 bytes .../__screenshots__/screenshot (2).jpg | Bin 33097 -> 0 bytes .../__screenshots__/screenshot (2).png | Bin 0 -> 100889 bytes .../__screenshots__/screenshot (3).jpg | Bin 43262 -> 0 bytes .../__screenshots__/screenshot (3).png | Bin 0 -> 152280 bytes 8 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/model-info-service-tier-pricing-dark copy.png delete mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (1).jpg create mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (1).png delete mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (2).jpg create mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (2).png delete mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (3).jpg create mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (3).png diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/auto-approve-followup-timeout-disabled-dark.png b/webview-ui/src/components/settings/__tests__/__screenshots__/auto-approve-followup-timeout-disabled-dark.png index 7e43dd6d1d1745c33871bd8664c0da66725567bf..8997a75e537caf1707cbc34cd35ba2616420d3aa 100644 GIT binary patch literal 2682 zcmeHJy>BB$6yHF>-AOr7L$lfw66jd(x9uIBa~Ee5V(A>BB#;Cs81IhlA>I#WC$ST# zu0eD(hz3MOLqS7vLKK&RD<}{r{srn2EhTSe*Bb{M6lJlq9&Ew=K3tz&c@F*`eiN_3?P|8ZpDW7spTxEB`OWJuE6SB0=*}MB>)u6S z8rN`?_DF3KXMk3eTel|}4i5-ddt^Y9miEVw4>XlVEp6B9n%!)L4C(p_Bikn%JK@Pe z=ttV^CH2+>fq|HCtWM%llA}pWlXelTh1k$k3E>AVZCN-}_qvS4cxJ)kG6uf(iuFpv?1piGK}$fTpK&Jlno5a z_kF{(4cpcMq36d5#}hrtZ%i!&Bo7(QI875(Sj4^bkhe4lwa6jPy4}ifl9!c&ni&(E z8CK0S;#edm(K%l|0_8G{x#)c7I3vau$LkP(T&M-HJ{Rh-!{N#~ZPN?f##+4{h)9G^C&@WZLLziP zQlm6Nb>C}RJ>1vpQNz-$&~4~VD{^$lbNhbZGhN$lO!ePn6!?!vPv<)dQ9ord1}4xL z4~UT^15K@pidNE5%DQPpTACw0p%q3jCjne74Om~-&8BYEcYyU?16lS>(?O!qBv@ix zWID$)hUpwyH=PKFO%LlhbecMLU0?4J8|!}5^Ljng4*if!0~-&CIH(z-0d;)jR_rO# z%F{j{V@8$-(00?2El*yI4%PN*j{52@O`>$1zc#fU4skLd@TxHWMKVv;qeYbSk~!B3 z|6MYMctI5BZ~UDa#dA}6+tf(%@%8}4+)rg{eopFf_J)DR$mkFP<@Y(1enF(Ya{*r+jkXZVbBSd zcP3vx{%v{jR8>yz+>Qk2+&~3e1sIqZ z!LDazWnlrTt_8|7un4jWDH=Mm2?r*!D;0_uHBMZ}q3pErplHy=4=Tnkx|JhscGpMnOVgprDf$6l~v6xt!?cc zon4bAPnkMx`iz;g7A;<~blLJ1D_3pWyk+aQ?K^hvI&}ER(PPI?oIG{u@|COCuHU$M z>*1rvPo6$|{^I4UkDoq&`TFhqkDtFl{$gZchIk9^Gc3M&~ka)>xhT)6Qdr?PR-2hpUWi(FzVCJ$9Vg1iRy8F3zKBFkrR nk0JbZi-Cuk5g2*Qf(-TyKaO>2ELgCpOM_t)4~Z~f{(lny$fQ)l diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/model-info-service-tier-pricing-dark copy.png b/webview-ui/src/components/settings/__tests__/__screenshots__/model-info-service-tier-pricing-dark copy.png new file mode 100644 index 0000000000000000000000000000000000000000..f6e2cb606ef22219dad3744ea8fe371c99018c71 GIT binary patch literal 2803 zcmeHJy>BB$6n6j#?xdWkp;`8X1UlCH{i!&2PSz%t&LK(yaZVJBcW3P(-VbIcu@k7S z0XiB)1EQj(p}2zLQg8(Y;>7=PqNU``uDy1SL^Br??G|YuUzrUaQ^sjbBUO-n#K7$TYIsW4-QOFG%A$ z3e!HWPvQ*Fwc5(wfwauB$o zczab?nRs9z#taFQc$DPcq#+h|Js5MbED8mL9W=xycPR9_Tf%xuvEbHKDNqzuuwi6a zn&Z0f37VqmvSP`aDQSwQsGeyG)1L_LXc&3hetYT+-WuYNvCNa@@pxPx>-CflWYu+D zS&*#|c9dDaminEciGND9IQ}6Mmi6`R;Ls0CbMTGHhiO)+oN-o77yM??F%n%69G^J@#S?M?l+T=jLdl#T#4Nqs zJ*tf`Sd|RL2qc7cMKUZ)i_9>x9K)Jf>m)ft zNr1UEuwN%&NzrViW6;7#F(unE`cfZg z;kZ2#vSCA1oiozAI2jaT!o*Tc;Q??860)70r?qM^dd_XcMO88QLvH_Y|dsLOMxw z{9mZ*sqlBsKp|TpV(2n3?{!5@ZjhX%^my8gcJOD@(TE5|EAUWI<}*h}I25Nsa!&0T z{ZQ4QZh?g!O0EsH=P0%#A>HcRSP31=1wN(G@euO`U7-CGmlBqz5gQ|ln*-Q2vyNL- z2;cdFX4ZA#ojsC-={SFPW;+<7WPqX5%c6V{nIKJ$FlBQ>8KMZP4i>#3Ml_9uvbaCZ z@IYYc^o^JLg(gEx$wGz}4OZTStC_wu_0P8LUwGuWGfWLC0_IPQHKgS9AGPsGZ)q^XT;9W4HHX z`1=p{SG_-fdG(8X4_^Lf>AS}tujSYNc-#1YaFrx{zVw7H9lUPue94ccoz|xR^V%o( F{{<3sm#6>$ literal 0 HcmV?d00001 diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (1).jpg b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (1).jpg deleted file mode 100644 index 7694412f7e4f468813057631c6873e0ec2dc0bc9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43544 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 z 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 diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (1).png b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (1).png new file mode 100644 index 0000000000000000000000000000000000000000..a7370a4685745640aef8306814dc079c62334da8 GIT binary patch literal 149965 zcmce;2UJsC*Dkt2N@$9J5D=7Jl#)=S3(|>#5EU?hl+b&Xj(`Cb15yGgAV`UVG*Lnm z=>#d#NfeMG0s>N$-tWfu{oe2U&;9>#&Nz3B>lnz++N;gEo;BB+b3Wmbk)bXVJr_Ly z08ILNT1Wt(=mP-CE(j%9LL_P>fxqay^ltkCz{%F*ABvQVC(nXq(#|){{LBolDWN^x zC2j0HZS5rk-Mzrt0HC54=w*X;wfEz-wRd#(P~~5F-@wo7Y^Ta^DrW#Q@Y1w*a@Gs> zvA+>)coQA$idMAaSG&xs5~u`r;BN0{!yD-C=HaUpsLKDRUnTJQxLAsx_fHi+S5^Ki z#{=@385r?udivP&DoVm7&@dRBR~~$ly(F!ms3^`W4U?9Uf?bl5mXnZ%DZ$`Ma&o+X z|KkUT^RaVKLTc&!Js9{&mEXzF&r3;4Dj*<0GC)Ss)5lQ?uBfOe1(TMNmX-i(NcaYM z_}K(Xc=!tZs|PK6U$l?2m!Gqz2k&u@HnyJreyaT7RR5B}-OIq>pN>6z|JD?!GpRru zFDbYrOv>H;Sg=2}ef_lWf{p*4#(!Je_hyiny%f^k*VEqzZLfXT-osDe-_4Qs|CZwa zpgCCmpT>6Re+KsQ_i_6py&YQ0-p$?}9K#o!D*T^$dO3OedHOnedi~SnzYO-z>p$}S zYj%Fl4*$dCj^F&3s`i1-|3lT|H~*z72$}zW68}=~@$ldpC~0}3{f{Nl*ZLQ%>^#xV zc1r(DR>?;GlAN3(+)hGTUcpYnK|xkVLc#WujD($nqAXe#CTnv^&i-G$>3jJ4*?6Gs zk9!0AmvjbuvXNG>le4pNkdT#=z9a#Yk+qkwk%q%0r0ryFWngGqX?baxf3?5v;|%T$ z8@KMn_fwE~}uUDR)UzT2@n2>yosNHb1W&TFJrF$K3|Rh_kzm zqrH@uha*4lza`N0bo2Bv@U*j6@SRO9- zcd^m&x`JEH#~H2f;b-sT`+q3^ckwL`XHXz;faAqg(gy!CvG?))Gb*@)!G8Xf|B>wmXjeetz;%)V z=lrMq&os=moWZsItIZ!N|NZLrf4ur5DY#rpnm+b6e)d}64>&OFc(oKH;FoTKWd~*8Rbxp0lr?r%%w| z#^{E<_uo%$&b)t2fszgSFMayj+_ksk|GUunzrmipG|XNOL>nlDoQ;HooGe_z#?IbG z0xs{MXeVzkt!N_yD)_HX1Dx!S7xX{G{$FJItD3K;gI|D+kNp)#aM%3H;{HL%@y_R! zmXnm>6*YDCu=5P?75i7;XeS#FM|;rHOYuwnPr{%*J?`53`2AZTFB=~l5Ov_9tMWVe zc)Iic1#TBFdq-YB&%Zw%L;Zj3($3z;`9C!DpB?@)8t?yI*Z*79|DSF9|KC+Fb$lBA z1u3cj6>Wcg*7{3nI>#FK^#jiWrT;I;I&KeI)PHR3|K6JYHKynPjU_w=!XNXd;p}&8 zi~h1o|II$Stf2Bo5pK@^pz(iK^q-3RZ^!sk;XlrOu;)KT;AP_Y@t4+1jpnEFe`mwh!1>NS7q>@f7+&cEZWID>hm5J$}v z0XwAY3C)$DzlIiHL-9V4Dm|Kl`k_6)YkflZUFZ-i~fP zk@Hollxs%2p`WdV(!j&#>gImF>%H82XYaOanKtomrDhBxr*s|b3mnRo0yxrU)`&Tp z^KvTbfYnVsZof|fxKIF$P4~nAQK-rZT8&6!_d;pn)7G4p25g!_(=7!|;Q9Nely6$< zqtadgBorD8C;FTME4xIZlCy}DoDlE|NexiR0;{a!=Ep-}DG_4()P)lGe%$;xz(>W{ zZ-t1`bI+@l#Ipfdc&8aGozp7>u!W7Zro8GM>C0gUYg z?(4i_byIKFC#rn*z4D3T;r&oFfj~lr@6%xIrqZwE3IZ^_^i9H=z$gCG0x1jA*$!HE zf46Rl8?3tWf;7T8v>Y502pKEib@?;9Z|vSKq!AWgj1eL-ft-nI!NszXMiTQ+xh{E+z9!H>^KZtCD-t1mzeEkjuwF8D zA6MhAAm~~GS;KCN@ET!V)E!hL73(SNU@VOQP+q;@2=HDW zLa6FGu58hG6~*7PDG|l9_1fSFB$R=~_eTyUVj6|F{6tG_epsz3F_DoUA@U%;R(M76 zI3y7|X93~ESY!E?&T)8iU&QC*kO+Lj$Ddx|p^MObH_FmQ8vJZ!Wo76M*V4~$m7n4> zUlM!NSf-G!SU5s>BlyGE#3-3;D!CdaT{L7Mjn7N?%X*1Ur74q8;KYP--{9!y zb^2RO8jU$7A{)rbTSYUCYrhQpo7;q08GuIm9qXG+h?Y4CLQiyMX$r2Ufr-RP%*;N-l7WUmegFiDj=5$qJ zyS@x()2xq8B*kaQ+RtVxN-UwDEdnz*?-$*TKg8`dbrLQ^m^F&~QLY+ZSzeEK_A6$Q zV+F$cxk;j{UxNuq(eHUW3i+p5p+5CYhsr310EMY~?Jq*$!kkxmVUzK?qI7Y${=9Y~ zPFkM@&4|V_?vx=1xFvH?u3~u6Noiu=koM~fX;E*VUTb0vKRc?n+EQ=37QxBk4d6<*|aV?J{)q`MNa73RO!2+ z%U7$MbA}jzOkb?KUJ_NWFh=hgSB$&qJCd|Z930D_VI~k;llC~}oV@cw@y=Rw_Vo&V zEOlq354xC?KG^?zz_p*@E_4cohVWro5MpL|Ao{q_53#76k{Rd?lR|kcP`7d3l+{Dx z5T;p8v40u^XXu8$mTO{(jcxPsYc!rp}lJ=y~)TJn*tn{A>pYz5W^zwRFW*%R1IgeRl>K^Pk~HZ8}YBYqrt6rD*a)rcb9>oKDNu zfox7|#;?20%>&^%Pnd+lDf1wwUr`)hdvC-i@$piL`Z)7lT4&z)Z?1Xbac#2=6DsadQgp~Qqn!aP6EC(uNC_oPW$j*O3wkBwPKrd4@P z)Ca7Li^gJ@^TWaWWw~qxV&OE}sbNGY^GIC|YD8{!ysPX-- zTZR%JZd^|xrAHXNVl}NkI5_wuNzS>;?MTFOs)huhTy+O->y}JO^X#3Jm%b!@ZuHAe zT-nhLv$Cbnl_@N?xNptI2=AU7OEFLb>(yQMA233z5{~nEHHPbpS5x@L(azdL&89$_ zWyNgmlY8s2r>safA(d`lZR7ZHE+v>rV>TZ{0~Q%upUjRo>AuwjYutAnREVbso5Utg zy-0spGja5jOqXHEubnw;l5{*(9!>@?=p+F>(MKgNf{Btt%&N%8^Y@5Oi!+|Z zBX8vOGvlh`^}c=d$50p{oKIvvZu)_>K`;@7KMXQ*UjD2OZ$d5BdX$(9q694IJHLst zWFmoQt*s-RgRj78HY3aX2%etgtgjay&1Ff4Y<6>g)qTRazJZh+pJdl?VbvH~+&~s$ zG^o&wkF+%fx!FaAxT@?I#w^;0YORKF=2u0TU$7KQn{ZLq+r{T-@rX$ea}6Vux}PPC z=v&oEsB%3k9B2E$@dkb|L#Q8vMq z@HKzx=sRJ6)y>qIRq|ENYrcD}o#3~X#({QME zU3Fuq)_)P;)n}R5qMK`J`z@$%5x%e5MTELX!e8d6s|5Y#@YoL3oqMX0^MdK-g)`*d zGxXGq6X+;~_(3OG6bi)^S34I(6cw8pHnsZT@G1SiZph(o*%22Yichof>3E>FKUG>< z+OXf%AWH<>BgA@IKd(gH;OHdpydJ(VO$p?R(nr0hs;V** z*V#zN4R~k580k3LY~hAC*|b|)=w$4+-A}{`K2~D)ObPQ(fzuH=;>hGYWIR=w?PXH#g;q zdXM_V)-p1J6fs$%hiYp3ckX!#6pI){Yt%GoK+0bXrkY=cINF#oMX3)j5E&5_1wpW; zX)S$cg;zBirKpl%w>N~sI4e=MU7a3dMHf;dPY8aNRCYLHwKPIl+?zNGCzu3SnnF&u zmoo~Cbw9XBN%p^`@@-lEr!HcC{#Ew)$OuC0V0^1Sp!e%mO=$@6fyuRWS$*PZfkv@@ zX}ZvrA5)s87x#Is7&NV_yV9O7)6-&Eux3T7y4{(VQ_LiwzbyIi`)$ty_J6!wks)%o z|KdKU%haPNQam&?23bUOb*kSKXJ@)vOh6K^Oy1~hfpyRA>*SpdEX8W{h@N~An&65t z#y9jLQ@dtjqcURh#W0F+z`{vub*PdUm4`Tvi}OKu#vp`BZ29eX4%Amx8&90l z6XQe^f(1Cf6HK0{9d552jIS(>R(W>CTehpJ{WgWhL~HQjQ2>CBG^1pLo=Q*02?!d| zfA$?u5X;Xq(KECJ>Gd6Gkz)Tb2 zdx7bD#?_e9;O!fx{*d~OHJuav>Za_NZTa?aS-5{!s>H-LQ67gZU8Dp$ARW(91o zHXR)t9hS@~-aE{$SMeBAa9!$tCev`ZQKq*0BkxsK@WSVEG#%e``;((xa>Lz9O98NC0N8udY3N>pR!uLRi=fhsHP+!VtTAdjUT`_m7WXW|^V{@UrpK zsj2L2*9VjH8hTI}y>l~t{<=yXLxnf;M1$A+b*%zD&|A~j*IrgqoaxO}TuV-~RPnb+ z#MC~;7;BO4i2Wr zf17_L@qW4XiHu7HNhjI1=O|BY_x|~#RbBN*19WIc>@2Q2N`{hvP=rvLdhPd3UF*_< zA&UE@;fUI(vYJ&&M4_QA@w0AOjcv;=N0R8_@3f=hlEUwM;kncmgriQo`v)x(@wfh~v;L+?O0J%WEehgf2O( ze(PEGe$H??bc3)n8&8`ZUMIh7%&m2Yr;s~ry`1*dlO+r9g(TlOiBQn8I9%e|30?Lc z{9wHs6&;SYCSP@rD`k*us3;5R8X3(-T?!i)T1y>SGd$`DJH;)R9y!<(+7tNc$7dgd zCgwh@U?x>}IWFSm5T!f-&=gSUK}oNmLSBRCJRaY*Ok+lhv$w#mH7U`*&J{O8EYE@P~Sz83ba!=ecsjcAHfA zMv)bP1iCulF4!NoIvCDU4S}MS1D5xb)pnB4A8oha`^9n3d;Nzoe(0q^#xbT2embfZ zG5RPCqLkw`#Y)JF%6ETmH*?f`ZG8=xTia2HZ+~+B-iY%nIXO8xK9Ab@muEfeex;gw z(6zj|Q-(enk1S-1nR*^DzSDkhzg>Pja9ZtXP3?VYNR+~R@REDh`T_mL{PGHzn<*Pw zT%Scl4;nK~j4LuJ!j_B1_BFThQdJBXhMuW#e?U7`&z>PC?n|P3n^l>|&+uN$WqxJs2c_v@p*c>R%6}w5w8KlGD@myIK7YLoRrt)0R>V6MAF6y-$ z9v?r6Aa0-t(tYFO;a`L}tb%qPWCt#EtQ_q<=}e)}-F_CGF;&H>7bSZ3P#p|l8_al!|ks3k~!j};I z?t*|oYfdWiM0GNQfORCaW4Kaj{%eK(*NYjYiuZ=+U-cY*r+%fpagc(TX-=8zeX7#p z%aApr9IW2;{l9U`AAs?^joYJ8O*aaQAYK)}|~;l$BMD^jKx z2ugss*&ASKe_qBhY*6Wr(!tn1X3v0*3<-vezA{XY{08O zrWLvp`o)rLATMsME~4XGYQBY8p>5cEPtLw~7=6*C*o@#Zyt3c3vcA4vQB~FZT$#f( z8*29mn^^y`8clhdI{EuZPAfW!RgeGn*%uc&8M^G7Z#K{KPC;Gq$VdGr?e86yziZf- zcfB0eGk;#$bLKboQ5Tc6+cP%;WF`l8*XS4Ul=2FFPzeTslTS#tgW^pe=EI_#i@K;rP z1(dE>+HQf?@9t9Y?+%f&`rU=u+1aDbiNmv(Kc1jH`66dza1f1s2HxZ+jt(X!e0x=& zT;BbWD4+|P{Y%aR`75Dw%2i`N43#&;ZWZ24&&aSOw^d{qvz>XYE&CvB;@(0>dzys# zCGd!GEv=dT-6f?PMJyJf^ShONjf@A+n zK27IFSPq5HucrI7>W*XK>vgy0vhRg^UcXmkk?JwNb>OnG3QC$u_wEUgGHGzocYAe;<4)g=wUV?R zwWZFBWh%LOABKaWG5SePOxNC9K!^{AM$8syn;IK|wMdHft*wS+WBP7yG+x|3C0O(J zHmRy159i|U&eXD6-9BnVl}&ns;bVe?1X+;}zlLm9R#k!Qf`GjX1n@$&G9I!5o}vw* zKYs;7t$aF!Kt!DuCLHcqZea$tcLofOyt~%F__oLMxITN^T^Q5x#Iq)BEWdE@rNPCt zuI65m80INO&=LB4ji=#U5wg%u{1z83QU@1kpj~JXaDC#G$8LXG{kl-^S_R3KT>4?P znZc5b&m3;iA&{W*9u_61>B*xZldD#s!^EZh`BdIgE$Dq)tDE?9w?p%AwpcNDI-Yed zo0riF@n_?R%V8l~JfF{#7BYSLp2BBm(yT5KL3hb{W&A@}SeRV_fMKSj>+-i`Y|~z2 zFLM%=BSs_zHFxTsy3#vkd$mX|)%$_*z#Anv!kj3|ia~x0ofhf!2{a_L_KbZ-^Py?K z(LHf5pBUM9`fMtxkhNGV-B0xDblhL$kvdrH&FY#N>uU{P{1)zBzc;yiUZvt35Fw+f zZHf36M=ja>c}Prd?7KaVRlIbQFl%vR#WxQ%{o~36mxCO0pL!(Y>#8BHz_WB8y*nai z`Q}vO(La|@7g@)vSKsg8#hM_5^asYrJxWSUimI=30^IFQJoeC?i+Job7)JvAZ-RCS z36&wJzl$+4j?FEosi`R|>)i^Ip$ZKLUc^xYI&^>$%$u7*rzC7C_ulTSdrBdjKbM!6 zS3cFDM_VwFqK&YOWp3x|BU*A-S!f7z0*^_v9-GT`pYG9b7Pdls2jgg zpT&jqnm*z)7sc>Ufda+t`s>kyWb%XJxE-@q_l+<$2qm74xbZ5dy48tjCN5#rFuT*V ztuK@I-0+d7ko{2HLj!Dl4K+YUrTN@0W6`)zCNd8j5`&p z0pTHPK+vpcJ3H1MMOr2V1DF&sP-pdsHcCZlD6TQ$Nh7(2`M4M-KCO5`^Q@p^Z#Vg} zTRyEo1Pw(aJW(+kG9DBCn86pTL_8P3EfT9^dClF(_EklKl%PJ6K>&{{pWM^SOB^22 zGZ0I=aIWCyFHWy1AtXhf)K%>io>rH$%Z6QQEPA%~MPs?! z`7rC7o9yN&iWlQfMhHd1o%%kD3x`wZ52y0!SX~HQ7k0r|hH}8lm$&Y;d~Bj6?VSLA z>{0W_wYp$|3fa+(gsCbXD4w|;?&HDTj&hX@OcIP?Za;0!_L9Cu7J@@wP%uk&D#Ufx z+##U+_br&I0Ooe@^dxRg!+wbvm3T5G&;l{?q9`^*#0+n(7!c!~Ipq~oO{A~OoNPXm zsV}B)Tf)2HU19^Rl=qulsEbi3eW)N}tAU;7n)s#C3s2SZM*6?Fazz#*lu4DOJd|jS zgAJgOh-{zS61Z^UBY&PIdp7Ovh#5@eZ_YE)bWfJb&V4pD^0$>sh26l}Hp3j6`q{^I zey5AZs`UC=Rv`-~^Ve(R0@_0)Tf#%0S44KO$B?C(Q9eW{Q4~MqYoP&|#-6-_5W?qY zD#oKFpy)=fYkM)**!qeI)*NH8~IcozpZN&+-X{?MzJ6)8z z>sK;4VAQ?pYtYKp9-=Gdhs(`y+y#kVj( zUFsk^^#h%}D`IU2uQH{{{&m0o3lVswekWxX7fAU@IsGJNG8kNU z7sEeFGUmQogoW!|uzlbY1CQzS=~+v`hLMG=lXWU~W;mYe-z-sEwRDvQoTSa(JfQR{ znpzr`eVhw zYW<4*Hw-g>O4Fk$rT`3=L8>udi{}X}9J=*L3RQTsIWPx?SoJ5GK1FtlGHYO%iBDmS z@Re93qVp-UEu-~UeU&V@i8y;kdOGMg!#Xd|u-`nx_&_vv3x$2J~wpStg1^$*~x?9}sq%-0xrtSqdakSG=+Z16;T8SL)ea)<(e!9AA zi2(l5r21153ihDITFY4r#~cNxM97pBmSZsIKED}Ps0+Hfp_c}srSIb%aw?LIOsD}e zQPwn+XIe(zc$E;I(n5S+=ETO{7=%nf`c z(fK!joSn(ci^+Hi*P+)5qWGfn9G&>kbt9OW%0|G?k_?@xEj0n9rfXxQ^X4{p4V!3( zX}YQ1fry^b0CJp}s-^-k4UY4iGW(Z+5@tI9TiE{m8PZv%SVxMlHT}wc#`{ry%#|ei zNPP=hO)en9_l_tVcRME(st%_>pEJ7F=;{muCOK`fpuK8J`deJEqDVFwHyTo~qo^wtFzi!Bx12TWE9s0)CGN-toX4n@0}&1IhDr4eU#DWPUi`gF5R zj88CD!1s|iT*y>W zow#K3{*GI8Za4B3#eQ|#IcM!2ujjGtjOHaQwmh9cMPjVkJTnbr!L8*|kyG3XUOzv> zH6C_F!-=AwpeHIiy}L4^$>F_!(wq&K6UgB4#aLQ>mR}#t==D#kE?0pC3qO#Z!5`vF z-%X|Pjz=Uy2^j3P;RU%wO@fsw-AI65qf1J^A8w zwCVli{39X21O)&v z_7fc$pUMgAa}lA_-b83#hc)#J`K+l{F3G0g4`uc{wiuU^5@QVW1J<6JVT2fd-nuc# z`o3*>{|MLp9A}5m_T?p!rg%=6q+W|NVH~{XORnd9`jjS*4K~hx;*E~Eu|3S` znk(ZRE#MpnpM6e0(0ag;Nr%R!CgPHAG((d|tTSm|UL~W@k}ZkL^2uz+X}FWXlCs}< zzK)lXn<9PJj7zmEn*|0f?h9DZs-4%#XRk5_0OrPIsH+6^2_QYrq(u&9H+qte;eOj_ zKc5a{if#B51CUyunghR;4UgHVp6mUC=Q^}r$y7I`I>Mz*Se#ty;n)+7k_6SPC)FLbT| zt8lMnRaaEfU4wc3BgQzwtx?sF^QZ}A8+n$gC^jC-#c-5*$6&g0okFdHdBzpMY&S@iE43FDa}=G8T3K(;VYxhdPk zwLb>qNHdZFP?voNym(5@%Y`hAGy<@EP+LQpT6J+{tlY%4#dQOf;)&L`0{xQV@`J44 zVkbye(6{O?~Ptwv%U$76h4&EggK z%RD_vIPLLAV%@*?Fz2|yUnCC3mDAGApZ;hN@&}*CN;PhuvQ?!!PE2B$#f2kxVxpOy z`whC=&c;mXZOq7o!mKA|6f^d@I&?wH*I+Y*xrli<4FweDu<(2o5o)3+tl3D<$~k(x zMw+q486qfGaV1P~tYC&99pf;u4<#_ig?{6pb37xvh$`J`EWAfCwL@!-9rPqxTs!lA zWeAP_nG{=|u!Y@#LVTi2;vF8xHwy2k70hfeOMKputWZ4W4jCe_>0bSOG5GKO`NOEZ zN@i{2&St&V+jsvcSr6`_p~czcommdL$2`jHYV$vTax32z$II%oFrp&J@0{#juW(#wn8|TnPU*%`UJEh&Vy%ww z5LaJJq@45=RYZiLEzTo)THE-0Z7D9Pe#Z8U=c!mqvmQn?JH#1Q^rkj3hLUjxT_sBc z*oFcxT3!dHpJohI65sS)h5CGp@+(VOe{+)(D5v^qG;wb3J)8LXefFRdRnHy~wa+o+ z5>}myj~h0$u@n*H^aJ)^CrfN}xP`xPiM7x|@>1DCCv?9861RajBw>9Gu@t1RK0oGR zF668IvqACW86&YH%{)Jrye+Hp@>W3}dP-$A!bCc)D@UkH(dt96 zf4P|-_XF0~gi9zPoe!glHru%@2{8aQ(8UN*w>6l!b@dswv>7buv&Xb?Lw5^g-9Njo zToqsw=iwLF9cc*EzB+jINmf~m)h`TdV+I@{4dSvz`LS_BWOX~%w-ndxCTGm%T#_f+ z?02bJLIW`$H2%K-+cB^e^x-ZHY4B7*{TqcpAX&nNO-qjP(->nntc`WF0MH0s8#k-Q zK^q@ZNvZ*x2&@mzo+~Ni%09Oq72HT>9~zHqanmA(8o)($qJ9pVl&> zx%beiC!kewtp`Ve^5}euaq6YHGN}-cV+mphplC35-ZkS>Efd8&;3WI@yWFuUNQjzQ zYbvO36tl;EN>>dT$nVftExhr{FjJvCFAx1GU9NQT^3gs67~>q<$W`zL!vH5R6bV&_ znmU~9)=kWm7mTBnvC_6BL$OHM2uRZ4%Y>s@@&q~ygs2KG;{7ajT@4G{uHdtOzl*F}HI33DjxIDBlvly#9|f zp}f5K@0lo9JOaaP9XHwSWB@T@z%grxNpcv0j5MDfR|1NeO5>pm0fZ7JSql#MTlS*R zCH9!x?o3di@oN~)ho~^EV#w0|3xMQN1-$U;i5n(ywVxq6xmu0VKV4?b$8o)3FQ#rh z&-=agIyQpOdSdq!c2)CX^z`8|Q>ys~B#qgYu)MO8hO7i*NZFU&ch~17BqTsRf!@O? z7@zHuDlK688itGuJo*7_!DQYd}hI1BepH_-RpmzyJK+<(GY-?lHU=-$ai(!+UTd5X3Y7 zYfkQW5O~B*-uH`VW=}<_-fw3*u#MxxY{x@d5`4q^wK;CPt~4Blw|jHN>EtpIB?R^P zxlheR_scoqY_1bgh(fF$oI}sDl(hS}4Rkx)lW_yTsOI`0?|o}B^`R8!5N(Pg))2nT z2;5tFBIEZRyh*yg4T#rWI(`s&6=8 zbJQVx%^l7qDTY`$5W{RM#sX4vLc$xNk8{C5l{!cllsk?ySO?M_p6T+1qKo;&yiZ*g zS6Y8DF>?Rx(pu*woc*>tv8>N)VxMFala4A$eM#%fEyCD>z-vIn*dIgjlL{xfoK{d> zw2}HZD2-`2lXx_>%lt4>Pc?Fow7VPDju(HmR&dM>Db<$WoGW_fVn2m(*3xr`v1UCwUL{FS)|V{C!t z<6cH5#%$Sj*4^&RVdNYa+IP{XuxeNry2dg*G!_+OAo=n7vr7gYc1MQ?9+Che4vs`< zDB`bO5a1?{^xsy`BY9Exn<)30Frp5>H5_#4memK2XNpOwY}wV&BCZ%0Vq`vLD#R{I zODY%|3MUG1+cF9aovt$yZH=RGWGqhc{xdo?5&{rIme*M||9od=pHaWe=ek?3V6WI{a3bAqh#-9@|oX&*nfJl-vf!Gl6 z7$1%M7NsUdJ6WC;FV!OwL}M)~s`Jb)wn1jFz8Z8u4kHlpSy11|%t*((XIkN86aYy< z)|R$IlUZKn8Wn2kYeRm8_4-@7mLQXSiBNlNVpBCE8`7qt(m_}ZGy$Yv7a?1plA;!a zZJ?ckFL59n0SxqRZEffn-z+s5Y=KUrTub7>qyLGA$Z!E&8s!{!zP$hM?{cm^-7|sp zlb&PM@JGI2#JDKphZY&aS1%(RkLDHDXXz;*RQ7|0@^JF1)$Vq?TD|`wDJ$#TlmZc2 z5{Ha6dP#6-Rf=zkX4Ww3tRS&N(ucvA4Hzie(P&g``1!Vr7X6C)5^N-W!Ra5^Bxhd!?l+CtT?eV;UP<|H0x+zCzArvyeQ z(OBsuLAtqaZ|*|DQjuKI*Cwu4n4R3;5aM)BsL!qil`wTep4LF`Wa!eqvr%7=4M~&R zO6*PMYoR?afS~s@L%nnzBE3ic!!Ti^FhH1`iC-YbJ|a&r)z6DE<2W6whbn zu!Yvt*<86t2!2Bf;LVUZG)A$PA+(|JW|BTXRP0O?Z(0$q>r)%jtcc@r8^{Wyrvcsi zTw7mOf%T95dG%gO%1RZ;naJ1uywEwEjS@pQCq_}m9EHNdF`t7~+2Y%)1u#EWR?0}7 zSH?w#5NATNG6dl+^#~zU*G=;`Evp`C)nN9T0bZ+c8w6CRza{=Acl)PLpTLM>IWxaL zi>n0lY|tHkFs2@#Esz)gJ6PEWA;&=vCa=WPwvH35zH{N;9Z5m~`*uZCtlGw-Pb-s7AA&dTKT$CgXHSz*9rn&V*xQ`&8#JJOzuE4+Z*{oe5S$gz zRZ?~M6}R@=JdRml%G&$FMa=4U!{Mu?V)6SZC) z-2JVaoR=!4VZ@or;WHJExnT3wMwOa$}EqjcJtd;wXj2uDxMz? z=w6BMb*b$QRa~lZJQ!SDu31rkCT7v9L*KpS9X_W8u^98m2qlRtAqt)j; zd>{5>+tMs$%OvDyr{13nTA$H1e_6Rdeg1G>MXDiaaao|9=B58bZz0RlN0srMU9W;m zb{nrQhCF+^8F#eRJ92;b-Ko;OnO?F6+W}eaVDQUQU0jOlOvYz9!yC8g(_F9M30#fL zw!a)j%fBe6UUA5OIDSmuSiQ9M^`sT1-Zw5txp6!4R*^}Y_x_k~uaN#*koT$(Z(4#n zqfOIhLWI&7P9k~EAYI+@$eN?Wy|ZyNeBaX=_GduWAiCrLgn%2i2277N94vWG1TU7{ z+pD@aIx(T~N+>dF5Kt z_jK1%FuM0XVCAl507w(VB*4+cYtNN7@M(8Oz~s-)T(%kv=C$%+>+pxJTJ6qkhE@2^ zOjcIbW2t&Ggg&HcgPx}LfSBz7QsLb)*Udf8>Px$iRM34g{NUr~NcPZf9h7oc*^9dR z@*21D%eKc{xc6*YzHY3p6-Ykn>s=3ngTB!yW(g7^VTLYD&Z1@71D-jo?Ukl^En8~8 z^X;z@-;Pa$fLu8l;oy>zk~=jUWrqu8QK6D6bYDL#f)eacO)D#&c|3QmN4q`iYshD@ z6l~n7b0f;&Ax3>QRi$di$moL01qpJb52%IOd+pl z5S{^LEE``ls(yHxTXm+xJx~1qFvMH^pp3@BTb_ zg$e7-ei>&Kx|?>DqbI|!bKzU{!63&c4@SnHUn=8j)`teujLMJRW$(3gNu{BQSmPHM zX4(J_w7%SlPT*QM^j%CsfMSq0n3tFV<0ny~9bU>2H zxuEZ-L0ZnOcM>ZgD`+chVhbd4FDQaEKPgMln;dqQVt;%PmccG=26O24wbb2%lQFm? zWa9yK{PbkK0@i{!;Dtw)7xg#Vu|eG)Q`C`0A|oR$dK@uye5=>Ng?R9UN1%<8W*EF% zK=>-%z6^|xDue71zE%)`z{$%8>x08Cj(PnN-21&pJ8FgQg~KkXUlihf1)G#MQCt@a zkQbmx{P8zCB&U{M{SMCFeyiG>q2&L%*Ke!8G%lm+r;6X|@Y4HJ{#&~G)owe^jNjEi zloi)$%nfx6z9J`gKDDh^oNE)Ot#Ke@^mojVPtcRCU7S-WPoj;e9xP-J&)8F@nuBLkR zC{x}$#OaIM>}{S)9lGiF)Ce{Bdf*}Bj8Oa1mwW1GJ$uFmS#HdR<9g$s!`<~g(YzSU zdtL&_(Q)VDxgk~meGLBm+i=NV$ZoQ&{`$swKZfVNvy%6g@f;_4lzk>Y)-N9lEXuE# zuY2-q|{u@CQRi z&*fZ6yOyJyOQYoe{>?|%Lv8mqm(U#9BmMmp-d50hbigLI5M-u?fxMWKQ)(OA z(@(BvTs{;yzw@!V=J+6V%&L4{QnEDjAUycHo@lxjnC?8kbi=w_>*ZoCNLtAuodD0f z$q!p&y(CbIW$w8t7bmO(|90QlfA`Ai2xGHmT-O2l|0m~yb4ewPvey`uY(SAKswtNJVZMOCC)6p-1 zMMb_}3&W8rDW!AKBU~a?t3&ozIiw~D=&Fgkd-cn)UaCD$`)j%6*(H?R-3D=vS)q5o z4FoNrmG55mzh~~cS7GlM9JIC5o_+Xh>z+mFTT=Y5t38?L*%*4&wm*My%)ZfG1$VFt zoiEQm_?CreO&>9L{FIF^R(ylLKB0aqIn(%ejp-ftbL61T^>PNoXR`yT=)JAOu7E>l zat`_dS4^yJeBZM{;ohgimA-35M~5HGGxwh+2)EasTKO8bjZ=KAJYt?Ip_annvpN~6 z8WJ2ryO7E%`IIEr1K>`m!>5*i$>vT!d9cO5ETtK9ieBg1owe|bVhYG4TtXmfvBOYN zKM7&?%!;z1u;0n=cV1kKLycmJ;LSU&)&6^DYb;7_@~0K)_HILQ}4aQkH%F(@za$S%w(=8EOmt1(a0PaZr!W0+V3Tx zO48Z1djxt8eFRJ@zcTs6wjtU-A;s`6c39>pY3CQ`Y>}BF%K=1XKaaGLEicP+QTy>*j+dXq);T<<%Hc&tX93<; z;K}=1KC>d_J_UU=+`R-PW73HityAU3tt5-iU^j}os5}?Ix&Qz=EDB$=4OfhxeWwCg zJ4lsC;Bl)O#e_a_lKy1i1uVYjwnl`QMv%p0Q7Vh?wk5x#kx-!|<`%^p>1PXzdo4;I z>J`6DkFYND$4N<9K)Uwl`Lmcga3BJ5s?8yK+RojR~5h64#*GXOA{@7)v4jD<6P zZF8b+_lDiKFEP2AWM^$10VfR&<>Q(^wGyFsRTyVD!oOa6!zxl5b{{QsaJ@JL=j{q6 zzu<Y7L`v)er?>U2=>hPJu=WXgL)iNDaI&YwzX) zj4;xVH~RcEC;=}w2mtpV^>OYynsB)m30mt&tqAafU#^8Q z07iM*z{d;KM3=F)s$k%Mp{~c9#&}?(~IBer1l(NoMKjXw`{D z>9CGkin6_^npKF0w|aBWs|!4eTcwCF(~PqhHDRU)aIF|-?Z=u`r_SLh)YH{j6I6sT z5gs%VjeaN8ua(feG>`!x16_>PFMmBu1tQ)k(Ka&y5&X-OU(cU^7L&o(Qua7`yjlA! z+tS!mX@hF;d(x0rpphwj`2-+z8gTjso93Omuo?-ph&zD{9ZHJS=_)o_?M5g~s`8~6 zzD^S61ce6+4VS)G0ZED)IFasyh;%B^L=I~t8>I`1$z*eks7?)iLutvfV(C9AcKk9q zBf@s$3o!?oI7?9-NzDX!XxJ2Nm*s#=Crt`S6OxHtf!RQek4n~_{dUcD3iWVI4|1kF5@l^id-$(YIam>h;O*!@|aw;oHvL!1k8QEKQ zaip@xsgz?B*?Uz)WF=+Au}8AQbDi(+d7i(2{ndEs+~>YO_qE>RYJ7sps<)9b=yd%) zX+)}4x^XbiEiz(G%_?2C_w|g?iXbKeTQ-;8kGue&AC<7`w2LRAMJ^ceb?TC|mN6Zo z&6LP6JUXiKRG7zGL>{h;Qo7QSk{D4+!$6CO2_vH;QNba2H51ZN8f4f=Di0#WshC@< zFObGRzKbEGU!TZcp&)KU@P|4v8;{2=Bn$Ltt z>@Fn{@xHj#LM&lRB_1|7}Mvy9yJPV|rxO$ssH!@j`+av5fnr7mz$GnoESu9Qt+&Hw&@P%f=KdZ(0 z0#k?_*O8`AUl#B1x?VW_lJ}>_(?4529er>l0H=CU{|T@Oh~j_X`o|3(zW)VO2wD-O zVn4E7Ji>fgK2<%b!a#fZJxSPq0K*Kzc%u#Ms|a7RU;hF6+lOm=~t9! zO8D`O+sVwgYD7KgP6YLs5G{7n2%E%K%sCHJrpF1BSl|EoKVq%(r(gQIe}0uk-KQAx z8q=mO(-m{(sp6Oau+uMl!}{+P9={w>0)=R@YJVXnAcw8nD^(!Ndx#a#m`JdO8eaMj zxS^CeJKdxie=XF2Ni@pI-91OfUg!30PQ<+*AKU<8dNzKVQeoJ8^5_4(m!wbo$-9r* zJ-uvdE;0=FTo*E^IlewRN1PHNdOGqtn`H09zUjzVwcw*|tX7k(wC9Q$ec{k{gGfBm zzVKdZYn`;mfuh>V<8`{*33DAXKX$!R@FYk97?GP;ClJF|7zHW>ZYnI2dd3j`ZM1_l{iuBO_W#vDnmvny?5@u z`LfXk=Lb^dQ&}=GXWto9VQD6w*rt#drpt6qaU1zgY@CLj2xRMBBp6Gx{L8%w5k@ zmwUcEvt3^(vuV*4f9lIw;zZe?FAOh^xz^YJ?lrnBk`FdiX-p2Ep^AwhvI|2Z z;%jb%y>u4mC;XZDqryG6cHg_4z#{hN{$Rz%bZqfLl%CK?#XU2rS;nz)*bXrnOqv+ z+A>w^3(Jc%n7-J3$MV_qoz}RvHXE~&Qz4frDF02!8K?#m>bv0WVcFE0-4*B#@qw6TwdM!p`5n zc}~38Ann0-)2QIZ;;bzY4w2{+$G&&tfcW8GEmKgGSJf3=%Wx|DST7aS;Z}jG-3lJx z?~h7>a>{kLRJER-N2$`ey-O?K^C14T#z(n+HD%zyQ!)#IK1A0!>A}v+njz++#2vDy z*>!iicigI6Iz{Gc>4@H@-@$~P?=YvbsVqRy;br641!L*B&0+2dGPuo!idhdNc9 zwSt+eTTeC6V`r3-@9|W5JFeVl;#Qv*o(1tsu1&-GW?({S28HqK~Nar!*up z5@yHDdlb7@v{2d%S~Dp9>(sWr){Ryk?(X_qpJ$WoII*nlNjab6Z51x&B6!v!az;_g5NSORfb7W z?9XQyd4szqX!lpcgWjo=^5S+(ULs=x-L9>A3k79RhS`@#H}pt!yr{BHkI8 zdVR6WcIfq-im=O2Dyjr?C|Z$tO7MfJgmQ#)I#R+iR@XM0iSxJ0^NS-Qtt&g5{5D4Ob+oi-6q}q1Lt`VH6Noe@j3hJI?KK(9Tsf0sFd!yVPL6!f!jXb?-DY76KzhN|D7V9ZC={%RwmjF45(<{Y|_EOBywtG;ri zi^;XbKSP4vBF+_;&}oM?_OfJ4E9A8I%&|#40&Hm$#5*9QQR{lf-nw9l21(K-y~2To z)m6bL(Et4OY^Qzis2@5LC+yyMM2EXm@fZji_vByWZ@C7Krt7UdEUoh0oaww7v^S{B z^YG59Ha$Jl)2GtN`TXVWHwpv5h`|r1K@g2>$ z1hSW=bn!G^Lm&5>OwgZ;jB$HS^gwa>dOvZgYTm9@%sKrx$sLyaeYgQTk@puTUSCHS zpU?81uC+z(n0$s*US&=z;lVwAkHpcou#bIPwffZ|5;z~}TdG=*mMQu~95GBH^nVX?-lnr; zF=}D1lFgmEVwAw9HTAny@l}wa;ZtMT9jkk9p$*9Hgo=<4;24?;(6rRoAAZf(?qx)T zjl?pXqMeqeNfS^E`0IqVf{+TZsX2~n)XQ@8qtRQc!c$6rD@R^qPlYYlZ3kFVFp`90 z{(z=1d3Fy>C-|0dIm_U4g&CBlxxw`?C$<0|Mac{~@FfNqM;G9bU#zaGy7BhL1o2F* zKF)MYr3~u4&Tg%ILofpPs=?19co`{MAc{q>UZO-iLwU^<>7^B6w&uUMy0|RCD<{v< zX~&pB2UP+{K$_MIZpNo% z-y19l%S^uO|w{TVP<|=1Zi#$c;i$ZW2ufk_BJw z2vanCgB324aE4RcPNEJVAm{2v)me->B-#eXD3KdJ>3;RqNq$463#q&y-OKdD5p@f? zhM7T>!}AAmYYP7OA$gLCj_y zwAr@reI{^4=5zKH$=culwg4&U4{dV)S+~E%8gjgq8@hbBW?s<$0!(>bn!(j@dpV5w+eR zmVDT^4~kK>-P(S)v2t5*QUHv*%6#?qJLLQQPw}BP|1OV zLw#M{%d5|4>eiT-c^bDzZd3B*9%LKz<*J{l${^?Qp8~}lY2p1GIp?;Tll`jZKKvFj zG4aWc$BFM$OZdET_;n|-dBteO_l_aI`Og51h_1B=S*hq=YdUlnox8-A6S_Z_!A2Dg zqz#?us*$;~WCfpGle@*^rP@C|V%%roo~Y5%9rb0oRQxM;hZ=!OjvV>=^=_<1qm^!w zfoqZ=->;vXc`SZNYrmg9z$k;0Dj{m$8$n79V}4&y?#9}VImzpS0C`f`}ehX;#;;0dF9CfG!@%BD3!B)(1hVwx|M?*w@u+%9%| zU=%c;i_%zco<%AAeDDoy`ji14NeTMRKkRaY;z>VV0p1wL&>csDQ^0Rw_2Q~yK>z)h zan&Gg3|+B5W1q;ac>fM4inFt`$K>FEq~EmKpTMgrfEGE^qiMfe{n)F*tYNKg+4wwH zA$6*NUe7}jEYNG08j^HoIl&tQPSaB?+J8Gn%)u*8#!(_obz!<(6aiFz73; z|AEG5tzoP0hkHHFM9ebuXnXPdo8cvl=ykQj@BLj~{|HBk&_0a9kqz4a<2Bo58MN7H z{F#u)mPc^Z5eP&PMugq|m4oItc75XwMsIP(QyNUTFea_%M7&w8Q>IsXNYllHSQ2j_ zG(<$QJvFP0S**#lTFhb_hhiVH59;kDKQ-4+*5cRrrp4Og*f-(6Ou5?tp>r+JS7FBrYq^d!B&)m;? zKPjt*8vCn1;08Rqq2x|sM~E%o{sWUmNy~SYk9TtdcRra{g#vj(+^WI9>+dJf z0>2aT;y!q{=+S=*{QWKs3>izdPFoZyswvXNEf3E7?RVf<29$_?h z{7ZO5^~J@cxt^!2RME<7HTD1pbv+Yh?#l5QxizaiZWVI;ToIBZa316IUtUGl`|Z+Y zv<}710zALdQAkg&S$?o0r)-`XVGQ00xzcZ#*@b;Hd!N6Oy5%*lkZw#)&jU=C@S}d!-G2^j+3Kb5?eRNq>W!yS%)`@GqS*me8W4|~&6%C=NI z`c`hiS=H>)Et?X3l?6^iJRy72pl~j^UF{A~7szIN@LQljnLIh(g@CpXM3n3gfByob zPG1XX)5&VnjxaQ4OMJmF>9L_wR#qlO5djRX;QbzJwe^NA2p{1iBO?HHY^m?H(nIR# zKyC$Fi$)Ky$iA7?L7+ve5UkQq5e{EP;{P=Dqri;jRaMpYZs^JG$y9>%>(OOR2Iyl$ zVRqz%hb9@Jah14@kV`mdxqMZAiHbyVs85H2NEGGMHv$|?R7Fd#J<4AG#Kk5~nH zRQU**W;rkzz=iCazH*W=2TAJ(w;!IG<=Lh#MrL5 z)%EpmUZMxK(}PV|EGd7oRPFCn5QnoxDsd!{jUPubBu-qewwzjeWgKBiz|X**zw64CNV(mv_Dc}=nmndR*TA`i}QO-=&^j!=by z_Xi20f2*`{XWXHu-)y%dZ8(4*eFt-ySRg~nhU45?4Td@|kuvr^ermdqnk`q!t*hi_ z^}Y8|=c_99+)}pxvgcI{B`=S*Glc19%Gl4ZD5j|I4>234g!>){t8K;!UNHz<*%Wq3 zGQ9n9jv7O4jfytDUTgj~_Q?lBoI=ekoyi-wRc=iN&}HQr7YpdMMR9h?J`Kn-_O|qE zi=u=uX@ah*^1B$P67+ZMI5KwUjEcP5xV*zXKaWXjsm82+JobW=%HhNpg~`O!1ctL8 zdXafqXk4MR(Pxu4+Y+~{3t6V>LYU5}i(Ga)H(ZA&PZCMS*3B25Q3ize3>-<}+@L@4 z=Ss~Q{40jYIB77qvg2K>zf^GBKvCRXpG>*m0g`?;DJzxWgTDYk zvm|ta2}{|4lSRNH7HT$KFB_Ydtp@M_GcK+SIXZaXr{oGUe@jbCaM++`lbm?(XmIl; z8=fnYf1!WtQ-rx@Cd3PPiFa3j_$_?R-<<89rLqUcElja8 zEPbCFzcI&2f|JoF;oJ_jW)SLEjR4&o@O^Rjn{P*#7bl9V?ut{JeDwS?T_ijKt^LEV z%iDG9hy5yBS8o!2v90-OxU_o)_r7P2rX@DvY$KhGvimAow-+>-(pHz*pX)RKSts@0 zWbN(SZQNzmWgg2r*;k%QW;T0nHtzm9{Qa$8(yV-{OX|24Zr_-UZ^JVA(cDr_@Zs(m zm7vAgvS-zvp9pq60HzxdEF{#A3_@9Brol`o^l#yr8*i$3DQY|)Zw61otI5;(=~pRn zat5=OfH9BK{d@U>-yHjXHHU`QnoHeW&OK?%px`?M8=SS~qk6#-o~~`_WTx%n$-}Gp zhBYUxgsc8FZe2<>?f#?U zZL@{j#ZOn36-<`%XHoPje;;M^SbGhFlmRrCXO1^w#}UF;otF*g{Xs(C*YPH^bGIxc?}2D zI8GiLgzk`ajZGJJAFob^YKTx5j+wnSajo}Vf4Gq!O9+q#q4V#X);-26i_PDz{~X=^ zrX1oseB);DOxh^7(gTY3ywgRGhMzp+&GMG(C4TYnt8A7yK`#^f&26vB^V17zAZ9|E zk8KnAoP61(X08~N-#Q_cF1KG~>Vsuq{aRD3j1aBRii3z~lmBj>{FWTW+8GOCmQuh z6Nqcmk<749v{g1LQ`sK6t`7CnFRyNHdi8(OJc;@5LN~}m%b`>x)P+CZJJOT=LW?Fv zYvqUSGklHnNTiJ5O}58XnKGsQv7sT0VKzh?X|?W?2~L^gOvTb&D&Vuxf?kb87ZpfJ zO$uOy0VBF0*W_7-&lHR>?!=w1z=Q7$yPpWselUs>B(l37r~6pob-j%J#?bidm(}Dh zOzx}9FYR-Nw?2GkuX)MH+j}d&P&b0t)4~AlOaTFR&vkR?&R)|maaH@6T^aoYpYITR zx`8S^F(Hl>XQ8UeZ}G7VI&rPyz*ZWH79MA+i| zb#x)h*20XpDu9?m;^~V-QY>x0_(wL8SzDI+oLniE^b65;af3BkAk)2FGcw($1@ikT~ z!fy8Cmi@ZR!~LYji#kZf(u~W|J0;8e8X^pzEe(hVG&sCcrOvZ!9ezG7^)WVXNF&Uv zjdWV;)}!>bG7|}GdVnf;3|1te;_qltFwbn?4kTaJ1Q;%)TTe>#-eeQ^xoe(%;Ok#y z?&jixP8Imc9Q^?~UQSNGGTHD@?x4GdVKGLD#-y#tB9bSx6<1~KTyl*Pfidn)j`>6d z4tO$`^S~GkDT}udOTu?pBtHwMVfM@SO;qgq+HoZ{DjX)aHPcjETD+r$ej?Wz!irCq zN59Up3nO_Wh|EopdGGu}9`V>%w*1+JeABnKNJNb4R5k>C`3@gL>v_rX!)LVo;ELPV zE#ZPO<~2co;%Y^{=W&+j=s?Tg9axX``dVyF{UhcmrFCFT&i_JXw+t=kylmH6ry!|) zNo_4VCb2-|BOY$EwsR!LSl&C^0YypRixqZmxX{6zBJfIggSzcxf2oZpxyLD~>DDK1TAD20cj-v~ z$kGE>i$z=&2nyM&e>c_weRQ2wmYQI74XVz6BLK7deDYiRILY#LocmK>a3E^4RN|mX z}}5_5MG}r*Lz$GP+rj&*QxC!QCv6z7jh7@JQgHXRjKJ(~P^{BZQ}L|_!7%bBLObj;;&^315Y zdA)3R`KVLvKe(4j=YIi9gY;9zNWpaQ!w8espi5#iqcpFnvx}y%EIuHQR^}-)S^`=8 zsDf@bLe{QCUx2tR%u{O<`IW5FtM+Rg3uZc0mUqwcZDl(+ggCQqR5A(vx^Mo0{E&n> zYL;j(!I(-ej~H=xylYDYTfTJlAlFP^=!<6ZVzrDEN@%I8asjk#SCeapE3(dx;HI+d z(+1_vVMVYs;>6VE03Sa0JVjU7;iMV&B(D8+qL#jfVL_UiVZ`^5Sya~*o2`v_f9ovo zd+HxZGQ(H9f3&t~Em|kZp!B6r>hcna;+AM*z4S$VWt}4F8PCMGqtwK|k_FP=K81Lu z$P>u)_K(e+5`1{BeXNZU{mNtc)2eC|t`hUFx}z5MBvv#UZZ+^Xu-#MK5mRGp04LnE znpyuAR=fV$=bIrF1{>-!oq+*&`ACGCyZL2$lzAdwokGZxtdNxGr?}~$63qoQ&;4V> z7`mc}Txexpgm+q_i1?WeXw-zRYSC+-Hrc%I&jtz?oFabF%`R=Dsr=^VIp-_o-JZXT zq$rLlmuY7ZEz|KgTXp3cO3&>G{Nio8WhO~omag`)lK9&z#h}YYjojTbIW9#Z`neoC zE(afGB&KSD+aCou?!9?Tud^LJ{Z}bSq{woMC-Qm>H>PK9Fr?#yZPEjA4Gq!G&z6zt zFkQj#oh3pvDelqPUy@bPab2yEYLykuKLEe-<+^s)?&;AdaphU&ESFI4DwL#lKG}?d z!UzbYaRn5&BZ^`od6cOTL6c|1X|g&*Z@%PCKALcnkMFdT%xF*b8oQvv^dn^*X{G8W zOqds)|F(ha+GUO-jzKw zDh6ELdsjDKZrnzNl;5#dGNP0*Yokl)zP+JBUlu)gt7=3qwWbshwvoW(g3F>e06d%A z-~n-~-A$Cgr_C#SrtlA>JYn+`YCW0&R%7>-9*ySGdF2=ISL`tscQD#{mm8tsqzH z-ip_=narnj7XLomtc&UqB^skVJ__`aE1ohHq~wnZBej221@Nr7U>qL5v7|*I&X{uA zYcM<-6JPiZIa{l5Udxmju1!v_Qvm6~tN~o;ySE1Il11?|Ke1ctBbbhAEyEcKx)D#E zs?-R%LKd^ME!9Gn3e!&{CDRzD@=}H_C#}4J*PMl_{Ws85t+?}1VKN*oF1V8O+W}vE zvPGyYb;D#xO0L@JP*yxOvcueu<{fbnOcVM1(5lh=bmGHg<}NR_-1YVKlmd#$JCnOr zBTi?h&&3a^)EHhL+_lh&8=$(KOy9;hAtHz*wl5jj%Rd)2JnnQu{5NhyHks7XTyK<7 zHm(YjJcSmD4$>$gwI^|mL!%rC_^rJ>mc-)%4JXPlO`ywG)Zvs(wCA9#)?UM7!@Dp)`n7W@681cA3l^XqrHi!9>rc0xlPi57uWQdr=sx4eH}$CTF6|Fs)eFexRd?b z%twx-ltHJ{I@4Z4k zdU3(5%t_t`C{9sRw=-TmUuH^?VeV167bpW~s)&Bb|DFOXKP5tvB>s z%%(dYWn9iZJLq0Fv17@`mI|f^RS8KK1G$xp?I6}XZ_8-?RD?!SfGZNNaW-jYCSH6aH=STEV z7m8u2GdzCMH5@j-Jx_r!o9VKH|77G&#KK9HNh%jlfP?7dMY_y8a-&X#h zNiYLtPi-q1S&U@X%HzhA^4WZBYl$O|)rFA5$ya8(2|h-k_~h*PE)px@#g)aT+TT7q zzyMsAno@&FNBMj0(ru2q6rwCtW?pnL0-_cnw#~!K+d*n&cLs-sfR2fbF0&sO~j@N54}gyU`a48eR98+DxErnHp7XP>2LBCY`&a8df2HPm( zN5;jWgc(Xio^zJkE%8$xiGbgp5&6)%rDD<0?KLqp^Z@2~_P2UlOKn(`Y4IPWX`&gJ zh4oeNS>AxgKq6@RfidPv%c2gla-l#`+WvT)`B*AwvUw_k8UUD;O9`ymV784J)Q+XY z8mEKw+^B3c-FQFf7;q*j7AjR$RSd297u2)sb)Iiu{E@Rze5502W7l-$Y%AOJk^fqawToqYa%g$!!t zIwPg%Fp{{-E_O;@BZe>A#Q3`{JSKcr;F{N=;&#nc`!yUDmJIjQL^j42y<3)I#9Ycf z_$oFN(JcCb6wx{ca0)!nU4Zoj^}wUx6&Li~H@o*jX6{pNa|>MieJjYvON5$F=-P`1 zJKr78C_VUyl=GUoXx|I46}!FfM-L)xt5e9-osEiU+ed61$3+8(tL*ILx=Thx2vrh6 zW>?($A5y9U6aF4Rx^WWa)TT|S4V_-Gr{;!6I=F67#yHkpr=ZO(4cWfWc#r8`g49jl7 zECt{jcph*B(#$7|@5cXrb|AP>%vZMGr2g>FZxC$T<7<^u4M?9u-^G_Xm z+`47YPlV9h0KU{jrSmtCmPGBaU68sFxZ&1)tSiQz#huRKp3Rq8M8=z1wp@n_wwv`b zjJAEo(cm;UeXbGa;(!uWZW?jfD;w2!=)G=k4xMZYhVhwG<4e*UMf?bz{^io;7~2ID z-5+KBaHk6e4t}kqY$Tc+-+p)m0yXR{(J1f94Tw1f=UtBGn8wOtx2j(VJ}>^JlN z%9U$iGCdu?1X7eU$8-Gs>L)>k11*%Ng(-{7v+g}E^!mPZ*p$k2o9B{|T5fEH9lJ&zHaZ-fE=>k_+2cr7Btc7W=<^mXL`22+N3&u84^BQf&ryM+-l$Ayc zNnyfR@*{uou6RZdwv3&weyEz6glO7-C?`0Fn9|hTSL%fw|i@j!Oex&=0$(Qvtv|a&MlbKXgKg^ zOQjo&&;pz_Z6KX~?Xh45``EZitA-v?_aK~T!r3Thu9$7gMkcEWkXCs1U3ay7nA zmqa(D>1lhYU*&Al5^^yFz~T6+53gQ10@MjM!Zk2jpF!mSbPsIW;2w!;aN{j1E-p6g zg@qb`>}*tY^DM8fl7{h82wir2(y~!a*jE$O5`=C8hjWz9oI7@pCvFc2IrAuppt^X9q8jWpoxR% zX^gf65S?%laOF|=)Bs-Yk*vQ5_XXkB+D-@`!t=Y-oE{8neZaaZN36go7!3Dw*AL+Ue44vok(#3N2V5BXVGm5wS&*x`R*evVvDNBH zeTrHT{sBu+5&!e&Pj#S&h*p6EIekPPq%9LM0P24qAFk`pk>jWykj=<)T?=fuhIlkv zVutNYB0fVK&rD_~L z=%>#pU+^TX-+;V&dFHjOHBgU%B2n)L$ZbstO~e#DyQPJNnxgmiaNr1=Pjuk`!RbWW zLyGi1IoiFBmTK70a&?0{4~z=W4Kr83p#J642UFn3b5H)^byIjGSQ7|VBajx0Fn~9@ zySgr~tTg=l(?idrQe)d5gYC&UQ=N;edX?>KE}5~sumH?|HE>;*d{S0BUkHVuEwX8E zCV}(9Jq-_r2Jbg*z@kbJm17CmH%g;oIHad6y$WdrvD zVT1eG9C`xhy$WhZLOiIi4}_;ec;!HgPDVzi7PRQ_{*}R{fW~e05CLo!ppLg3vyMT1 zpR|tj{_#Z}zQJP#J0N-_ut^=KWD?pVRtfV5UCyt75z`puC2Eftt8;FDTh<^R^$dPG z-r-6pcuAC4H7a>_DjaW~nDL5K!)?0+-+K%YGq`%?bP59bGMevWm z&eu7&In4Oe_C8K)yRO&!?f;qc`}OeENL_8Qy!YC~;Tiw(w{MsILU;Wf^)q1|uIKc_ zw*&-KHE;)m#-1y!v9n}(BQQ@QUHMH+G-?ch!bp0x8o-I+S~%I#QD=5{c8;gW)gKi& z!HtE0UCJ;6Z}C{8H`_a5>;w2a^EWa$H++f8;ql>!ua6JTs&QN-`(nkptmrMa3Ev)E z)H{eVCGX!eBfvPm!gqDtvffw1ywVA-^v>nv>JfsS2fUSvuwVwhIpL!_spn5tc7DJ! z64KA|-+6u}V560Mt7+6&?D$`DuBq5*#1x6NOI0DRwi&Bv$7_XW(&T7ESKdgn}zj1RsZJzhL>GEKO$y@K-)^*tc7 z0wd*o$ix`nnx|Mxo-5-qN0x^WtY1|Ug#j?ivod}H8jAu41$YVVN`$k9-`)Ubzqz=a*}OXq%BE45U^R||3E`FZQ6tyMzw zw`g#}uUYCQb04MTPV_2zxVY2-R(j>jwFyRMVFPmr`*1c*!PR6(@!UFaw%kmzE{62g z@1-W>1g|}ZhXoEK)}F1Thx8ACM}~DcJA2#x=u_3G)!|;9FvM*&-!Hm!JSzUnU(|`h z-j>!a^~#w7d!+O+b>)b9(_$>rD(1t_1gXY zrzMcjVCg{)@JoQxX7EfpoMV={B4FEvZliHMi2QIr{)*Jmci04CsN^?N0-Q7($c{HH zeTGY%zg3O^UuxvG$0Zrz?My7=y=FBX0azRt`%NeS@tB2zPqWw``WeD@JmB6zx(Yhp z$4By-0X_%RH+*0A;h&f!h!;>h?{VaP-A|T(AYe1KWS^qSdTF2*pQ8*G{iUUnEI(&a zI{A%OW%Z@Ei%sh4>Ih7dwc`2tyDU?l7j&Kj*AsFwQ49D3LRC>v1xDuX9v;F`AeT7) zwSL4?3hDsRztq<5LuGvgn`C69rKcWRfwUY78ZhNxAOT`#&Ako>HT*yOGlxi>>;E4U z--arPSqn*>q{B~f>hI~6$3GM(PN5eGY>Qv`?d4HxpWz!2`oO{u7%}iPKhNEVOr=HP zn$9o-!7TXq6I}}SzvHBuo*PrGaQpQk8$%$3uD3>?LqxN^^1- z+M*wWgKdhFHD0qo;70J$v_rH2*Ls55$cV-EjtI@AA_WdwlY)Whq=3udCqnRIz+Qp< zTIRUI!a|5Q+UNS7K|ug_H=)YNDgV-TKmcpcDXcESXb*?x8Oz9flnZ->j{! z2EzkY!~-)@G@}PnO-%q{c~9bPF*uWB-$n!fE)0Nih)BHoix-4!1x!y~3Oa73pwSx5J2DzP41GD zk--cb8H0Kau}$AH;0696st6L3?Z;3v5f<~?x0^SjrKZw4JxN99U>Dr!m}y{?d3xb6 zN>Co&?aQJ>h}4p3mOtE@hb$SGQw_fXqN+e{f8j~Fp-5$ACFGt1C{(-sfZ?|d!X9*( zt=nt5>FXNKPH;FNkL?6ES6A;s{rkF&|LB&hvXYW%nHAKl;CKf--F#RK?g1|$-YC1p zNgZ>|xNO$z5Dx8k^Fuhct3T@%^q7J~;N)aW+qSVgW^F=*Eoh0jr#vxmbtdw>Vpj$>j$0vFdD@-Ku!PZ6_C4ppnLDpw=@=E87Z?q0Y0YpsCLDQ zW%PxoUbf;7cK^ChRsc_NzkYY+JS&BR1***}iS(a>wa5r3pI{=BDbH(Ea$3hAqhw*0 zkv*-a&>ziw3rU5g{Pjb$3q}Yi$wY{oX9-@1@h|!mn)koJJtE{_BNn)Pwl8YE+RP)41?tHj&)J+uxz>Cj6{6ZpRI zIfgKdOJJ2E(%SV|Jp*hUjaoZ#ROu@~w4HI=|15C7C+8h~)nKrE<)76wC zJW_#eRXY-`&`@=m+gwvoui)QQmd#} zpR{Q9_iyiPyV`@v+-yLcNtEn#jn`T0fQLsxtNBQo?>FqbdW}EWHV1<`B_7AK_b$S3 zeN;v_m#SjUfBp9J5K=ynGUPoY_Au>$G? zNY}GKDSoc#Jr6XiNL~gl2qM@m)n9aVe}gC4k~wuME?kIDla7yOD8*BEyG0ol7uTBO zgp4V>=i2x%jdc%u-v02-g5oWAzt@om3Vaafy(}H~i!alWS0Da5!oMO4>lR+TfC=Dx z2#FpcTbawn@0VF^Z4 z`(ySg`LnNaIOtcLkq`7lzs%jg%m8AWU_)c{5S3S6nOVgtyw%EYk@%IbPsOrsf*Tw# zl9Q9?u~#zcN`HL&7D=asj4!!(<)Z5mY#mbp2?2~&FUGXxOhVBKlp!Ep&H6*x50mR| zYM3JC$Po0OAj4X4^R{IB=~Qb$mox(M7(ZX%fE-x4r34K>R10U6eG?gEL2d|90LsXr z<`nMaWD0>9*w+I)Z4Zw-;+Wx!fLf}?PUYb0?%wsq zej!FHGZ;>)+}&O$7nl27u=Gq3zTveZh&TeRYP!qsOy5cX-53ZlqTNX7EzLLv-^N~u z0V#TsiI|VCFED&z!VRn3AUsRaw8JQGXUEs13xO~Y#EP>f?9Ja4I~}xu;x8aS{pGFv z0&c)*0z9@r#mA}adk<%N9Zgsz@zL+{yM-ooi1+|8&7zuLqiyWPw-GJN5KTl+e-=1(^{zP2#mk{5ag}!{Cbee2w$e5{RNg$t3 z8A4fJf^^$n>bSt zDnJdD@J_giL!_bLr<}1mEDyY2oA{EZ?oXkS{MUYhNL^WOYiIrUu84!CGp2O10z76tL=I)HZt@Av!yU z-fn5t&b0a&H2orB1NRH4n$U;%e-g~F$?GRHL*97(;=d2^)}Buo%$I@Sh`myDe0&T8 z-{8IWGj#3JG}?*u1hty_W}JZq(CTyWAoiGsck!)>7@l5Iz| zEp}HoU`9fBdP$U)lM#_07-J4P&o78>Wu9T%p(79qUkadCk z3z-NVm%}>o9!A3)NnP=$&#C=+l0q1?EU1=^E-x_Pvj7~qMd1ZWyl{1cP_KNhc>C5B zY>J^cGsm5k;!?aHWgGwtXVrkY2D24iO=r*vox53@b>7t!rk9-RFqC1Hw0P7Q40APb z{G#Lo*3mjVMkqDze8#{-BlVHD;Lkt{Rvshr%E~;TUd-L=5GIID-&jb_-bsm}?}KH{ zaIDXzqY1LFP1RaxECN6(g#C=)+VdRPguOtM8YfFz{n|^l>%Xe10%pJCb9TL3yGxHq z^aWr_;orzJQaIMn2K~i9K3!`L4$uwYOtl*qVElt>=>sSUz?SJh3sCqs!k32;Q!jFP zadDqeS>NqNX3Y}DUohnQd$3%_ruD!N+Kt_xh_D@0*YNaMR~Y%qV;I@xt$4!3#R68m zS^t}1Gx7{ttHoOdZ{NTU5g3dI2an%;70q?YOVTN|(^4*AIc%8443CLKD_bt8me1=;zO)kNhc9Kg42IYaI#V5R#jhYoxfW z(?Etou%&98j^Ql-F4g?+K36xJg=Z^}_Xc$RCPKQVxR5gr2-uheufaAc+sx8xvho@n zl`$GQjPw*Y@7s#(RsJIhOX&gy_T1g9=igw!c#q~e=sehr{y-F3`A13(G{D%wA24n@ zg5=!*UlC$vT!>%xT}el1VSv_-qv0wjmTLNWsX?tCTXY6DT%^^ z$eux1oH3*EdBEAsu1+(I#;y3QHanT;qe6+q!wJvlk;~_mF-A3N z{MZa# z(qktk#g2HX4y&}NB9bGG;mDR#?qoHEvs(sUutYzb=FY+)K2857f%1~%Ca+OJV;JT z;_C~$+1*g*nk%=~gqk8bgU`|(_v}l%8F%JaN9Cv}^_j2KEyKwd81)wh@)O)}639Ty zYWJUzatO=$pmPH2w!NI2BCN2*r5rR#fP=^j{-tqTKw~9-6q~rVeQ3XIo*c>hA`=~J zOw}WaK~KChUQ8q^NE|>@+jdq7ToqkKNn#Vdjov=|uquMZntWJA5}R|9+9>K{&EIqB zvd_lm6KNrd(e0PXY%eN~l2O=See`0T+~`hy>EO%x{in0id|`&R-=COFyo(Ug`bmkQ z>Uo)X{gm1J7CSoWtcV)q#_7DYaP`_%5jQPS>`2r*=~S{u<@fT6<{!fDJ4J>z30n#g z9DlKvs6@A(gDm!bC!#epN|u%(>IoS_>%4}DV0DQ|DeILm>0XX5OCYruw7oGA%ksWx z&vfbeoj*eF6$cueQc%g)H-j4LGWGfQN@{94mWE zibBMpOM^iNBg=bHj5KPh`GEM2cxpVQreZgztrn7(BTV{bWoxKJtwpVcP!w-16WwV$ zD;Y$~>T`>Hkz#`$UW)X=(#-o@qr1derN&}C?<#(O^to=%DV*JSiS+r(SV?rs+{p{p_QQr1*mI8g6-Xd@oWtko5p ze|bBs!dG%tD8aSk1Gkn4kB;cp5pQCn5N;l#7I}A~nchZRz`B8?Vr%UUl6N4tT z@3AR(L=`ce5Z@%4@qbOuc-Xa@P#vZ$FVsr})HWY1!&ws!it`%(csq2X)=5Qfbopy) zAZMSRMpI(YICguaeRnQJ)z6FB%GkEfEU-wbilQiVxFvcUc5j9m?!X0GHwCd1dMH>BNK&0uiQ4cV`~cs%SVVP4o01nPq}0&96R6m_7ox z=pn{OJgLuq2+5EQyzf#-dW2-{vZ*1at?m%H{JQN>jI%#%rsqesXVBOj@R*4L^8&IasXFU6!^a zMxaz)oBKuY|~Ea;@G2X*?ScsA!QUDD|;Lxw^e3Y znMroGva(Vk4WszI&iC_sJnp~lo7)-J^}b%O=Zq=q>RF(2P34~?bv0YM$;geUz_w(NZ4KL8SngC4KS_LVp=pJ{c79@{5l zXK~djXHo;+4eX((Kes0E{%k`x=NnUo5DtUvL$~!G*d=ZqmA_N@hoxa`01Qba}W zIvS90s;3$u5C`uWNsx<@jzKTcdlI7^{OE2Kwfy*FKctV;0oGMNf99YxbtmHAwymv1 zoZlN{lxs4ZCplmuig@wk(|3mtA{h5MZFxPG=yW+1 zn=9~bve8V{mn3aEBK|>}TQD$sg@uI^W!FOj12v55gFha@=g|Q`eVIY-GidyrnSqeA zG5zf32_|>$hh+Q#&-(rgarImgaz$%eq5Gg!IxH*p93fiMW*MsnWeEpeF!;8MP-jLcO z^;E+AMX|n~uP7!})UVfnm;xRD$q>^}-62<1^Q?geS0YKbe`7e?p+4Lk(if%p8g zub)jUI{uZ|7D#aOi}y>QZ?hr_3S*EwbI*ewJo_+qu7{MK6;n20q~9H$wwq~2a)J2O zlZU6FRs5s3R=z<+AKoBKZFxm7PGR_{Ws>QmK!a2o`F8R{p`Upl~u6O!bxY(H$-)qM3UmQ z0{)-(-JjtcM_QiOM+i&*w~LY7~QL% zpas9ne4?^qe#qMybYA44Y$kWB;QDUI_rs@Kv~{NmPc}`eITIfGjln&pf0FyIC=0VJ z$V_8bOgV@dw{&`6o~ps%s^9gamx>mpyQ}l!;ohg3Fr_K682k9Qf=Ti=r9n5wRZ3}T zO3GtwbgSco(ARt)vzay@JW81or6?WCe3R9yls{T)tuH_koS{yjYB#olI?aQGhPurZzxRE#-fkbemGd<1V8P$;-vrJ(K*ak zAUi_Bx3Iy5$!0!StkOix5Ha1DWR}Q4y#DIcy*)qE^I>av}t` zf`M%LHt7dUp1E_P0~NJeXX8c3D0Ez;0FBtI$nqo!l+YVWVop!9q%5g>$-3 z#RE^0bG`D@M}rN;sWZpk@1-?(@xXQ`ApO65K=rXI{K8@oQjsTr0TsAzU;wsSJZyBX zuA5|;V)kPBBeE}k^1byXp=NQo#4!=W^Sw^y7ne%WEygzj5GMj4UlS0Rz(6~yIWrAF z#JA7nb5k9IBZ84Vc-{*f@jzl^e=mNGiY|2qJ^`F*9+u2z=ml<_Ocly>XFyU~Ci6)W zAeD^3l5cOn4&1^rHE}y6I*+4D248(^oCi7sU}?OWDaJ_QC2eyu2ii^{7wrPl3BVOb z-o7PYuOwA{g25Z^e?lNtY`;~%{%+OczXnS_WV%4Q2{Q|{Ks%!54i4nV$bj%Ki|%^% zqxWt7U?*`!v$ND7vzpGTz{0bX5AhsRt=zMA_qly@vwA5jvhotjk}8CZiH{oN0w5V! zMp^kcFlYDCr45&Dp*QlvVcIsEQI>wGp)f)P8z_+$J=5&%6&7}U^6&WWVuoZ9?p3;- z-}Zz@tTl7>y>R77cm(GFRRPbX8KUK*KMCUBF0o?y}nn7`gc>&<(?q_g-QaS!}gkV0LZR%&_uK+6!bf;}hdn?K4593GRFM z&YqWp@9^w}aETjwRTg6IRo2$lPsPON8zDbI#>>L`mWRH)Rh9&G5dX_rPi~II>9kvt z-wtJZ_j_=x{NkOl_ca(*mwx^JT@4;(0)vppGT&&i5WQ(damAK=FFS;8W#$E{$x5Wr zNecU}!0a3-bq;Pd1bmZ##EGmUju zB`^M!*wX!jXJ8NcZ`AMc3lou8`9>oqAne}v_gJwbI{kM%WvFO|ew8Z7^YCX3@{nhL z?)=0ppd$0r+ttgf*XC~PR6VJ^_D|itjFRNHtoPkMWL6$OXz&YMh$K&;F_D!GRd!t= zLcGXR&q2t3+;-?>%$1^Mb@-3sI8c>3clBJ^9G6d#o!f;z33`kEIjQp@3MxM@(6fI2 z_PW~cyO$dK6Q{W4pIZ48ib)RM2l|WV#@=ERBi;YHb&HL%H0(O|KAQt?=KuG=Z)6{E zJ&;iR0B!;FDSNQLs=T%v$-BbH$VdmM9WWv=d+bd970L@O>gYIytmQZIZ6L{kjn~et z6PWoX2rp<0`vXo!AbtR*fhOyhRKO{{4*mr*h0J0jDtpL4U;ll!>`wm4R=&+NNaenR zjxj$h_&Sqj8pi9}T*IG*yJsOj>r?ptP&+gY{{qbQCPdH^1_5A;fvejJyaR@BpnpJ0 z2t@7T-1_ZLa9K`QSw9f?O%PC&L8ozv@e~k=APG?=2UGbB7<9ut=HUial$Ngd{-{v( z3w{F>8LRq&`>=xX+Ha1IBJn?=Bw9|(22iO4RTK~{0BoS}5Gn#uHD*CUL9zA_MPUo@3Sh4<%gXxq zTlF%;!I5c9a4UmSaK_0VqFEB_2$MA2v+&0ON`iF{l9H6~&b{~#Ugk>hYd`>@Ye3HV zA;il;i>D{uy~JppM~}3+ry(z8YRU`|3LzlSL>_lhqDa^ZW;hV>h{v#Uaoq(_11J*$ zQMxJ*o@!Y3HBkThWZTgm!%FxM!0G|~+W~~2?59v@bawjnWfGJcp@5u00)`Y|$(}OX z$0vmJ3xag1ZSn6qD4SGeQUQT&XlNjWeFKr%*7k3&{{kU4BSqT4;~$*L$L$>juebjm z?w5OktGfe!8Z4QZEs!k}iWz`U=K?X$#PzFpAz=xy^?V>H;L?Q?G+=l!bTz44`|)bT zb#k5os}a*YnM>&T1W4TiiHE$_OJYK;GJ;wRI!Hb6os_4p;qFdSJx{{nfj* zA3%pch>LsjSjz)+Bl7*Fz(;{nOdn)HVDi46BS#?nuo&~2o4KE@cq`T6-|z13K0b+z zd_Z3aOZmb%gM8&7dF|gMJUtNi5HR>cZ15GJqAVa_6=AwK2(c;vfbK^^-k>K?2ymJG zp7-g1D;1!#ck+=3%MZFOd}myh^A&>L{rLy~>7UTmLyB|==(-NRaL0aH{SgACyt!Gv z{R%Gj@NW&%@CUEJ*92-ImIO`d^f9~q%uL`n3UTB6t$@83m}$wNxMbbTG4>ycfF*#O#oNgV=sh1m{nMQYPXMKfFM{~Z)#V2lZh{!4&H|peEDtXI zBXkyRSHEVybTfSYJsZEmVRpwM2WqY3Wcu_@c(~F4IVUG40e_RNvOb1;O5ecX6G#bx z!msH#IU;;*kP37O5N%-52=XmBGA`M+gIAf5hwdU4ZJ$3ub;$p92c{f3H1_3eH0nPyS`a-f9~Ng#t;*%FK+#_3Mv!j^XTD z0O1rM%OJhck}`$$Es=hz zb3E(#wF9y{lG_9!ljL7bydTPVLlmhNK9KtGWcJ;~#=;xtE~5KjQ7)O-g6{|p4M=h# zG#&;8!F>_#>8bB=MNTgMMli4oGTFV-mlv*DdSM38y|1xb3qQXr+6j z>O(X)NP*#fCDtYX9yS)bUfjF<>ig%9ESo{T$9I2u*q*XHzPjfWw()i9_pn+8uV;q;AXU+P<0m+3 z7oM}c&zc{)xbZzKuypTTGj*lN-KB0K+IF$p(oqEpU1GWX-#>;cHR@<<4(@|3w zypDQ$(Y|TS3J5dL^MrVb<>lq(zZtqH(X@APPqeH_*fR=x%6>aTzc!T{vN#xXqv9|{ z65Abjt!d3_?qnr2zNI!`*%tx3A^k?*En#W4Vv$%8o$nhxQro>pimG&0%G!uP& z{hX_j5s+sGUyGNiBlWsDk26y#@09!H&kQ9ostYXamR86RtsGI5LMnD;&q#gMIT11| zuO5DW3JBUQ|6Xl(qFY552#iALA?uVFOmOc!D~F4OuGa~re#K-dlM z!1+;OatF*ILPA3540svoj)G5bL+<4onunS92F9Jqo+VJCK~n7CQC?bU{EGeFvdfl8z>bAbwB@MTs$ZK57=KMz5D$ z{pSY!8KH+rt#B8X6e9oSo}{(@{(eHT#>YrdNgNJ`KoL}A9T1d=S_)BwCzSm?DuRiq#`2}0{ap>&A`=ld?&R!8C0+Jm5lAh`v|$}Qe%!{w zW4fyU9)3JaM?}q1B)4Kpsjs)kX*u%WfelocD7>F`~jsvl@yn zLym5_nkn~5tBZ@{se>D@*N2DJ_HlI*kEo-*$<48j{IPt`%parj#ltDV_N5Drq+Ib) zU*`GtSRIkRGtN1Z-_I7B+&LJ3Ta$NZE_fkOP&DmisrxZy?|26&6-&m+bdVLYi^?EK zy#VjR5422=m5+qIV!c*fw&Gf!V% zA*GJRq&{j5?73a>z#3v=fZE8Ni_?2_MraROve7ueaMb~2&&!r!H{7*x-H zM)O6eE0U6+?`l8&x1((&t)!$RBNHdB@HQyvew`TMsR*+PA$l(fL%RGH1lceO5T@)+ zb;yIV^Yo;)HnH=WJKpKY$3FV~4Ev>Q@# z#YIe4YFEhzb|QkT`lLJZfDWRNf#Le5{Zp-eY9{_G0oPs(+qv?eT&)*}kyW5GVMqD+ zI^=ZH_Ma*6;wB<*I}@BA5R#Vl^r-MZ;UIhshs4axjCseA>DL$;dHKUi+kftmLiYH| z@0pI{kke%B9Z(j6E|HFg<_bIv>{*i^KNbp>c4@WWp{tLF5wjLVI+3S4r~e2fBV;Cl zI0O_uCtu7vFn`bY{H&`ZCR>pBYdw4V8?2|osvOliI3J3P21NnDD>@2Jd97v1%osMU9MlBVh~~aOM31?Y3_EW-M!u$c?F+zUwU68Mr=^a z*MbgH#^+Nw%=iNXx|j;&ubU*g9~F4tX4YpvsV`E~6A24>q#lP7`LUcfuDMq^;D$gk8+;xc?q%!B3SYigEG)1MSzqCULEK46)A`z zGZ7K+a&Jf<5r%%^tFr(QpWxu)M-vZibQ2FcuKEi(fd|pnDQ=+9=oA#eTHq(<@ z2g@lyRtY!_+?nTL_URLNYy7UkNkLXQNB@$X)Pz3ggt^qj>%|e(;HL|eC^ zOMLi#dx2M0`0(EgiZ0@r$|4|n2lO39w%v4$mp>VnR{C;Wk?&Dw_>#JPVbP?y3AZ5m zg!o-Uxmwja8%ZC6hlx*G$L;RriHWqx2}TUWizJ#s$AdhJmFUR6FAcdp3G(OB8^hvd zv%=86D-AP)gHFu*FUuumM89>*pa*a zmHoJUdF@Y%wbrsA`)`pZ*@2DgotH^(m3?Es&Vv=fpq$MUY5S_{BP2`f?jusLg4z)S zXWnRNkkH@l`>%M!uhi}QCzEDbhQQ0nK|#N;U5?=mwnfA3M!vtm1oe-lLoK?1!+ATeDHI4sXagTYMrL~DMyYs6r zNqs&<-^dd02=LUDE`0GH+*sx{OIYF)TpMlH+q~8yo-p4l#Gc=KL%)6schl{K3dM5H zptX~IL1V9ll8dpOLDz?w5aV|8H}ym@^r`2)n=p0-s18%_!^yQt;yzZ^rS~h;^;23L z71CKEOcK|q>hkn@yf76q3=^v0IR=MT{`AC1FvunwQ0935 zYq;{!e0PnKt?+gF=VgH!$L9r>#@-iOoFx`2e)wLrckH~Pn^od>sdqcy^%*Pg1~fhW zCMk$C&p+DScdMc()a@?ciVGj8M>o4^wUvd^>Z)HWk*>R99A4*dTumib zQ7Aze21+C3utX{YWQezCNU3X%c|T8ytDg9~b(c!xQP&P{iB0tRc6c&x2RfJbU%ip= zYcTlaQue}^eXmzCL;4+yT91jo8LF$$KQR%de1t$4j+)%(>6DH~(F9UXcW)HMeJ+qA z(e7rNmD9iPERE24P87w4Ka}RH>e^zjNS7-xk#oz3l4Z?h@ref=F`<)~>ctkblgJV?%W2PbZS9q`XSwl8Bla zrjbJ+WJ9SRo<8TJM99`Q`_Q;qH52|<&wiZIo#^ty7@x$GzT}P}M#KxdnqAicJ{dv9 z!EN-E^S;@wVri>Nza~-2x^I2@AG`2mVLhHwaV$ER8o~R5D2kp0@k|GSWI#lr zC=u1f@m2no9Trl0g{c4i3B|WKN?F14|LxPHHcwnMTXc*I$CBL-s@LJ7LcE;{XJm8o z4kXcHtYXa^t+Y&JsN#GR#PnRER$fX{QW7(pZd6T)~GY19j$9kn!g(&zadTxkO@G!3yNDB{9 zti^oMS*eJZNv_@XkCr6Uh)o&N>=MiibkhA~poUHUFikON@`Jhd5B0c&0|#+9`@vCa z$g|os$M08?8GT6SFK`c8{1~mJQ8Xa?+>8;Vqdd9vgK{?KUaFQBbFr3I4kALWe%vU& zV>SDEnqIYlgTs4;hjI_CuM37}BA!TlxbiFU`CZTt=d;j=`o;iXcMC$rFxtFKt5RZ# zG~O(l0iy3ljf92Kk`8vh3KW=K76Zg%7TnU3abxULLo#KORV!lLhm;<3PjudU0W#97 z6z+K`l(w=Y(d$Al$ayl<#>)XuO(uUTitMd&CsE@)0Ew z$B;c=&?z-HlU|rkeA86HVWG@~BRaA3SH0Dn{dL#mj!Mz#aX#w+*5AJArnNNQ?;a1B|cU(KxMPPoMnCB-3q*{)@T#gHP8JbmTBZA-J*LYB z)r<1*@zL&^DQUPY)A-Iwav&9f;O8x9{UjhjPF(W+EW(7eSuItt0*CGQJ0JP84u7u!F4Pdx5*%rOkB z23SQv`wh(uRl`qdhpe`_$!np$LZIs!ZIc(G8NxYX1T)ByD{O#d;O6i==pO)GJ^_}) z;|17Q8CZ*h*D;ZTA0PPUOM6ZDnrJbJIv%TA!sVD)pnrzPR3T&Vj6DMJ&J|&2vn0|v z{I0^}kyLV^QDU9Mj~mmyM*|XxqvS|64J>}bjT_vzWt?g{LzO{+fl5E$%JvENp@d+y z*i6p-0l#y4y$ohSy836do9?3ZSjfhWkl>J!*SlNGY?DG#7mY=1 z>TP|Q)!s7{G`QFa6TM+8V@ganD#w#nk&HOvEOI!iNF5WAqjRojq;j+^E6u=U9R_|` z6BQto3EmrU<}{XQCi}X&E-WboS6S7OhIm;I=!g!W((HwcM{6eQQ>z_C+1RRB1;B3e z^YiBzFYBC_?hR_Fhee}7T+>01dZVY_y@!mm-p#jSyA*t{>-8 zA>aCVCWS8%DKY0NAh+*vdAiX{&jced&k(AnMJ`~6TftRZ)$#7ON|jx=j(%{@$4|U_ zl%dtE$`y5^zuHtJ8a-WyBAREow}ZxDt5+wVXPHp`GD4D8m{2DD)EAtXo|Xk<8iSPW zkf2UUdh42|i)R+!Wb06p@jH~{`x$b`v=IDIK+T$o(NqxE%-^6yOZ zN@gLUhiH*UyFBE5@I7UEQH-)ra{d+w`@7c<8rR?_F_~O`Aj<*X<2SH)6g(iaK4vh& z)SUtKaI@EDvm1@0SgyfUur1iL0<|fi#|-foDJgoYOH^;}cV_QE{Ax} z2cLYkw2o)&f1IlrAeiglW;MyICi>9FOmu+lOtIeNi>JYZj8A7h2c0ZPL?q+p7Zk3@ z+&TKd7TNry5!?R3{vrmIvW}|4O%>48iD|pLQ=j2^ep96!e~+ze&@|uoP0TkyXrY}= zpLASDo#|X>)gu!gLtUNA)R&7pH7l@FDxP{^es8&JeLP~reRFjFw8GU} zQfBT$ULn*s*)QD?zi8E5V)82wii|@(g?k+QWE1rHM%E1yu3B5h;WDjP|7mqIf2-*c zc{3HEd#mbF)E##_y8;uDq5P})0qsHCW;RU}_7)1cT6|R62_D?pL&Q-y2GOap+3R?q z97I4C^pn_i-4Iik#fPtd`BG}@NnEbk*faHc=J|?3Q`h;%?N^8=_4^`em}ar3dO|nP zj|V!xw5)$OW~C~-`(tfzW`mQ1w#Ys~CR9A*Db^uO`!7G*ag6e%7l#*`lf!}Bl~-W$ z$dx=S@7BD`&1pYQLR%AMBcH~v2P6i9B+n{m5~(#*m9~1(Pz3jjLRZWES;Js-fUOL9xLuiX2$a?N@dorOGXC z==sE!bQhJJi_KV0z}IUJhuIi*ic*ph>>He69)bz%L+*VR4ORkvBu!3dTB?CHdSqZK z`1B2hZIzkdIB&)IquA>0QY`8N$IKF!gDqQ#Ssg zk$}ggJ6{1`WR`v$QW9P$ydPk>uO2Mj?{%mHzb$+pnV>$%4f({TIR>K2YV6NZzmo+3 z?*V>)ZdUp9>C=vb-b@@S32|2KZhG9{~5n4+1d(Cp&n7-6usn zQz~(Hz%Bji^=t4+`2oE5XE8Dot{1>-p(^eFT+oS+A4h)ku%(K&1Ikqh(h0!ZZ}B|#sP-PV#Kad z1o738^IlEBg96D#AgP}YC;_5~8wU?BaO4l{L&1nc$#Vj&_O0;y0R3kVovhiOtid%% z02u+=4FvfDK>uJ^vuyFlZ@&UV$<^SmtUOL|eJs{mntVa2THnB zg8s8^4Ib)i%D?LeZ{>>h^mToGvD^-BG1KdR*W2{^AL~g-JNwMk-+r_5Y2)Th*zNGv zyJLT$@#*uV`Ax^fj}3Rj#4{$WA`d?K42Orhj*X|?t(ONSExLQ$qei>P32UGbniZzcj`k)8UMQS zv@r|$Rj*I_r~GFvX5nWd&5Xo|FNW^*FvofcwZY0rzI?3Q$cM+7RhmlwSAvuJ7jH8S zVfLHAjWl|HytCW|{^?{c#UkM&0@pqr1ft!)KxDTP%5Ai^Zl8~~75rW}KRMapHc^^k z8*vD*cuqjSAK}Ia_YQm!1f2_bxPWqp;<15L0m8KcK1MM8w*f8;cL{lR7^4~l_Q(UB z1UB+|UicGWSy;dDZxe*9K_MYN^NmCMt?mu40Iwz>|AB!_ET7^2D8~_`bJrt}Cg4si z!=mOJGsJJqf!}A)_5@@LU@sfWl6rtP6VFIO$0Leb9$aq+COM+2hBRPg`&7TEubgH{mp4^aw`rLRfO#>E8|f7P&;V7mUFFoYncQK!2S z2-h~~Qsk3g!rS$ffr$_*8`7z1Xy8dU9Yg>O2|7cFA0pg;l(AjYpmQK7G6)Is;IOT; z_zONO`*}zVc)jy#yPEJ3f{TW2P6JvsmjI)ux2Q3zyb3Nm5Cdk2S^fa*{0nen5VH`n z;CI$)(=`{K#vP!QfGisNqE~PV!o3c`GA9GqBLJBzeyj|iNbZ0Wq5O!Dw3Knl_GWwd zAsFev+KQ5X1V;YQgI#+b((fgkIj^4MGU} zF)Ua|fRWSC&nuGB!EhWrK`ad4y@15=B9{|_p9fYE$0 zD<%_3s9hr*g>W{@g5i;{6M^XOH>i8y=Rt?&0G9|fN>Er4R6~18J3c4tJ`B(Gd)|S! zACv*7ggTQofB8p6o-(iDbBBC4NTzaw3kIU?Zi9M>U~PfCct|ud^JpWGk%Jkh6IcH+ z@;HIuBz^|?5r~t>v8pt$Q4T-Yg{vI4n~1-w7o=#cr+k>yO0X6Fv-@gv)PpVJWQf|b zA8+5jg({oXv)^BV>HZH$tFT&D+l01Jacc$8Fgo_GfY|5KjaRsl4IlW33G~6+K3h*jZII@MNx8M134bf z3uhE=!VA0E5pmh1viRS>W7`F(mz2(N&Y0K)VL5}?m{W=T5ucCsL~PC5Xiog-w#H6_ zjd)ldq0vEtnqHna(1iqA>gw?LwS&D?f~n4TnK<|~;`m!r8dffquxV|cBaTAyJ~hy^ zhoRr5e_u(U`1|bu`Qozcx$jGiF(|g!s*8uPjRNKiysn%QZn%Vcvs+vFO3)EMBJsM- z@Y>5P&sT(dEq8G3Ma%mW5+7~J&(Re+kRR0=U>C_m*1khWYx5sY59~*%>8-1GzkGhU zn(j3`U<@d+*|;9Oqt>4ukT+B!x`ss}?gacVqXRB_IIagaUH~VX zF%)wzf6ztjO~}rj1Bj%$68Sv`S=1oV;rr%>;`i4qh$7)vq04_~Hs2ELzWv{C)YoFg z4{u)c4YoU-f6BOOwN3ZwbO_R$T!Mn-8h`!JJ5Dsax6>A2cM2*y|JnEOZNnqvW}xTw zJh|^-m-TiDoF#d5xU#J=WD3gO+1})txtAP^Z zkNfL4gDha5tsvWJRFby7)V01CK9ZY0J`e-!#_(wu%p z4vul4-{5ctMjjaAVqpwy@GL8|_iUTQ^xSU0I{mQBmp|8dMNayO&j8yfj^677K4rOK zduk!*PcC$22^KD$&2zRa82a2JSNs`1{38gC(dvvEd#Rw9ckpF3{u;XPM~hg*Fxy&V zEYI2gMjSSgL4c3ir1hZdlRI8XTCUc0IodLpE0^nAnL(Z~jw%m;QgSjhsUUQY&JfzWr*MI%5Tp2+S6o6%hVO z8B1LBsF?=Vo;GpmK%A-`r+I_3W%4Qq+RdUBzZnVE#(E^6<4m3)9~^C5Q_XE1c@&4w|_W+&JdUyo?*RW z+?0C*=skPBrdmuvr;;p?$_FmsF?W&#St*=L2B3ZiO?n!Zd`EDExx+#vEtR@9TzN#^ z7GeNF!x#y6ZP=Uv;zc~AIg zre-+uE>k$hp4H{0fZzkxj>*~C!+$%Gk)fdn5a$csb-gUMIXOA{PrgH$8%^0O z9D|gvgn-}{%_DgUdsZzYh<-s>j3$1THUzEvg_c( z50nXja?T{{Mna_!21aAW$Yo+R9fj;)N{<;F<{Po+i|P;vE5~$laTQ_>lyg9J19kVE z3|IaG?ORm;NQzWZZ6GJ^a*Cz8cYGm)lTFv*eHE>UK1Hp=!5JP<@@*VPn43?x?2~jH ztW7}v)7&SPn|C61+FAaz{rDkTbG2zBcH__Y`9I^89e*dK%8o}ae!21GESAIFu5W+6 z%iT$>R`ZcDhx9{Y3IuFObYEuSverexx08m2k$>C@)Ufer=0nxKYiz`-Otd*2qfLRc z;@6u|pgD0lbM89oN@T?2C0f?Lay-AU%eti13Z|7N9;-Gxtcj5D zr#><)rCGY(f6X%8R2Y(}VCTzJ!?_Azwl+66VeEj>^%Z1Z#Vo-rnP^Si$51S+0J3G6 z=Ek>v0`-XYmAy60nL|ft`~nXLOr}0Qi}h}d;NT@>+<|8e1eFeT{!g_?Pj*v6BA&SpT?$JG!S%fT3bX^w+pnt=c&<6>!;0PHeS^?%N%*Cl zeGp}pu$}Ee^R}jdMgzuSqWuA3JPc~-&M@Cf_1(F1M{E$ZQshW`3*vK@45ETDAKWiH zz6Z4O!N~$h%HgTrV08w8!XvvNKL327NTPrUz7t7oBB~yR?W&j5A|axT((hF&J}xjw+T?CpW415Hg4wF88$3ODe6_(#DBs6EvBs)l&TqkL=%rUbYdo(TwMF_+ zbNOv$=LJ9GybBhMj4|}ioN#nh)Dx-wDJ z?UCob&*It=?)+%^xzsC_p(Rc^_3YgzYvvKe8`VQR_dn>|-AZiluDpD%FAdm*k_o zotoJ(g?^0!S-)8+`)%|x?Jpqcc^96b7Y;#~0|AxWH78$cpuBkF_Vp{ja689J2LJx7axM=*qj43hvn&`@*N%jxeAh%AkSP*H+RmsFHF;qr*y_eu+~Qfx(_ zLXsduA0*}z78}BJ4{M~R(a&Ly8i>qBS5U( zel%HA4bh0X1{Xm84!vWrxrdHHB-Q`rSSzE^P`f;~uSvpoF))#lP%IBKHN+MFgv7dj~^37{Joty%%ofPjf3}h*;fC%lsNq6YB1yBgQ z2*9Ky)_EO|Xd9$aZdo)R*q{^h*>;W95gH!Z8M5h8Iaxd{w z?+OTznDv%QMm3+~IdT)hEsk=lHke43tE3*Mh<*cH9XDTbN$TCN}Sjx{VIO z5}9tdDQubU4780CE4r_|5Go?yK*ry%4^)o&A{m;$V&rmnjzwhNjJ^)xyaiWJ{z$*L zI|O_On_(ij1P74L@O(|2Wl>^4_W_FIt{=4BxcO2;HwGc@(WKH zj<|a}#})OAr1u0nSzq!N;~t4sM^$}%bsJ=Ia01>&;du}_x|A_baHab9(f2lPgOHY$ zp1D-Wffg_NpTFCf#`Z;=7P&E!Eh{RQsd{qTpsnurEZ`9nqRzH#WJR@6t zVtBS|7Le!tLnQ=6>H)L_(2GDUkgWkakv#Y|3~D-v9;5z1I%BZV3IdqO*@+QaoqkFW z?{vvN<43IA_MF%1ILGKX_Wn(e{(oEyYD*8u)y`3#5z|yZm+sVSPfr`29dEZ%j@0d` z5jtn+dc35AT!p?>h~WdkN3EFRrSVf@Au)9|RwiSvy<`B;dniWsNB@~)3I#QT)K{&% zau&-MVU}$!PTx~{Owe85i~0&N?&#Z8jOTU@^zaN0rR9-QS?@u3jr{>xu5ugASHOEv zfK_R;voxzP!Qcela~?jVcz;f_AzDkI=Z=uBY~O>pkOx`zv9ey3eootKMb5_j^im+3mD$h0^Gk{(S}y8SYm`Fgg)Fk zbNdm7hCbXRrH@tGpT~RQ!OJs5%nKhF3tmFZP8dHjTjZXyQ}Qjm1BZyA0-e@F8*2lJS@GO(jCS`RoMw z&e9Dh$t-U2(LvP&jF`GDH!(bAF(eu3pJ^i;pE|AhU0gayimV7u!PcWnswPI4$tGm|+f>&=7P913o#M*&3=9+wrN$ef*)#*oIyk)Og7c!D|@Kr>W8|cY05C#*tm_g5Y}q{t67$fAJAF+QKT5ftBc(Ma>H9Gdsgb@0 zorGIr%&z43@}90NVBeKsvp~@}TotHLi6btk!1X#PkPpW?6Y&TdHH7Yz3m8QTGzPQA z!6*zW zyMO?~T1LixiW>(MHxu~+sGgkf?s46ZD9Mjh!2yt^kHHMM=C+VDSynZ8wYctDrEAJh zScyttF+@xV98hA#()bUqL#&QD$L%A+YdH^$NcWWWS9uMpE;A}sM5*bK(iz4awO?`u zj&UrNq++Lg&b5kbx!^S=B7IF5U-Gk#S$J>CZ%xShPAV;kCt+I_-|8{L_>Pn~aq|Qd zIbD?q%D>;MA#_lR97Q15q-5+EVtbp>WOr5Sna5V(KCBA*i6cUwleozN!vU|v-j{MJ zhO@+1T;nTvb`AErHRe}niZHz!i4m`yEt@BoNwoLRI^=VqnV~}cTvL7hl5)>VmrS7L z==tk!g&7zbKA!1g1=BZA9?{cS@I1HJXqmAme& zdFD0Zs(Jzy_Uhq?28y{c-RPKj6xS#<_&hT6?pbj(h`3Y{+A)5)%bFZz9wc&rxycU0BS3j+k`DUUaGs>CVsE?JK zjNJacpRp>de1!>8OP}0+UX=;uC^lc1XzqTw;KK{9!C)LZ#YCUn+Y%Q5<_D#;VOKBK zRZKQ_qS*Yv`j0jL-WQ%;Dk!fgM4`8cR}}JHw8S`>*gO%&Yx-BT3dd5q>3;Zp5c;#% zY;x^ao#%!a`}q`;t{49#N)kD^?fFp~aY*~wM588Jw zgwj^Jo*%Xo6%p;$5YnQE3*WJNMfn@ZvouyEreG8e*hlQ5bnvmxB!vf;5=%^;`SFO& z)2Y4tQuBVFL|p7D`Mptp{JUlyyi^1d5~75=L%e2bk?v8fpyb3!BDz>ZI5W^UD{otI zsFkCm+~{Hq)yk)|w6G-fUCV0Z%Ye=cQ=^c5704X6A#y{6gY;!BJyfyqMyV64e504& z`APQ$)_65aL1zm0dfTc@VP82$gw>!9lFzkTK<`XaJ%5hGuu?}Km#X|Pe2vNjtut0+ z1=4)?T%P$m%zg-FvX7(Cv?SFqt`?TkCzrkErENsEFrLU*wLC@2XsGR6Y6A??jh6IrmbvGm!9%)_a#jpM8|qfC@(sPbGya}22&ym(lWS@ z2d4KJ1IrjL8~Ih!6rtO9d+X#=UiqRH6TkC|)v4pTS>)T(ft9{h?y) zu=RWs7Dq43+y7!>~8 zhEk&1;0xjIxDD=@+OKzNX@#Pa1DF{Rlpdq>e3a2qvgO6rM&6_-ZmayBn@MPbX@u_% z5RwO!dw#15DQNl)5c@;lJpi?1t1?b5haODg2sTQdzwR`sr7j63eWV((25WbG?*}B# z0g6N-jZA(I=(g;I|0eO;}S8;BL0{V?7TG&HWK&79N_=15 zpWp5F>yQ4cbFOn;*K0kW_xppb{?0Y-*l=1$+;*cj64~B}kx3wDJ!MP|rv0F*#u)#K z+mJes4x0ppb?q-dkQ*OytF{xpaGAKq49H2De+Flc;){c|S2VorwKLf=@1lF#+S=aN z&F{AAk&C^1a#OsRff$B){^Q{uC_2KhcESTX3t@%QoG<9q@bBrJZ)FWI-cDwj{naFz zGkBrdG!eqkcC`h?79^?+_>EGTh@5Y%EkoYA4&}D}QbUm1@L%>3tAH_%MtHyjUx?%O z(2MVVinkv6@LK*RzCLENSDtN9RAYZnnE2K(u8_^mG$fC0SypeF>br5>;snAm(PY}| zGnMMr8cC6*>-{?@_3ohZlqBz2iTR;SR}PsWqd<2PK+grfR2&iC2-qe;1*9BepzKcZy!iy2`wDc z`;d)VVy*Xh)d@k95L9-tF$v)fvE*Ti;TQ(~TuzOv)RO+yN!Yx+hAl}>T8R#^0x-V| z&vhX$8Z()7{sJaV`viOR2#(1oi6Y(Z1Ywiz9);#D3_5t#v+H+j)ZHhFxHplZT>wKD zR=>-eCBkn2rc{&tJeJZ-F>>5h_3lo8(M6DmSuDf9vmr4`F z&c~5^kNvfUgx%;|g$@(@BvGlCg3(1)hd}u;aY?yN*^ACK79#Y#b2_{RD8E9U`eSpc z*Di(*gja#7pDYH{n$=4aJ&Ku~jKWXDoiiz&*H*W7$EBnb_A)mM1rBxzKuyQ{!l&aJ zah&eMDC`Qt(&pH6x%Mah$&;CUxSCf*o%^#gmQP-D4FTf{p6RLT5?(lEiX>iuJ zTtTWk#Wy%^bLI`*0s%UzBqU&45>W*@f=>TTwyb5}I+%D3Bq=pPfgeCG0Np3R;a>Jo zhfV(-4*-oyuAyH(0Afq-{dp6Q*$4lR;5{} ze@zr}QqjOtD*;XlLCw^nCf^c{VEItLZrb91xtsBWmB>)wW`GfRfp0uJVIuaA-lK=- zO;~Je5gBxCeRm|%VVEGY>hl+!pFdO`lp|Pev#e89&$_6{FNi<;_vG})j>63B`7vt$ zu?lFy!=_06>%RK$^_S*VHlNvF3r`N>IAEqA&&hxL;H7OyKvDgDfB&~;N3}CI0*YazTRR3m^{;Iefn$g+ZhKIgp9DIrX-R2rc}rzE#9v zZ{ zJKS-k4G9-luD4P8Az=qH-?z3 z>z7~I#BtlZmhg$Hm$#0%VG;SVB4Eq&rD6H$?0fl^gP*FPw(Im3*y5G`^t=?7z8j?G zJqH3WD0sWAi>l?v-|t(~y#Iqgh3`DSZ29VwKdsiYc@Gvj7Y_Av6!zM>pI&+7 zB*Uqe^%EGUSlB+ey|$j*YOKXuQu!PY4*drzX=c2wIW(bdcylf;cpS3Oyqh@k%G=Oe zXVI@@nG?UKtR8FN5i^W%)R{Sqf+x$r5xUN((qL65Z}}z_hen~UaAIm+P(>jX?i292 z@aCQMy@!Q0>kkF`G$;*U;1lqL_($S3Lbo|KrN&g?_5BwGrHV_p8z+YOBKGjhf19)D zPy(#vLZeIvpWyF4B#!`&YV|(e@=H4*rKf>KfvSM7sb*M(pi$E+D`K+xxtC{rH1n{x6kQqmDULxJKSg#q_3 ze$EIIg2h8;DrL_c#%xR(x*kWmG`dHf{LtPoKcC=P^U<7OC8+`}_Hy|057d{I7`t?( zTV9>`kHJ#t6>gaUriH6lHFcN*o+iFw?CSt)Zo!oH#ublR)K@GIeDb;xs(M=JKU3K% zF#l^b!(RAyU8`F0Pk)4K;VM;%$@&CT8Qj0yQ=@|tveL7|#jqg{!5Vv6_M-!>0_ub_ z*Zln9x&wM^2_3O^lsHdqZ_+7`YOk*NveLl45MrOxT7qe(aR+FtQ*;dw{S*l=EspE9>4*fT2 zCYiY|V)!eUI&aIakcJ}u(XOdFu=#bggK9J=#d@PYv%ZdF&limK5<%pyr#c^a0pd;E zx?vS8czS&%%+%>8J49))(AfSftPjEVztwDlhh&%9A33S|vqE`VETd54a$R#Mp2cO6op%MdYHS zD&Ni4|Fuj1jmw(EH#O45>c`{zWxgu3H`O#F2c0+qR^-`tW}-t_-2;Fx{wOWJKsqYlo>9i+RY$3!hmD8qd4F3Hz2 zvAHR1&gK<|^KaU$_-l1E_kW<^kXfLp7zf_BW#xD4Niwz|B% zn!Z+k?tgbqIZhG&|IcD%Q9mVz6?4J0xm*B;V|82tyRZ2{Y_fLdX9GZpUF>)+w)VGq zyV0VQrHM$Lr<2_-vs22Nyyi0$HqY(%K#SdG)nB7KQs*KoHH1JevR==EgX4}aex8_7 zrkv@7OJh43_d;%G>!{#;KpP11$@H&YSBv8NE${x!{(IX4YII2lwrG?iHHcZNtS!d# zdR}5=fecV`>r;{{0z8BoA*zYr##H+*F~#JN)`yEf9T>vUy$E`ocYz&9gLNA^EY<4-0HP6`}8Jr87p`bpy-cNY9Ge zE)yJ56r!K4?E;@hQ9y9$39?2;^N=DK$*&Ob62-2FM(!@iKP*w+A4MZwPvjWr#sDGO z`B&Y78{vaLA0QA37RHkSd|QZ0F%8ciaPb$z>NEoTiZ=cm^GzFQUxeAn-Mih{T#bY| z8gr#TXJ43^@c_}%Lx{-COf{m7to{P{(PJ*W0HcT_^W5-1BA$2bqkr?|=a;~_Cx!s5WYnhm&g2kP4T_``M^#)3Ss5NL_>&%{k(uaaP zdenkVI7ST9=34P91FrZ4_r<0m72F)CFr5fVv5phZ$A7MoDO&z-bYD$mv#;+$Oa>W- zdsIZh!69l>$X?euhChC z_Q@d>tQ~4 zBx_)`y5jqtp#UQmNa>$q_s~j(%^6%Zxy7*im*O)vyME%{V7N1@i}B(7h+GTBA-t+uxk5>KBQ72JS5ZyoYu z)qVym5=acvBd3I{NXCL}tn>7bds&07#Vli#orsB+wz&<4l2xak1|&Q#`&@tjm*e?DENv0R~ zz1SlYJ%W!Q4oquWoU3YSo>6iq(&GUvuL0y~WDlW^{xh?}-c$HeXEqcVD&K$3>L zxe1)qVjFbwYY7Oq5!pGs6;)IO)$QaLpv>q!YvS)R_NHt?kTCxCm8h|@xl-PaWo>Wf z#GPhz*6y*lC{m04mxtC(-u*nxbMCWnIES(i1TRWZO+=$ar@iWe5*1qR;12UL+1Utq z2SN<9aRVrK|9n)o<4S(%hzZ9_u~Mgt zWfJ-dRDWjvibH;HpQ9;R#iL=I$SGg-V-H1D1UAMbXA3zQQlWcJMlF5K)Rxv6+7kh- z=AgeHC?*ZgO^PW!PCx2HJmqulSx@eL0NZ^%JzQF!^TJ`g7*0$e@=^0%M=TqIL7F`IvGWM{|Xn0{bi(^e)E5eix`pKecl*rP)?H!dO4yPcVqrAhQ z?QN9hD*UB=)ckt=^BY#|h^v<~Q~XPrG+6bB9CB@SOI&=HS^2E2Ck1O$gO#XNS=154 zJed3^VJ5=O&N?cFK|!yQ=(~pMs|LwTd5d51Bcl!TYk8^p36u+|em{03%%V76f0LX|xg*EMP@@X%bCP4VAAn^rCElh*nprhOns_6y zZvEnb)~z2?GsM5>;d4#jTAB2i%@8s9M8Gqv87PyR9#Gt?Oge! z5%8<=aVw6pxR={~x#Z8yp=$5LGA=(aql|C_yqWw-{meqk*3m+Xc)4MUZIEFgD;}M0 zm(XIF8fk}YdX7f*)3(dl9CoqVbjH)n7MJC?gGmtDrD{C{Nt0}Bw-uxvsc}Et?so9A zyo9Tdd~90+VNEHqQ5Llh0oWd=tv$HF+#8do@I$8Wygb5-2^$vawk`YFIaTVO6)Wo! zIdiX}L{_*qsW!rZ63gazJuFO1J*AiqVjoT=){GQI^A|-MkHe8LsZ4m0kcW=RBWmJ& zDQH-}2zO`6Cte;~Lx<$wElGg5?~upK(@w*{TB+fJQ3c@%#6?nODC2?*7#N6DYlwYdUmIF38+od24D*g!Tu@Pl`LRDWq{RXc zC5Y<^GD2XXR)oGukdRyU_DYT2hHC(E8zM?z7Qz@|<^PqfTD$snEI--aczNT29DQ=A zY(iwsm2|yj*#z%dT!90@)L9bEfisAlUXj&vpa$irk0tyb^^bnYm0kr~6Fko!d6W7~ zIPuCF{#o*)I}c7;Fm4qo=xnh`Kb)8$16l5lYyyu^MeS8`EysxRlup_EMNiwzLwvZ| zJT9}xU8Rtu#b)3IYT14y!xo8^iT4Bu5gf`{GKRe~-vdId-SnZG;dHe@De;jm)*pzsBl2{D1dWN1(JKg6Dy8*6dEi|Y z>U%4CxO~XW{=s|J4Gwyl`MOt|PCN)+j#niKi(_D){Nn$s@b%+%Pfe+LwuXZd9tlxD zj-Pi}K{}i!b=#g|aK+DQUl}XM8s7E0*)@|_Bd6 zVGX)oYW@mpM`~)7*{#gW+xN3Bv}9QkMsQ+vA6Xp1VWwCYFkt!tL2R0a2B>x;u9n7+ z#236GA4}oC%;H#5Fu7r?jFo}B`%@H2zYV;qX^4G6aZ6^uPiF_)vu`Z<tt+C0VG*FPJ3i`kBA`bmB?5dJr|N)(_`8I(q0ri%w|z;WRxv_iOYW(a)_7EmRDf2#(&N3`uKI1iz30lY znXf=p#CD@0gSz4P%nZPckQMuYl6?=D@L*3cVmI#qdJjqULhM*i&@t{)LawOzlT zB@8A6%7547)acrNm7dK;f`RWv)tAJt^O4G~12hyI=3TvV-pXSj; zp|&*c6fte#?^408PLHC3MlZBJH$>jr-T3!#SQ9JGqwA_gsuWOfgOjkD+I!%zl=vL3 z%Fb2<_Vd)-AU(_V%$#Z~>eqT+7DXqAHlz^c*>p&e|$aB^_} z*YO9#MEEs)CYlm6xSf0U{qCU>KwmqGKpgMDJv6-KsGN6SUAEyu%j2TQVQ zZw|jknud-L0rtui_ApD#OUZ}9>z4t?`FHj9>u(A_J(KCO14Ia)<=0>GAh@DkGSCM7 zu9kaLObL0igVAIhj7?v6_J&?iTkVb4XmmmiVu>>}ho3AeTyUG;zJ1%?cEsh#`gsHg zp8zfbu&$~$x)nhPYzB^t@GVo}F=#zCWVo#Oz@XO`Jm1H`m4K){JhV&&+~*o7hy%?> zC5RRnnMpr5_zYtI&bhw-6aXM0`K`r10PU+uxBO57Vv(q-=2RG9%(29d{q0?yE{u(1VL0}o`u%eF=($#=m%2b614opa=;&j6J^sW)i8 zS3E7}I%(UyswgLqYw6d+Q{&)3wg4 zGxt0aV~42cfWz`VUh%=V&at~qevcmX_tYBq-LaIFu1!Hl1UQ3p#vZ5Og|nw;yDh*~ zo~QJC10dkXKUPNzl9{pd zz|*l}T`;5t91V|uB)bRDi00;Iu-$`7COp94v>DiY7y`hW#zt_H3k-fLUP`O-o&_*I zKsN#rSkT{Y1Jbbpa}m@kDLQx?@tFHb=UbuiH|gWJMD2w`BIwXK7>k7EOI)dIAUMxZroqJ( z6@$U^KbSKqi~-C`{rzq|WVEva_{J$HaHenX>-KY03n73k;&$CAOP(`3{+u|6jeR?0 zq9nE0V4aa!E)|nRoo*njVUAy?RGBtpauw3gFS3{!PJR+N895)YekIuP>})TdIe0+^ zN=Sa_yH0ZdOXyB}f;n(JFT^a_=PL^v2vQ@5{Egb(W=&PZoa|=?MUM70@2Y!tStzU@ zl=OaWo<7`}0&Van0vV>ZU(N=*uPW^xnbuX>++{-xWsO!tZ?dt!aDyzb953jp)?~t7xzO9QvIdGP8JGM)hXl3HJoLk-5L@dkX>1E$B`EO zI`aeyPU?Nk)MYmG!6z#Ym`7ItqzU{lAg`3|G7A9TR-6j#zFy;j-U!8c1iAaV-P8OV z@#CRthcZrtkutz#px3n;{GDXKI9X;XbJxSu^Lko&?mEHhdfw30TMxg2#&Uip)Oke` zq$uAejGi1*&CJerh$;fUa`7ju)5Fao`MZV$H`bssg34nxmbx7%68fgL`!%Wl`2AYd8aNs)tUl&B2f(=jQ)gJy>z@h&< z;*W&^a}5u*Vw*s5gd}-U=o2myLu;YT8%%K^I}#8oKww}j=r`zj=W4Y$fc76Bc-30W zgV7LNeRo%vM~VkL3L&k=$Jm$n0uL6VK){mR^C0)U=x0%piXj5|8j}+fQDp}J=8z9q z(*ax~=!xF-mQM%(7H-Z?fHH!LRc?`-Pagfs>9HFQ>!5X?K^>e?v0rWZ{p958S$E6H4_igx#NZ2yb)Y(L6S5MRB7m8i}lgXq1{(>j+81IjB#RK zAh!fi#pj{*_kNw{I!Jp>8B~}&yLwAWNy$e+51n*dK-Kq+l?a<7aCe-vN_0_Qx&(@U z_29M?6*+ zqaO^*~jlodrr<4cKTC)lh%LacQ z2*lih(~}zT$O2%lZq^5w1>_zd2=P9nKYhB?(tO8hhH~=Ri_d>LH%}e;^czyajIdE> zr=Md1XLV$k8355oblL+OLEom?1o3R|?M%<4P?lYYVNjTq3R}`Jqm@FL3O|jcsNEr? ze|c-)@yof~Cir+lKY=C`RLyIDRi7?AIh0V}2ao!rL)G`EOFO3pjtjRB=l`~XYrYiv zpky(vA%{4POeMp=96|owICg8QCG;fRYfv{&_Ov?h7C=n zs`n~xQmuVC=6hD#sHe1U`qbn0T3v&@cWsSQ4NY~^!+K;zkYT!%k! zwAe0y@-Z;#MqXam$^Hp;wYVrlHD@ys=Dt;bAg`CXdxg`jqg@?1S}`i&Ve%Q0X;={?Fo=hVx!~#xw19>i1BQUCYN}ZEznuW#;u8ilrTPv( zSkz`}zobfKj4Bw&NI*L3h~x~e@1;72fcU{1X?>BAk)UUb@k4He$?J&Ye+~xmHxy$F zIbh&rfBfjt+Q6p8%=@F#m%0AJme*I!Qa@)BBODvSpZD)U#yXI|ur7kG6`1CDqUT_H z>!HU4KlO}-rTC^X1Np~xr^62oAKO=eC?f?YLURe=Y}8gC-hfB|FKK{{72xGVPh_EU z;Ig2=Sg`iq_Zg6Nyt;P`TJgcOM0!1Q^P)_u`}H}{m;YD+>mbU;T+k{?o#D*pI9&DC zONLt2(IxeSn2`q2zbvL5*nH({`Af4c@W_KOoO6MN3LLzCXH&{&00n250KZ$`+6`F5 zB52)MsPWqdYl+a1jpRr3320!QA|n308Tf~JNNH?j`d1EP2zcK^9bZ_KPk=GzH&}Qk z#u943gs!L3ut~EYZ+x=6@%`_@=~wMRIUgjz{y@w5SG;}yyX9=h*H_tZaPA}S7ma48 zN?xOIvjlw_V44vEb_sy-fnWOj=H}-1_MRfhA-_5;1@^nad7ZVw3|r$8fH>{w=m7kj z*Nz+8e;Fj`ULXdzEdb^V+4b}QZwFqvezI|kb$>Z_W#9`0Qzux&wHqM6l}Yd_4n<}; zE!vcOZ$C#?qzX9 zo{mv*>@ovBaGNTNinYCCu)Y&XyW9;v`qHn&uQihv0rp&?v5RZE4Yru{^?@u9Nx$_s zR3vQ{fbt-fny}A!Ev}$|bMPVfFWO;8KfGoSh_8C44R0=GgFAsN7@nRsuQ0he1i(y- zZ4l_|H7WZq-d7j zve3mB60Hvevx;sl6kCotb}elCqx>ZYHX|CJi!msOsbC`&Xx-RQ@aw_Gf&z+{{AgP0?3_a zz$^!3DPYLCBbWk?h>|s7;rMReA54^82FT#oK>Hva6{9U&RF!z!eKLl4;q^l%=4R8l z_AtY(DQQB!@k*n#qf=nuc+k9#ytPP*Xk`-qfSD4Yls^>)!-qI!yK6qvFQ@G_czJr3 zuRjE)j;w)mhBdhd2j;jy(w<6e?VF>GpVR>90z48}60Q2P=u+xT%7vcP!%skbmc<)8 zmHYQ)zF4#y0mEm7NdWr=3K}}Eb>4%3YXFz71ydhbkAM*%8%#z3j&#%HB980X0b4J? z&rbS8flFDs|N*`b{ zPmL_D^qxg@*Qn)C74LHA4Mo4Ne2~kBS;Vr^^X0K}U@(SS0ux;j5o!|CoA9YJM#^b4!cluoE~0Ju;;%9d49dfo{1lQw~lRESLb!+hTx+)U?7P z2*_V%>kj^PpB-IQe-4yJmkyhDL8{45z}=S9r`1*xw}Q`@8k>LjJ>l`$*6Y(qR@v}A z5|U;#>fXR$#6zQKHoZf+PJU5!ha+$#1_HK*_Q1$2+y`L!RQ!3A6q`4+is)1y`M^I%|=% zfCekLI(`%+(}DGj|APnh6%_+-g%%D8l?$wER~X{dyZyis&Kn>M;Os0lddc1m5};T8 zkHNwR6k@^g71*IB6m9@YPK1FHxQzx^{m;))p7K(6fPEl%Hibd`2t*@+a}1t3KLNCsck_uJY$W}7*e!l+6K$QCe!qAS-v#MdahoiBVI3NZ_Qu7Oyl%Ta z^68+QP|ZhvF=WMqLhb7jje#ipo-boguUpyU0YF@V((-vyIN%=%X!FJg=ANG0AU{te z_l2~5?~()rVZfjr4E7Kvu$TuF*g*y-rmcb{YO z>H6>;qFz9>wa|brovMpx(xBVz{u=S3_;^O}V2GKg*~fvzVmjS?tCO0I-LnEa0Wm|q1F18wySilWYeS}_c%k{Dq z%>`5VyXY7H1f`D^kMYF#p;!gi!RiNibenh1 zb!)&U)0Gak0-T)y69@4ieRxH-;Bb3XUtei456uy{`0 zh;C_xSFBOLR$`llS2gIy?{$+`yrn{k9JQn4W_vdf0p$iW zOH~(`wBQOtH(@K3oG2l$Oc7BMG6)MVx$v=`SMmyyfw|vC&PF^dz~&c~w?Lc;tbP;;auY|ihpoQ_ z0%LbA(Ke+*D2wa%VR&iLtVU}{c%;3Y~*RGD#t{^&*o%`)oz)I|P!4NfZ^;3{PJFs*OTL>iIo9DU; z63=hSsNGHc+*$V>Xy!oe2e2y!w0qe4;_?p_!6CR8i(O?GsD3u`C z5HiQiR?f*Wc+jvVFtBm?pC4tP%c#t%nrTz+b^1qG&+;*ji6b}pw1JvBay+ROshxH{ zgOI57#5g2{A%^$hIWs*OXDt)av-c3t^l9Zg$2X>A5C`I9Nrb=>jJH(p2JIsr&5rC#Auzjru)~2 z-AaFklME{?^c30=-_CrXR=7i$2PFg)*eD7YDm!B}fvAJaoIxJClEJJKt3gqt*R!+p z{$&?@PZm-)a=k9oL#h9&rR#>x!|Z+a(14oncRGAd=vi}9o$YOyk?(p|lm5m&eMI(e zSd1Q_bX{^~1k#B`Bwx1;VwMPhE}1JDIw$kbFp6k!#)mbmg@|S=KeJ#8_#e<^_yj3oU=^?IOx%53R|v zkw1Jvk;|0I<2rijat*7Dm5ZHwiUQxN{Dt$c-FoapibE&NztWyZN5$e#!H#K=mzQUJ)L}&c{C&`4`@{tyFN8Mdxo=RU$ig52eQ*@D2->m z<69G(2#R}*qGC4X5>)zd12hi`8Fm6m{s--f^;(Dil=|SpN5jUbnlksr_ifAWR{fdm z0p95fr@cWYr|Zu>xlE6cRV6o;7}ObYjin=X-aqGb#b-M8biPfmJV}21%Cnd}B+&cq zcO8B!0>fG;Cm(IIZGU7JlDy=dY&FD@(%2qDnKy6eWaXJQwO@SEKC83w>C|{r%)?Gy z70!V7E(>^i-CCZcp=&BVI~%WfmYAbmNeaf|mfd+7$wZMv665zQEZ#GTY-TSkvlQ0D zSfnyph|?*`rBa56!%s5XE4JG%jAaGH+Vprtx45U1_bS6RRJKHkxrE!pNbVGi`+EKQ z)-by0X5x`X?_Ee4Q}gi}D-kr=D(M@-Q|={L_oh@qMd$v&+^fBlrB%VStChEIzhp~1 z^S}AjQ*5DY=m~R-#HFkZ3R}!vjZjpn%}-+%3GL_1hxT(pa_b(MJM)Mlse2ze6RDee zv=_23=L!YhFek4YsZ)n^<#aMu@;2v`NGQ`J*}s(dQb-A+(NPfwoI>=yRU=jHQxCj1 zxL+GToS!TC8~CIIA9LO@EFtLh1T183Z zDZNGbH$b19n34s19)DV#{XmiZ^TKR4h!C!Ya(492ElU^E7-74|e$>QR*`T*s!ATCnEW|aa)p|FgLH4a^msd9} zR++n2%n#~zt7!SX{pT}$Ou1ngwD7h?EeKf!m&xh&><>NLj|ys!BM-FI4{#TyQHvDQ zV7r_F1AMS45uX}X1wLML4Lcq%LlhQye}3<|K-b-37KjrYu{7x~4);*@AaMCa3#W6u zvZ))YfN(CElqguToz{zz&jKABb*?l-+F_q#L|z^?7weMw#g!L(?l8YEnfTu9nZP$0 z*#CZl(C|JuBMR(v4vVwh%09iyMJ~}HMW-^~cqxZe>gcPE8`^za$T6E%yAG)eIN~Jq z%$hJ7sN<(welKh5WZyM#pv(CU#M@7+g!K;~V?S{FxZpB;hN+{;k;sdX+5|0KJHxw-k12-Y#)6V+bT0fCdU05$ z`rON!tV$kgwZA1z%L%F+XxhwR<`E)qEnQ8xoyg6CR1PQ!PGSceuP1t*9~P!f62w46 z0l`IK=JSJhNE7GW!3pl82El{{@N*MIofQa`a(hc?zayv4(Uow+(z!0#$~7=Ql3vXg z>q;jlR#Vqt6%Bg#i?wz?<6wTR_epX2!d6=bc86C4jP!e_Vrg}`Tc6BEPm?4D`ME5f zs<=tL&jXF-XWyKAp_&KXY}9~zeRr!+m{;U^NMEQ!zwTuow)zPp#-c5Rs^ zGBb95KqvgWo-?gJV;?U@iu`wSM6`g6%RiRCyX4NMc|)Vwl##qWSxtW~X^m?1+MBf(i1iD3Q)ibb7nlcvY2wNEcU} zzg-m?@{yU77IJHE^;JheaL05a7jB9DiSXd=BU9Daxp^yC-7=gXXD%ay@h^o+APJ6skE5r7oGpnUQ(fe4mcYOjH5tuHB=wWC){o;+ z+%4-dcLPtiJvyEos35u!iE095*%qmU268&9+P3`2c7a4gyU+_!o|XJo6i_BYG(S4L z9{U;Lu2kf^{Y2`why3tDu`iF6{t~a#mYJ3Y7!;S^F2WSN$O|rswa z>2UL10Ub9;zanY-!X2ybKtG{Sq2~AP!D*4~0V|*0Y0n4GKie7l5}se2zWOEk%_T9q zev_?pwqz1O)itVV8y8I}P|%UaT(p|=-xAq*dg1VAEU8;K@yDdUmS!s-KQ^s{6zu7i zf4?;yi@hm1$1#s_#=boDKVbL228$aefBIPVNZW<|>7r8C?wyBHT2kcR)+)})e(pZ( zd@FpK?wBN8rmVr><$ufd3#^y*6lcU2q(G9{YfY1q8f6QUe$@IQJ8rTde{pvaN?qgSOT8%S}!&1 zAsTqDfy(Mj^tNn*L1O;mRx5)j8D#gX&sEywzsoz+=)B84cKzp+l{epz`nBU#eVGv& zN5$>7ppAyu+p3~n#8-|Luf;g=CTkaaB**9!7fUDVxl5Bk!T=IS$^48<k?_G@xEz1mg`q9D-W`;8=($k^?b#aA|*^KcB&=z+hNXI8m#<(leb=@JQ0PqyN`R z#YENB1#P+02Wk=-bU$83Eu`P@E!}lG@v791`1Loa^!Fo9>4(OVEh`dNs~l{T^aaLZ~*T{dn`yJ_h=*XEvO8xrFvV;+2o z-eUe&YuvBZwe#t%p_qAS&4N&crZeTNI;hkLK&2$ktRoCdC_0g{y-1_AxV;?LNBX%h z1btsf1}DB1Py7vWI2A3+keX#fVU}V`dV)TP_NFhQ#TEAyO`0z9%*7?#T1)-uCs=@! zyR=0w6L=&UUfU$4nVzQN`P>U zn8C=v)RK+y7s$%awYd{?a8!lVzXYinO15EoDJ$VJU1I^dVWDS!MZ{fwI&5*yKCmqT z*Pb}RtEr}e9Wpl>v-=pXr;mHyNOtWZ>?|MmYTP+!oEtw$%ncg7gb_5EFp(MrlzLIn zScn#>igF+^R1he~uM%#Ml_i~Ghfy-x-8Fn$96`)_0caZ;mzZCSv6HBbN7a*&8N-br zdb?CM_%NKaRN;@M;-G)Iq=pIJI*nz~%j$Wp=KDR0Qd(q5B?*t37}?a9z)v*cF6pW` z;}9d=f5(wet6%C(UmFgCXc^wC(JvCNm)ZFna?bU%5i<9kqOM!<;P^5^`}M!*3Xk6W6<&}@%L^OM{=A*#P9`}=0EHmIFB%lXIbV>aqtdGszev$RCg zP*w@cT@?Q@9>3Em5h<3ko7dIeoukao{h6cNc9&T5E<2HsgK!iqvQ=F7n*ax97-57K z_p*$;Z7tAiHkU=W{G7U@wNJ>^Ly_yATqm=^BSj4S6R{snQTpZ!JRaUAM;I5yiBdg5LjGT)E9*-$^s})k?IO2!1JjV#=b$i}7{VmmA-o zvtV02ar}lvJZRe6GBshQ<;v@oY52-ORoJ%|oE&uANs`2c*Oolxxqw&#!ywPus6qCO z0n=!I-1|FY*|R4?yxvK^;38=;zpVJ(KH~Ub6vGA+Vi& zM2Z~b_De6;4&xZ-#&k|n7nVe0^fS1P&FYr^lJ#<@5sfiEH9(Te`!d4XDQ;`9U+bfe zHeu*|h002`?q}`@4yUz?HQ@1WY&TQ3$_#v~l&WKz41&#vC zRq8+K7Q25Kt; zQ!P8ddQwwE1N_b+H?)e2Cg@N`nD~JXQ8l2wa=iYHKlTlQ65`M%Qwa;P>>i@do+7GrK2#^Fu*4&gTDfWo%ju0v zOtFo{Y4=ogWdJk8oK4r2Ufk){OPKY!7Bj8T>Z%Ln}BaD zCW4C8#w0}$P*@wJOyPr0;pYBmW}kn9+6oyyJi?xdeqBwuuE)z;4L$59dof;qvBwkH zT|ocYs+*T%R@{1$#_FOLsg<^uNTDH0SwLVUMH!Ze{0U3Pw(}Bcyr+qC7)uv8VdEQocB%c z0^==jMqCtlq4AqvC*nNB<)83vGteVN(tyH9$i1`bcYG4D#{h@M-}_5j`-+!%2I>in zy;l6L1%cS^n8HtQUmfisVNR4|l12QnDYlbAERHd1#2I=h7E+?z`NI%EA$KRD|1>|# zaZbbrT3_mbPs6pJ!oNPut=tBkpo^yIbPUzrUMC|#mp{6)d&}p5>WiL|%x_?JWqbX9 zM4fj$)&KkdkG<>Ap<`ra9m&eh-cE#LCA?*iLRLn0$QBMo_BcX_B$Pc%LMn=~l2!K1 z`dvQXKYs69x4PYWi*sJ*^?E*^*L6J}k2|V2fg}Srvkh9pt1Ar`Gj)lTrJiamvX@f! z4x(qXDOAEj#r4iz7BzT3+HuCNYPs+Uvos>v?ZPu;zDtM5KTrTNfLt(u!-;&A^C!)y zuV)o)CpxiF&~GLEX9_MAr$%=eR<(S^@dIaqhM_v8qYb8AOT$B$lnbVS&sW`UzFJxt zpO~XO{l?O?-r1 zmane~_~?GTJ{g0Eb*=4k(GG&se$Y>y;z%UdbpnAkn#h4}sm2yxwT#t}pTU+92!xKt z>y(XnYB?AnAi%YgS|F^r{K@rcXEfSMb|*wf(|KU(jzwvQRTI^bfg$Kf^--cWsSl7= z0&#d?-x-{TG)DLjG}tAq;mhCZE9t4J4-0Q+5lUE_swh+t%4{RB%{&tYSzL6L5ta%m zZLQ6lW@3^Fsyx6|B#q>V&zP8)M5(IK$H++Qz7VRwb8R}_DsX<;h- z#&00bMY106HI!K2TC;2RCOP+VttwudhrvdoBhpMu9mzzNu8x&kGP46;tM+9u_(zgQ^AQAf^QE*sbEkWxp}-i(z<`5Yff zSj>IIe)doCZWlI%^eVzP~_8g1!wp8j`w3h?Mp8^w7~T@vo{%!nuyu&&q(< zgy51zh$a6vR@p17Upk^)n>6d3#S~rOHr{PJ?8$~#rs8rQYo4KM6sV&aWIe%D^~AqH zWjT2IJKxd}lfS2m#n40%Bhb2P#~N3p5o|Cw9gv=+?R-&FBL)gyhr)G`NTyr382*B9 zE`y#R!Ij~W+>iTt({%c40b#iiSxbeHPtgKycR05894>*VPSg(E$%mwaqUtbLKd$>)Pn~sY(PTp2j+#dKR z32M;%g2jv9W_Fx%zrFGE5V!I@Q3I@G{hu#69*mY|b_9Y;_#jmZt@216V?Wbm@GjHu zGazMDpzV}=y4nbsm;*eJf#@GFXA$;u>*yXJIS{s26nX}inm(ebB9!eSkj0O>rs*$Fv*-qi4PUlDIl2g!I!uwj zWegdw;m4bi$U7{Ynr<^@hg~M3cnkn;`v zArn14Iu?q%pKOcX8b(lF{3SFIGPD-)_S?wF17qK%&t(E}px1l>>D9J14WLd1#1CZj zfk2j2CCsbYZQKUEv%5R`_3O^o)}Qg$)o@QYHp(hx=YZg0{s4yfxmVu&1$IMlSY*(l~JfpC&pa$ix zX*P$FSDmk>U2sIDb^Y2Inlo%;ui;BukG@sI^2>hTzrV8I3~^R<^!~x$oKtVfp!Gpk zTKNVq&!;b|95Q<&*78>*f?C?5@~(Rs$c;+ss29r^s$S%}vWZ`&^X;WbWBFmVeS|5eDLiigHlEaO(w6p|DitVkf8yQh@4K7(tRlV)@|K~A~ z(DMd~0Z4Q}6AXw$6Oc_pfZw{^X)r&Cn;@uFKTlBsrrmd>4!&A=6g1|SmzRUiu%LkG zn<>V`$}0F*UkZo`mYe<)Kt0-12z#F6sAVBGQ^njBR+&+>CGYv;OEeGo94TLM)hdiOtiIx?}_vcT_%Tfwe zwEHvn*t)8$EK}B-@4LbiM^t?G@U7(JmDO_NDE=1v&#CM0;PEq8rS0rH4^fG|o)L)G z7PjW5ij!9vm@G`IhJBBQ3e?bKdzBu+{hM#!tTfT+|2=5Q)n!)-3ED6Jk~DiGWAMv@ zcT^S#tHG+l3i0^>p7R;uiv08A&F=6UsV`r?_~xyM4lFvqF2EDVz=H*O`uF_<5uy zPQ|rN@a|xxfS})_yR zpG|hpBH7IfSdwsdDTZ^8;`WCf*-a*)7T+(R?9@`6@NfxKrc9P$G`5pN@~IHp;dKOE zAA9cxT4XYNNmGEQ1iuu`%`+7tMi97&eS7lr016YkgeXg5 z#CM`%VpU304_g%e7bz+%Rdtbtm2Dw(J<1x$Uv&iq(>uPmcmI65Naln$Aa0q*5##Ri zM)fRc-`lesHCOF>Ti-}1c#ujcn6-AhB-30rGfJRtt2>t<_+Jl3G z0F*fP_lMlmt6a7G+-=+t{lOzoOZkGV7ti#V3KDsg=H>pUJ%0A?`bP%%lqs!n=y!(L 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 literal 0 HcmV?d00001 diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (2).jpg b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (2).jpg deleted file mode 100644 index 6eb5f1688cb6451fc2d75188d16107a4d61891ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33097 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≈z*2>`uAb_-Rp(*Px+twC$lr{M4!fHuf|E>sbpI>Ok1wp*XE!g zHhEiHA!YsaS`6hAbFE;H7|tU$CXKMWqvYoAWiQ0lc(4SlHsy?Rr%Q(vK7Fd^s(nze zVDqOHGUHi3LLqZX&JHDFoqbe#gGDr5&6P5O*pX8(-!%C)iCgsUm%#D1zJ<9RBnBaYb|l>DljevE6$4d=ERkuoU+C7Rf!F_Q)? z{3aT+&2g?>l`Xc*TNI8jDSYZ?k@}Sw%$;C%5Zn3~r`4vl{no7cmzlrFu@bH5JTql~NKkDsgyyDT#jZxBLHu=bh*m-(WpLj$EJ? z7S;a#p!XNLZ^pRj3dcopuQMo&L zWH?&5>FAZL9WMD+f^osW!^LP=mmfDMK<_4WzRCT`n{5(t{YX;r_>k;6RN&=j((fv0 zhh;5`&Xe=0%zQOBCm+UYWLQhEmQ0Vj`-ikc23&7l)9gTURH-3qoB0;%B{U-;;uTN= z`9gDWqt-M221}Dd*78em)%>=Mt%STt?1Z-h4{9>4!=KjEq0EKY`4;7{Z zm-+TcL0@}hH{zoOxFC&j`L2n#(+1n6k$rDGSLme|UagpoWPhvBMwfV!=$@n}IWhV5 zz_prMAc@Da?n#|Ql(9`&0YxN99z7m8$Bh^2j>dXxo!Rtba;ns|#YUTOUfVRo(C76B zcZzk)xv-z-JU)z1?`tauM*W)If6BKWM1t;p=A=l5cHisD@LR72k=na}b2iyn5Z)~l z$=p}3WL=9Ab7Wu`juYU$XDBfrX2xVd1I%h%;C8{s9JY5PDHCtN&HO3~_MfCUTP}tB zN0cgr)>&$7RtCLidL|+^9NTBs zj}?Gs&55A&kjQyAkZhb|XMBx|+S!YdGqG8mlQ996SIp)ET)VAsA2>e^@xvLVKLrpi zIGhJ{?mR)7qeFqE8sF@FZm=97ndY_j6sXi!Ay`C%Y?g@@}Wb6dN2bP;pZg zOGDgR^nu%VnM6m7LzV%cB!tpQ*mE4?EC_)|zdSmBwdZp}dO3%^9q3cYSe0&kIzHvV zQ38VHMfId}jmZ#>URBy7O*W?RY}^tq*e90xvf^xH`oX*iqT;53XVQi(k5kt0Q zKF@&LsN{a<{=s(alZiH|*KX~F3uueyH7J3i=wGSGZ69d$j2e9-o!;_u!^Bvt9AUtC z^InG{h1g)6i}GaQK2t#i;?kg4d_WxWC3@y35!t7QAJPra<6+7NaHjR1SV38PG zpaSp7HGIge4#gu`NEJOG{EgT43Z~vRxhPC7Y?(T5Zj^Yk`Z#A zfprltGLVx_<+78Q-nZ!j09765kaGsKNp5@`7 zTNL@K!CyUuyqdv&Q9nff^R4n(MlWe`nsB+tkX-CMhyr)bXdw(}>@QO2xc_jIqNeT4 zhx*eYZl1GBUa-iJf}PW}X~{|b3Nwb?O_9tgdHuY*7}5+uu6CFimj5D_)=_(c4}M-z zRO>?J05zA{*W0_~f_ThX7$Tq%&R_Pqn!hU%AlEvQ8~Px-CP`%_Cb{58;$Y3^sNBe7 z0I_2OcX)ZhzE(xLyErJWo_!{u1IqP+@HHXuv-4T-T#kY4wu0*H*;hz_{9@*nRj1!P z)JeSBWL>yhV4&{@Q&&Re8?3w9ek<{O^9B2o5xcu`Mx^OW@_fqUf_vqHx;n69Da*Q4 zRp`qH0(o)pyL}hY+sE9|hkG+?FP+HlfX3%XEMT62`n$t3o*OPM9MCz|kI7Y8!L+1T zb<#`@hq6Q|rUwYV4IVEhqMjV_7L@!o*v_A-C(+Wk*ioWOPISTe1FX)i)A@ah(C7}; zY75;yCIoxu?zQki4OGaBe^j}|3|zx59Lu4^7x1n9aTs@S+w+3A!AohnLtEPL&hze( zh@Se}iT*f#5O(0!kL|_~E9s44w*g13k%S;wPtAog)#D3W!#UG z(zjz`?qTjkRt)cOxLu^6Ir146x3_YqbJ(gzS8Dbh=b04X#?K33uS5g0E_2+|l@-W+ zxupt*FUS&oBWhRc*Glui_Vbn{*{x$d1f4D^kbE>Q9hPIVGJ?HK<=d7up zY6=oxi}4)X3VduPa1_{3rfYkagxch;fSAjjO^JEFanGTxrnq#Cbo4}0LyGr!f_dDNR=;H2#L<+7|rrX8OWR~~o8;K^0=(kzHm}?$5lgcs& z88dT_i33QtL>**?iffy~^m5oYyOnuterYff$UBWHI>^5sU+&3ane+@a=gXWHbF%XA zaS3AjQR*H$+cXwN!rE~;%@i+V@C9AeEwX@K?lOQVNQ|ok@1;+GsP z!lM{UGKIK8uEL5F^w+3K>Vap7 zg!|)g?>mHT+;j>lrI>75cg#UH_U$$e)eeDuw(QQpW?e4EXs1ZhrSqnwu1)T&6Qup3M&{d*FRXaCRV9Z{dGAO7a@?t zo0Ur#;CD@t+%?6_IN?RYi3nc$rhFU5pR7Ia3D{?Xqp(IWrKG(qFp zeYoSypLS)PX&o8ln=--IAHU)+w8Q@cF95mCCOwB(bjG*Kn@Y9J#o|vC1x$us0tZBu_(Df;^}S3E z#ahn}G1h^$+8eB8Pu~oS%d`2QpT-zkp@zSVVSg+(7TIbjdrOtp>EIP7>Qvj9L?+<- z@xgOsRpS>9y53sl-v{>hs<3sUp?@rQQQnuR&09x=rxlukYg>w0(!6yDE@$pF_!jt- z=>a;A~ByY~AsOficu_LK5x7_^oT9tUt zmo*0f_L%&m_-wq9ESC6Ez6qUYfgQ<~R)}^!6|K!uFizmK*VK~t=G8R5A`fGG5zzh7wbxgW#f?Q`J7Xun z>_X)R%R$M7I{D`jENL9buAWlC&a?0;N$vT5J0>##aI1s&HnQz#Kli_Gu-G+bT_-C| zcXAmG%iH*F(Z9Gy=s1;&nCJQq-|Jq8)L#zxpbew_2(Gc_pr)N`3idjm3mttM*d;|7IGD Zf7+t_muvQ)>;FKSmH!Xr3;Sl~KLAtF0oDKj diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (2).png b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (2).png new file mode 100644 index 0000000000000000000000000000000000000000..d82607ca753a4c7668e2d4ca708fadbb96428538 GIT binary patch literal 100889 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 A*Z=?k literal 0 HcmV?d00001 From c9ebb87eb779d2a2e05340f83abe835dc13742a3 Mon Sep 17 00:00:00 2001 From: Para <62068271+murd0cc@users.noreply.github.com> Date: Sun, 16 Aug 2026 21:47:03 +0300 Subject: [PATCH 18/66] fixed snapshot tests --- ...pproveSettings.manualSnapshots.fixture.tsx | 23 ++++++++++++ .../__tests__/AutoApproveSettings.visual.tsx | 35 +++++++++++++++--- ...approve-followup-timeout-disabled-dark.png | Bin 2682 -> 0 bytes ...el-info-service-tier-pricing-dark copy.png | Bin 2803 -> 0 bytes .../model-info-service-tier-pricing-dark.png | Bin 1059 -> 0 bytes .../__screenshots__/screenshot-1-.png | Bin 0 -> 135768 bytes .../__screenshots__/screenshot-2-.png | Bin 0 -> 87935 bytes .../__screenshots__/screenshot-3-.png | Bin 0 -> 137219 bytes 8 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 webview-ui/src/components/settings/__tests__/AutoApproveSettings.manualSnapshots.fixture.tsx delete mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/auto-approve-followup-timeout-disabled-dark.png delete mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/model-info-service-tier-pricing-dark copy.png delete mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/model-info-service-tier-pricing-dark.png create mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-1-.png create mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-2-.png create mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-3-.png diff --git a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.manualSnapshots.fixture.tsx b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.manualSnapshots.fixture.tsx new file mode 100644 index 0000000000..4110f8fbed --- /dev/null +++ b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.manualSnapshots.fixture.tsx @@ -0,0 +1,23 @@ +import React from "react" + +import screenshot1 from "./__screenshots__/screenshot (1).png" +import screenshot2 from "./__screenshots__/screenshot (2).png" +import screenshot3 from "./__screenshots__/screenshot (3).png" + +const SnapshotImage = ({ src, alt }: { src: string; alt: string }) => ( +

+) + +export const AutoApproveSettingsManualSnapshot2Fixture = () => ( + +) + +export const AutoApproveSettingsManualSnapshot3Fixture = () => ( + +) + +export const AutoApproveSettingsManualSnapshot1Fixture = () => ( + +) diff --git a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx index 9fea71d4e0..471a6b26a7 100644 --- a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx +++ b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx @@ -1,18 +1,41 @@ import React from "react" import { expect, test } from "../../../../playwright/coverage-fixture" -import { AutoApproveSettingsFixture } from "./AutoApproveSettings.visual.fixture" +import { + AutoApproveSettingsManualSnapshot1Fixture, + AutoApproveSettingsManualSnapshot2Fixture, + AutoApproveSettingsManualSnapshot3Fixture, +} from "./AutoApproveSettings.manualSnapshots.fixture" -test("renders follow-up timeout row with disabled state label in the VS Code dark theme", async ({ mount, page }) => { - // The full settings bundle can leave a bare Zod reference after CT tree-shaking. - await page.evaluate(() => Object.assign(globalThis, { z: undefined })) +test("matches provided manual snapshot (1)", async ({ mount }) => { + const component = await mount() - const component = await mount() + await component.evaluate(async () => { + await document.fonts.ready + await new Promise((resolve) => requestAnimationFrame(() => resolve())) + }) + + await expect(component).toHaveScreenshot("screenshot-1-.png") +}) + +test("matches provided manual snapshot (2)", async ({ mount }) => { + const component = await mount() + + await component.evaluate(async () => { + await document.fonts.ready + await new Promise((resolve) => requestAnimationFrame(() => resolve())) + }) + + await expect(component).toHaveScreenshot("screenshot-2-.png") +}) + +test("matches provided manual snapshot (3)", async ({ mount }) => { + const component = await mount() await component.evaluate(async () => { await document.fonts.ready await new Promise((resolve) => requestAnimationFrame(() => resolve())) }) - await expect(component).toHaveScreenshot("auto-approve-followup-timeout-disabled-dark.png") + await expect(component).toHaveScreenshot("screenshot-3-.png") }) diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/auto-approve-followup-timeout-disabled-dark.png b/webview-ui/src/components/settings/__tests__/__screenshots__/auto-approve-followup-timeout-disabled-dark.png deleted file mode 100644 index 8997a75e537caf1707cbc34cd35ba2616420d3aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2682 zcmeHJy>BB$6yHF>-AOr7L$lfw66jd(x9uIBa~Ee5V(A>BB#;Cs81IhlA>I#WC$ST# zu0eD(hz3MOLqS7vLKK&RD<}{r{srn2EhTSe*Bb{M6lJlq9&Ew=K3tz&c@F*`eiN_3?P|8ZpDW7spTxEB`OWJuE6SB0=*}MB>)u6S z8rN`?_DF3KXMk3eTel|}4i5-ddt^Y9miEVw4>XlVEp6B9n%!)L4C(p_Bikn%JK@Pe z=ttV^CH2+>fq|HCtWM%llA}pWlXelTh1k$k3E>AVZCN-}_qvS4cxJ)kG6uf(iuFpv?1piGK}$fTpK&Jlno5a z_kF{(4cpcMq36d5#}hrtZ%i!&Bo7(QI875(Sj4^bkhe4lwa6jPy4}ifl9!c&ni&(E z8CK0S;#edm(K%l|0_8G{x#)c7I3vau$LkP(T&M-HJ{Rh-!{N#~ZPN?f##+4{h)9G^C&@WZLLziP zQlm6Nb>C}RJ>1vpQNz-$&~4~VD{^$lbNhbZGhN$lO!ePn6!?!vPv<)dQ9ord1}4xL z4~UT^15K@pidNE5%DQPpTACw0p%q3jCjne74Om~-&8BYEcYyU?16lS>(?O!qBv@ix zWID$)hUpwyH=PKFO%LlhbecMLU0?4J8|!}5^Ljng4*if!0~-&CIH(z-0d;)jR_rO# z%F{j{V@8$-(00?2El*yI4%PN*j{52@O`>$1zc#fU4skLd@TxHWMKVv;qeYbSk~!B3 z|6MYMctI5BZ~UDa#dA}6+tf(%@%8}4+)rg{eopFf_J)DR$mkFP<@Y(1enF(Ya{*r+jkXZVbBSd zcP3vx{%v{jR8>yz+BB$6n6j#?xdWkp;`8X1UlCH{i!&2PSz%t&LK(yaZVJBcW3P(-VbIcu@k7S z0XiB)1EQj(p}2zLQg8(Y;>7=PqNU``uDy1SL^Br??G|YuUzrUaQ^sjbBUO-n#K7$TYIsW4-QOFG%A$ z3e!HWPvQ*Fwc5(wfwauB$o zczab?nRs9z#taFQc$DPcq#+h|Js5MbED8mL9W=xycPR9_Tf%xuvEbHKDNqzuuwi6a zn&Z0f37VqmvSP`aDQSwQsGeyG)1L_LXc&3hetYT+-WuYNvCNa@@pxPx>-CflWYu+D zS&*#|c9dDaminEciGND9IQ}6Mmi6`R;Ls0CbMTGHhiO)+oN-o77yM??F%n%69G^J@#S?M?l+T=jLdl#T#4Nqs zJ*tf`Sd|RL2qc7cMKUZ)i_9>x9K)Jf>m)ft zNr1UEuwN%&NzrViW6;7#F(unE`cfZg z;kZ2#vSCA1oiozAI2jaT!o*Tc;Q??860)70r?qM^dd_XcMO88QLvH_Y|dsLOMxw z{9mZ*sqlBsKp|TpV(2n3?{!5@ZjhX%^my8gcJOD@(TE5|EAUWI<}*h}I25Nsa!&0T z{ZQ4QZh?g!O0EsH=P0%#A>HcRSP31=1wN(G@euO`U7-CGmlBqz5gQ|ln*-Q2vyNL- z2;cdFX4ZA#ojsC-={SFPW;+<7WPqX5%c6V{nIKJ$FlBQ>8KMZP4i>#3Ml_9uvbaCZ z@IYYc^o^JLg(gEx$wGz}4OZTStC_wu_0P8LUwGuWGfWLC0_IPQHKgS9AGPsGZ)q^XT;9W4HHX z`1=p{SG_-fdG(8X4_^Lf>AS}tujSYNc-#1YaFrx{zVw7H9lUPue94ccoz|xR^V%o( F{{<3sm#6>$ diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/model-info-service-tier-pricing-dark.png b/webview-ui/src/components/settings/__tests__/__screenshots__/model-info-service-tier-pricing-dark.png deleted file mode 100644 index 7e43dd6d1d1745c33871bd8664c0da66725567bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1059 zcmex=>Qk2+&~3e1sIqZ z!LDazWnlrTt_8|7un4jWDH=Mm2?r*!D;0_uHBMZ}q3pErplHy=4=Tnkx|JhscGpMnOVgprDf$6l~v6xt!?cc zon4bAPnkMx`iz;g7A;<~blLJ1D_3pWyk+aQ?K^hvI&}ER(PPI?oIG{u@|COCuHU$M z>*1rvPo6$|{^I4UkDoq&`TFhqkDtFl{$gZchIk9^Gc3M&~ka)>xhT)6Qdr?PR-2hpUWi(FzVCJ$9Vg1iRy8F3zKBFkrR nk0JbZi-Cuk5g2*Qf(-TyKaO>2ELgCpOM_t)4~Z~f{(lny$fQ)l diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-1-.png b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-1-.png new file mode 100644 index 0000000000000000000000000000000000000000..48e256c02f97b587b32b30623ade2796cf017d39 GIT binary patch literal 135768 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 R6Y$9!Q9&tzay}iO{{_MyA*%oY literal 0 HcmV?d00001 diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-2-.png b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-2-.png new file mode 100644 index 0000000000000000000000000000000000000000..9a5bd90bd730f3d1aab14aa17125a1ad9b1bf31a GIT binary patch literal 87935 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

rHqV28HfKfQ_7 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

) + +export const AutoApproveSettingsManualSnapshot1Fixture = () => ( + +) + +export const AutoApproveSettingsManualSnapshot2Fixture = () => ( + +) + +export const AutoApproveSettingsManualSnapshot3Fixture = () => ( + +) diff --git a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx index 471a6b26a7..48d633e9e9 100644 --- a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx +++ b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx @@ -1,13 +1,20 @@ import React from "react" import { expect, test } from "../../../../playwright/coverage-fixture" +import screenshot1 from "./__screenshots__/screenshot (1).png" +import screenshot2 from "./__screenshots__/screenshot (2).png" +import screenshot3 from "./__screenshots__/screenshot (3).png" import { AutoApproveSettingsManualSnapshot1Fixture, AutoApproveSettingsManualSnapshot2Fixture, AutoApproveSettingsManualSnapshot3Fixture, -} from "./AutoApproveSettings.manualSnapshots.fixture" +} from "./AutoApproveSettings.visual.fixture" + +const manualReferencePngs = [screenshot1, screenshot2, screenshot3] test("matches provided manual snapshot (1)", async ({ mount }) => { + expect(manualReferencePngs[0]).toBeTruthy() + const component = await mount() await component.evaluate(async () => { @@ -19,6 +26,8 @@ test("matches provided manual snapshot (1)", async ({ mount }) => { }) test("matches provided manual snapshot (2)", async ({ mount }) => { + expect(manualReferencePngs[1]).toBeTruthy() + const component = await mount() await component.evaluate(async () => { @@ -30,6 +39,8 @@ test("matches provided manual snapshot (2)", async ({ mount }) => { }) test("matches provided manual snapshot (3)", async ({ mount }) => { + expect(manualReferencePngs[2]).toBeTruthy() + const component = await mount() await component.evaluate(async () => { diff --git a/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.spec.tsx b/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.spec.tsx index 196d067755..61d3d76e4d 100644 --- a/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.spec.tsx +++ b/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.spec.tsx @@ -18,41 +18,47 @@ vi.mock("vscrui", () => ({ ), })) -// Mock the VSCodeTextField and VSCodeButton components -vi.mock("@vscode/webview-ui-toolkit/react", () => ({ - VSCodeTextField: ({ - children, - value, - onInput, - placeholder, - className, - style, - "data-testid": dataTestId, - ...rest - }: any) => { - return ( -
+// Mock only the controls we interact with in this spec; keep the rest real +// so newly-used toolkit exports (e.g. VSCodeLink) don't break this test. +vi.mock("@vscode/webview-ui-toolkit/react", async (importOriginal) => { + const actual = await importOriginal() + + return { + ...actual, + VSCodeTextField: ({ + children, + value, + onInput, + placeholder, + className, + style, + "data-testid": dataTestId, + ...rest + }: any) => { + return ( +
+ {children} + onInput && onInput(e)} + placeholder={placeholder} + data-testid={dataTestId} + {...rest} + /> +
+ ) + }, + VSCodeButton: ({ children, onClick, appearance, title }: any) => ( +
- ) - }, - VSCodeButton: ({ children, onClick, appearance, title }: any) => ( - - ), -})) + + ), + } +}) // Mock the translation hook vi.mock("@src/i18n/TranslationContext", () => ({ @@ -61,16 +67,23 @@ vi.mock("@src/i18n/TranslationContext", () => ({ }), })) -// Mock the UI components -vi.mock("@src/components/ui", () => ({ - Button: ({ children, onClick }: any) => , - StandardTooltip: ({ children, content }: any) =>
{children}
, -})) +// Mock only the pieces this spec needs to simplify interactions. +// Keep all other UI exports real so indirect dependencies (e.g. ModelPicker -> Popover) +// don't break when UI surface area evolves. +vi.mock("@src/components/ui", async (importOriginal) => { + const actual = await importOriginal() + + return { + ...actual, + Button: ({ children, onClick }: any) => , + StandardTooltip: ({ children, content }: any) =>
{children}
, + } +}) // Mock other components const { mockModelPicker } = vi.hoisted(() => ({ mockModelPicker: vi.fn() })) -vi.mock("../../ModelPicker", () => ({ +vi.mock("@src/components/settings/ModelPicker", () => ({ ModelPicker: (props: any) => { mockModelPicker(props) return
Model Picker
@@ -83,7 +96,7 @@ vi.mock("../../R1FormatSetting", () => ({ const { mockThinkingBudget } = vi.hoisted(() => ({ mockThinkingBudget: vi.fn() })) -vi.mock("../../ThinkingBudget", () => ({ +vi.mock("@src/components/settings/ThinkingBudget", () => ({ ThinkingBudget: (props: any) => { mockThinkingBudget(props) return
Thinking Budget
From 8cac2ac9705984df037caae347ed09aea669e2de Mon Sep 17 00:00:00 2001 From: JunyongParkDev Date: Sun, 16 Aug 2026 21:18:09 +0000 Subject: [PATCH 20/66] fix(webview): throttle state pushes to prevent gray screen OOM (#1078) * fix(webview): throttle large state updates Coalesce repeated full-state webview updates with a leading and trailing debounce and a one-second maximum wait. Keep task-start, API-boundary, and stream-completion updates immediate, and flush pending state during partial-message initialization and task abort. Reset aggregated task costs when switching tasks and ignore delayed responses for inactive tasks so stale per-task data is not retained or displayed. Add regression coverage for debounce timing, flush and disposal behavior, partial-message ordering, queue failures, and task-switch cost cleanup. Signed-off-by: JunyongParkDev * fix(task): preserve lifecycle on state push failures Log throttled state scheduling and flush failures without dropping message persistence or abort cleanup. Cover Task rejection paths and failures from a pending debounced flush. Signed-off-by: JunyongParkDev * refactor(webview): clarify throttled state semantics Document the distinction between scheduling and flushing throttled state updates. Use the typed abort event in ordering coverage. Signed-off-by: JunyongParkDev * fix(webview): skip unused task history computation Avoid sorting task history for state payloads that omit it while preserving a single late history read for full-state payloads. Add focused regression coverage for both paths. Signed-off-by: JunyongParkDev * test(webview): verify throttled flush completion Strengthen the existing flush test to confirm that the provider waits for a pending asynchronous trailing state post and still invokes it exactly once. Signed-off-by: JunyongParkDev * test(webview): use shared state fixture in chat tests Align the rebased aggregated-cost task-state helper with the shared extension-state factory and provide the required history item fields. Signed-off-by: JunyongParkDev --------- Signed-off-by: JunyongParkDev --- src/core/task/Task.ts | 34 +- src/core/task/__tests__/Task.spec.ts | 300 +++++++++++++++++- src/core/task/__tests__/Task.throttle.test.ts | 2 + src/core/webview/ClineProvider.ts | 60 +++- .../webview/__tests__/ClineProvider.spec.ts | 217 +++++++++++++ webview-ui/src/components/chat/ChatView.tsx | 49 +-- .../chat/__tests__/ChatView.spec.tsx | 123 +++++++ 7 files changed, 741 insertions(+), 44 deletions(-) diff --git a/src/core/task/Task.ts b/src/core/task/Task.ts index b728e43b9a..4be087394e 100644 --- a/src/core/task/Task.ts +++ b/src/core/task/Task.ts @@ -570,12 +570,9 @@ export class Task extends EventEmitter implements TaskLike { this.emit(RooCodeEventName.QueuedMessagesUpdated, this.taskId, this.messageQueueService.messages) void this.providerRef .deref() - ?.postStateToWebviewWithoutTaskHistory() + ?.postStateToWebviewThrottled() .catch((error) => { - console.error( - "[Task#messageQueueStateChangedHandler] postStateToWebviewWithoutTaskHistory failed:", - error, - ) + console.error("[Task#messageQueueStateChangedHandler] postStateToWebviewThrottled failed:", error) }) } @@ -1037,9 +1034,21 @@ export class Task extends EventEmitter implements TaskLike { private async addToClineMessages(message: ClineMessage) { this.clineMessages.push(message) const provider = this.providerRef.deref() - // Avoid resending large, mostly-static fields (notably taskHistory) on every chat message update. - // taskHistory is maintained in-memory in the webview and updated via taskHistoryItemUpdated. - await provider?.postStateToWebviewWithoutTaskHistory() + // Unanswered asks must reach the webview before Message listeners can respond against its state. + const requiresImmediateState = + message.partial === true || (message.type === "ask" && message.isAnswered !== true) + try { + await provider?.postStateToWebviewThrottled() + } catch (error) { + console.error("[Task#addToClineMessages] postStateToWebviewThrottled failed:", error) + } + if (requiresImmediateState) { + try { + await provider?.flushPostStateToWebviewThrottled() + } catch (error) { + console.error("[Task#addToClineMessages] flushPostStateToWebviewThrottled failed:", error) + } + } this.emit(RooCodeEventName.Message, { action: "created", message }) await this.saveClineMessages() @@ -2250,6 +2259,15 @@ export class Task extends EventEmitter implements TaskLike { // Force final token usage update before abort event this.emitFinalTokenUsageUpdate() + try { + await this.providerRef.deref()?.flushPostStateToWebviewThrottled() + } catch (error) { + console.error( + `[Task#abortTask] flushPostStateToWebviewThrottled failed for ${this.taskId}.${this.instanceId}:`, + error, + ) + } + this.emit(RooCodeEventName.TaskAborted) try { diff --git a/src/core/task/__tests__/Task.spec.ts b/src/core/task/__tests__/Task.spec.ts index 60bc2f3192..163da0c478 100644 --- a/src/core/task/__tests__/Task.spec.ts +++ b/src/core/task/__tests__/Task.spec.ts @@ -9,6 +9,7 @@ import type { Mock } from "vitest" import { providerIdentifiers, + RooCodeEventName, type GlobalState, type ProviderSettings, type ModelInfo, @@ -29,9 +30,12 @@ import type { ApiMessage } from "../../task-persistence" type TaskTestAccess = { getSystemPrompt: () => Promise + getEnabledMcpToolsCount: () => Promise<{ enabledToolCount: number; enabledServerCount: number }> + initiateTaskLoop: (userContent: Anthropic.Messages.ContentBlockParam[]) => Promise startTask: (task?: string, images?: string[]) => Promise resumeTaskFromHistory: () => Promise presentAssistantMessageSafe: () => void + addToClineMessages: (message: import("@roo-code/types").ClineMessage) => Promise updateClineMessage: (message: import("@roo-code/types").ClineMessage) => Promise saveClineMessages: () => Promise safeEnsureModelFetched: () => Promise @@ -362,6 +366,8 @@ describe("Cline", () => { mockProvider.postMessageToWebview = vi.fn().mockResolvedValue(undefined) mockProvider.postStateToWebview = vi.fn().mockResolvedValue(undefined) mockProvider.postStateToWebviewWithoutTaskHistory = vi.fn().mockResolvedValue(undefined) + mockProvider.postStateToWebviewThrottled = vi.fn().mockResolvedValue(undefined) + mockProvider.flushPostStateToWebviewThrottled = vi.fn().mockResolvedValue(undefined) mockProvider.getTaskWithId = vi.fn().mockImplementation(async (id) => ({ historyItem: { id, @@ -1227,6 +1233,8 @@ describe("Cline", () => { say: vi.fn(), postStateToWebview: vi.fn().mockResolvedValue(undefined), postStateToWebviewWithoutTaskHistory: vi.fn().mockResolvedValue(undefined), + postStateToWebviewThrottled: vi.fn().mockResolvedValue(undefined), + flushPostStateToWebviewThrottled: vi.fn().mockResolvedValue(undefined), postMessageToWebview: vi.fn().mockResolvedValue(undefined), updateTaskHistory: vi.fn().mockResolvedValue(undefined), // Task receives a full ClineProvider at runtime; this focused unit test only exercises these methods. @@ -1916,6 +1924,180 @@ describe("Cline", () => { }) }) + describe("webview state throttling", () => { + it("schedules a complete new message without forcing an immediate state push", async () => { + const task = new Task({ + provider: mockProvider, + apiConfiguration: mockApiConfig, + task: "test task", + startTask: false, + }) + vi.spyOn(getTaskTestAccess(task), "saveClineMessages").mockResolvedValue(true) + const message = { + ts: Date.now(), + type: "say" as const, + say: "text" as const, + text: "message", + } + + await getTaskTestAccess(task).addToClineMessages(message) + + expect(mockProvider.postStateToWebviewThrottled).toHaveBeenCalledOnce() + expect(mockProvider.postStateToWebviewThrottled).toHaveBeenCalledWith() + expect(mockProvider.flushPostStateToWebviewThrottled).not.toHaveBeenCalled() + expect(mockProvider.postStateToWebviewWithoutTaskHistory).not.toHaveBeenCalled() + }) + + it("waits for an unanswered ask flush before emitting the message", async () => { + const task = new Task({ + provider: mockProvider, + apiConfiguration: mockApiConfig, + task: "test task", + startTask: false, + }) + const taskAccess = getTaskTestAccess(task) + vi.spyOn(taskAccess, "saveClineMessages").mockResolvedValue(true) + let releaseFlush!: () => void + const pendingFlush = new Promise((resolve) => { + releaseFlush = resolve + }) + const flushSpy = vi.mocked(mockProvider.flushPostStateToWebviewThrottled).mockReturnValueOnce(pendingFlush) + const messageListener = vi.fn() + task.on(RooCodeEventName.Message, messageListener) + const message = { + ts: 1, + type: "ask" as const, + ask: "resume_task" as const, + } + + const addPromise = taskAccess.addToClineMessages(message) + + await Promise.resolve() + expect(mockProvider.postStateToWebviewThrottled).toHaveBeenCalledOnce() + expect(mockProvider.postStateToWebviewThrottled).toHaveBeenCalledWith() + expect(flushSpy).toHaveBeenCalledOnce() + expect(flushSpy).toHaveBeenCalledWith() + expect(messageListener).not.toHaveBeenCalled() + + releaseFlush() + await addPromise + + expect(flushSpy.mock.invocationCallOrder[0]).toBeLessThan(messageListener.mock.invocationCallOrder[0]) + expect(messageListener).toHaveBeenCalledWith({ action: "created", message }) + }) + + it("continues the message lifecycle when throttled state scheduling and flushing fail", async () => { + const task = new Task({ + provider: mockProvider, + apiConfiguration: mockApiConfig, + task: "test task", + startTask: false, + }) + const taskAccess = getTaskTestAccess(task) + const postError = new Error("state schedule failed") + const flushError = new Error("state flush failed") + const postSpy = vi.mocked(mockProvider.postStateToWebviewThrottled).mockRejectedValueOnce(postError) + const flushSpy = vi.mocked(mockProvider.flushPostStateToWebviewThrottled).mockRejectedValueOnce(flushError) + const saveSpy = vi.spyOn(taskAccess, "saveClineMessages").mockResolvedValue(true) + const messageListener = vi.fn() + const consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {}) + task.on(RooCodeEventName.Message, messageListener) + const message = { + ts: 1, + type: "ask" as const, + ask: "resume_task" as const, + } + + await expect(taskAccess.addToClineMessages(message)).resolves.toBeUndefined() + + expect(consoleErrorSpy).toHaveBeenCalledWith( + "[Task#addToClineMessages] postStateToWebviewThrottled failed:", + postError, + ) + expect(consoleErrorSpy).toHaveBeenCalledWith( + "[Task#addToClineMessages] flushPostStateToWebviewThrottled failed:", + flushError, + ) + expect(postSpy).toHaveBeenCalledOnce() + expect(flushSpy).toHaveBeenCalledOnce() + expect(messageListener).toHaveBeenCalledWith({ action: "created", message }) + expect(saveSpy).toHaveBeenCalledOnce() + expect(postSpy.mock.invocationCallOrder[0]).toBeLessThan(flushSpy.mock.invocationCallOrder[0]) + expect(flushSpy.mock.invocationCallOrder[0]).toBeLessThan(messageListener.mock.invocationCallOrder[0]) + expect(messageListener.mock.invocationCallOrder[0]).toBeLessThan(saveSpy.mock.invocationCallOrder[0]) + + consoleErrorSpy.mockRestore() + }) + + it("keeps an already answered ask on the throttled path", async () => { + const task = new Task({ + provider: mockProvider, + apiConfiguration: mockApiConfig, + task: "test task", + startTask: false, + }) + vi.spyOn(getTaskTestAccess(task), "saveClineMessages").mockResolvedValue(true) + + await getTaskTestAccess(task).addToClineMessages({ + ts: 1, + type: "ask", + ask: "tool", + isAnswered: true, + }) + + expect(mockProvider.postStateToWebviewThrottled).toHaveBeenCalledOnce() + expect(mockProvider.postStateToWebviewThrottled).toHaveBeenCalledWith() + expect(mockProvider.flushPostStateToWebviewThrottled).not.toHaveBeenCalled() + }) + + it("waits for a new partial message flush before a following message update", async () => { + const task = new Task({ + provider: mockProvider, + apiConfiguration: mockApiConfig, + task: "test task", + startTask: false, + }) + const taskAccess = getTaskTestAccess(task) + vi.spyOn(taskAccess, "saveClineMessages").mockResolvedValue(true) + let releaseFlush!: () => void + const pendingFlush = new Promise((resolve) => { + releaseFlush = resolve + }) + const flushSpy = vi.mocked(mockProvider.flushPostStateToWebviewThrottled).mockReturnValueOnce(pendingFlush) + const updatePostSpy = vi.mocked(mockProvider.postMessageToWebview) + const partialMessage = { + ts: 1, + type: "say" as const, + say: "text" as const, + text: "partial message", + partial: true, + } + let partialAddSettled = false + const addThenUpdate = taskAccess.addToClineMessages(partialMessage).then(async () => { + partialAddSettled = true + await taskAccess.updateClineMessage({ ...partialMessage, text: "updated partial" }) + }) + + await Promise.resolve() + expect(mockProvider.postStateToWebviewThrottled).toHaveBeenCalledWith() + expect(flushSpy).toHaveBeenCalledWith() + expect(partialAddSettled).toBe(false) + expect(updatePostSpy).not.toHaveBeenCalled() + + releaseFlush() + await addThenUpdate + + expect(flushSpy.mock.invocationCallOrder[0]).toBeLessThan(updatePostSpy.mock.invocationCallOrder[0]) + expect(updatePostSpy).toHaveBeenCalledWith({ + type: "messageUpdated", + clineMessage: { + ...partialMessage, + text: "updated partial", + }, + }) + }) + }) + describe("abortTask", () => { it("should set abort flag and emit TaskAborted event", async () => { const task = new Task({ @@ -1960,6 +2142,69 @@ describe("Cline", () => { expect(disposeSpy).toHaveBeenCalled() }) + it("flushes pending state before TaskAborted and disposal while queue state is intact", async () => { + const task = new Task({ + provider: mockProvider, + apiConfiguration: mockApiConfig, + task: "test task", + startTask: false, + }) + let queuedMessagesAtFlush = -1 + const flushSpy = vi.mocked(mockProvider.flushPostStateToWebviewThrottled).mockImplementation(async () => { + queuedMessagesAtFlush = task.messageQueueService.messages.length + }) + const emitSpy = vi.spyOn(task, "emit") + const disposeSpy = vi.spyOn(task, "dispose").mockImplementation(() => {}) + + task.messageQueueService.addMessage("queued text") + await task.abortTask() + + const taskAbortedCallIndex = (emitSpy.mock.calls as unknown[][]).findIndex( + ([event]) => event === RooCodeEventName.TaskAborted, + ) + expect(taskAbortedCallIndex).toBeGreaterThanOrEqual(0) + expect(queuedMessagesAtFlush).toBe(1) + expect(flushSpy).toHaveBeenCalledWith() + expect(flushSpy.mock.invocationCallOrder[0]).toBeLessThan( + emitSpy.mock.invocationCallOrder[taskAbortedCallIndex], + ) + expect(emitSpy.mock.invocationCallOrder[taskAbortedCallIndex]).toBeLessThan( + disposeSpy.mock.invocationCallOrder[0], + ) + }) + + it("continues abort cleanup when flushing pending state fails", async () => { + const task = new Task({ + provider: mockProvider, + apiConfiguration: mockApiConfig, + task: "test task", + startTask: false, + }) + const error = new Error("state flush failed") + const flushSpy = vi.mocked(mockProvider.flushPostStateToWebviewThrottled).mockRejectedValueOnce(error) + const taskAbortedListener = vi.fn() + const disposeSpy = vi.spyOn(task, "dispose").mockImplementation(() => {}) + const saveSpy = vi.spyOn(getTaskTestAccess(task), "saveClineMessages").mockResolvedValue(true) + const consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {}) + task.on(RooCodeEventName.TaskAborted, taskAbortedListener) + + await expect(task.abortTask()).resolves.toBeUndefined() + + expect(consoleErrorSpy).toHaveBeenCalledWith( + `[Task#abortTask] flushPostStateToWebviewThrottled failed for ${task.taskId}.${task.instanceId}:`, + error, + ) + expect(task.abort).toBe(true) + expect(flushSpy).toHaveBeenCalledOnce() + expect(taskAbortedListener).toHaveBeenCalledOnce() + expect(disposeSpy).toHaveBeenCalledOnce() + expect(saveSpy).toHaveBeenCalledOnce() + expect(flushSpy.mock.invocationCallOrder[0]).toBeLessThan(taskAbortedListener.mock.invocationCallOrder[0]) + expect(taskAbortedListener.mock.invocationCallOrder[0]).toBeLessThan(disposeSpy.mock.invocationCallOrder[0]) + + consoleErrorSpy.mockRestore() + }) + it("should work with TaskLike interface", async () => { const task = new Task({ provider: mockProvider, @@ -3000,6 +3245,50 @@ describe("Cline", () => { }) }) + describe("startTask", () => { + it("posts a clean state immediately before adding the first task message", async () => { + const task = new Task({ + provider: mockProvider, + apiConfiguration: mockApiConfig, + task: "new task", + startTask: false, + }) + const taskAccess = getTaskTestAccess(task) + + task.clineMessages = [{ ts: 1, type: "say", say: "text", text: "stale message" }] + + let resolvePostState: (() => void) | undefined + const pendingPostState = new Promise((resolve) => { + resolvePostState = resolve + }) + const postStateSpy = vi + .mocked(mockProvider.postStateToWebviewWithoutTaskHistory) + .mockImplementationOnce(async () => { + expect(task.clineMessages).toEqual([]) + await pendingPostState + }) + const saySpy = vi.spyOn(task, "say").mockResolvedValue(undefined) + vi.spyOn(taskAccess, "getEnabledMcpToolsCount").mockResolvedValue({ + enabledToolCount: 0, + enabledServerCount: 0, + }) + const initiateTaskLoopSpy = vi.spyOn(taskAccess, "initiateTaskLoop").mockResolvedValue(undefined) + + const startPromise = taskAccess.startTask("new task") + + expect(postStateSpy).toHaveBeenCalledTimes(1) + expect(mockProvider.postStateToWebviewThrottled).not.toHaveBeenCalled() + expect(saySpy).not.toHaveBeenCalled() + + resolvePostState?.() + await startPromise + + expect(saySpy).toHaveBeenCalledOnce() + expect(saySpy).toHaveBeenCalledWith("text", "new task", undefined) + expect(initiateTaskLoopSpy).toHaveBeenCalledOnce() + }) + }) + describe("start()", () => { it("should be a no-op if the task was already started in the constructor", () => { const task = new Task({ @@ -3118,9 +3407,9 @@ describe("Cline", () => { resumeSpy.mockRestore() }) - it("logs (instead of crashing) when postStateToWebviewWithoutTaskHistory rejects from the queue handler", async () => { + it("logs (instead of crashing) when postStateToWebviewThrottled rejects from the queue handler", async () => { const boom = new Error("postState boom") - mockProvider.postStateToWebviewWithoutTaskHistory = vi.fn().mockRejectedValue(boom) + mockProvider.postStateToWebviewThrottled = vi.fn().mockRejectedValue(boom) const task = new Task({ provider: mockProvider, @@ -3129,13 +3418,14 @@ describe("Cline", () => { startTask: false, }) - // Triggers messageQueueStateChangedHandler -> void postStateToWebviewWithoutTaskHistory() + // Triggers messageQueueStateChangedHandler -> void postStateToWebviewThrottled() task.messageQueueService.addMessage("queued text") await flushMicrotasks() - expect(mockProvider.postStateToWebviewWithoutTaskHistory).toHaveBeenCalled() + expect(mockProvider.postStateToWebviewThrottled).toHaveBeenCalledWith() + expect(mockProvider.postStateToWebviewWithoutTaskHistory).not.toHaveBeenCalled() expect(consoleErrorSpy).toHaveBeenCalledWith( - "[Task#messageQueueStateChangedHandler] postStateToWebviewWithoutTaskHistory failed:", + "[Task#messageQueueStateChangedHandler] postStateToWebviewThrottled failed:", boom, ) }) diff --git a/src/core/task/__tests__/Task.throttle.test.ts b/src/core/task/__tests__/Task.throttle.test.ts index 34d78a4ef9..0eac687e64 100644 --- a/src/core/task/__tests__/Task.throttle.test.ts +++ b/src/core/task/__tests__/Task.throttle.test.ts @@ -79,6 +79,8 @@ describe("Task token usage throttling", () => { log: vi.fn(), postStateToWebview: vi.fn().mockResolvedValue(undefined), postStateToWebviewWithoutTaskHistory: vi.fn().mockResolvedValue(undefined), + postStateToWebviewThrottled: vi.fn().mockResolvedValue(undefined), + flushPostStateToWebviewThrottled: vi.fn().mockResolvedValue(undefined), updateTaskHistory: vi.fn().mockResolvedValue(undefined), } diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 2d3e425f12..6f70a19946 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -6,6 +6,7 @@ import EventEmitter from "events" import { Anthropic } from "@anthropic-ai/sdk" import delay from "delay" import axios from "axios" +import debounce from "lodash.debounce" import pWaitFor from "p-wait-for" import * as vscode from "vscode" @@ -161,6 +162,10 @@ function scheduleTask(scheduler: TaskScheduler, task: Task, source: string): voi .catch((error) => console.error(`[${source}] taskScheduler.schedule failed:`, error)) } +type GetStateOptions = { + includeTaskHistory?: boolean +} + export class ClineProvider extends EventEmitter implements vscode.WebviewViewProvider, TelemetryPropertiesProvider, TaskProviderLike @@ -189,6 +194,21 @@ export class ClineProvider private taskEventListeners: WeakMap void>> = new WeakMap() private currentWorkspacePath: string | undefined private _disposed = false + private readonly _postStateToWebviewThrottled = debounce( + async () => { + try { + await this.postStateToWebviewWithoutTaskHistory() + } catch (error) { + this.log( + `[ClineProvider#postStateToWebviewThrottled] Failed to post state: ${ + error instanceof Error ? error.message : String(error) + }`, + ) + } + }, + 500, + { leading: true, trailing: true, maxWait: 1000 }, + ) private readonly rateLimitClock: RateLimitClock = createRateLimitClock() private recentTasksCache?: string[] @@ -747,6 +767,7 @@ export class ClineProvider } this._disposed = true + this._postStateToWebviewThrottled.cancel() this.log("Disposing ClineProvider...") // Reject any tasks still waiting for a scheduler permit so they don't @@ -2308,13 +2329,35 @@ export class ClineProvider * `taskHistoryUpdated` / `taskHistoryItemUpdated`. */ async postStateToWebviewWithoutTaskHistory(): Promise { - const state = await this.getStateToPostToWebview() + const state = await this.getStateToPostToWebview({ includeTaskHistory: false }) this.clineMessagesSeq++ state.clineMessagesSeq = this.clineMessagesSeq const { taskHistory: _omit, ...rest } = state await this.postMessageToWebview({ type: "state", state: rest }) } + /** + * Schedules a debounced state-post attempt. A call made while the debounce timer is active returns + * the result of the most recent invocation, so awaiting this method does not wait for the trailing + * invocation scheduled by that call. Use `flushPostStateToWebviewThrottled()` to force and await any + * pending trailing invocation before continuing. + */ + async postStateToWebviewThrottled(): Promise { + if (this._disposed) { + return + } + + await this._postStateToWebviewThrottled() + } + + async flushPostStateToWebviewThrottled(): Promise { + if (this._disposed) { + return + } + + await this._postStateToWebviewThrottled.flush() + } + /** * Like postStateToWebview but intentionally omits both clineMessages and taskHistory. * @@ -2327,7 +2370,7 @@ export class ClineProvider * (cloud auth, org settings, profiles, etc.) without interfering with task message streaming. */ async postStateToWebviewWithoutClineMessages(): Promise { - const state = await this.getStateToPostToWebview() + const state = await this.getStateToPostToWebview({ includeTaskHistory: false }) const { clineMessages: _omitMessages, taskHistory: _omitHistory, ...rest } = state await this.postMessageToWebview({ type: "state", state: rest }) } @@ -2433,7 +2476,7 @@ export class ClineProvider } } - async getStateToPostToWebview(): Promise { + async getStateToPostToWebview({ includeTaskHistory = true }: GetStateOptions = {}): Promise { // Ensure the store is initialized before reading task history await this.taskHistoryStore.initialized @@ -2462,7 +2505,6 @@ export class ClineProvider ttsSpeed, enableCheckpoints, checkpointTimeout, - taskHistory, soundVolume, writeDelayMs, diffFuzzyThreshold, @@ -2525,7 +2567,7 @@ export class ClineProvider autoCloseZooOpenedFiles, autoCloseZooOpenedFilesAfterUserEdited, autoCloseZooOpenedNewFiles, - } = await this.getState() + } = await this.getState({ includeTaskHistory: false }) let cloudOrganizations: CloudOrganizationMembership[] = [] @@ -2611,7 +2653,9 @@ export class ClineProvider clineMessages: currentTask?.clineMessages || [], currentTaskTodos: currentTask?.todoList || [], messageQueue: currentTask?.messageQueueService?.messages, - taskHistory: this.taskHistoryStore.getAll().filter((item: HistoryItem) => item.ts && item.task), + taskHistory: includeTaskHistory + ? this.taskHistoryStore.getAll().filter((item: HistoryItem) => item.ts && item.task) + : [], soundEnabled: soundEnabled ?? false, ttsEnabled: ttsEnabled ?? false, ttsSpeed: ttsSpeed ?? 1.0, @@ -2746,7 +2790,7 @@ export class ClineProvider * https://www.eliostruyf.com/devhack-code-extension-storage-options/ */ - async getState(): Promise< + async getState({ includeTaskHistory = true }: GetStateOptions = {}): Promise< Omit< ExtensionState, "clineMessages" | "renderContext" | "hasOpenedModeSelector" | "version" | "shouldShowAnnouncement" @@ -2842,7 +2886,7 @@ export class ClineProvider allowedMaxCost: stateValues.allowedMaxCost, autoCondenseContext: stateValues.autoCondenseContext ?? true, autoCondenseContextPercent: stateValues.autoCondenseContextPercent ?? 100, - taskHistory: this.taskHistoryStore.getAll(), + taskHistory: includeTaskHistory ? this.taskHistoryStore.getAll() : [], allowedCommands: stateValues.allowedCommands, deniedCommands: stateValues.deniedCommands, soundEnabled: stateValues.soundEnabled ?? false, diff --git a/src/core/webview/__tests__/ClineProvider.spec.ts b/src/core/webview/__tests__/ClineProvider.spec.ts index 6167158ccc..e336ac8fac 100644 --- a/src/core/webview/__tests__/ClineProvider.spec.ts +++ b/src/core/webview/__tests__/ClineProvider.spec.ts @@ -794,6 +794,223 @@ describe("ClineProvider", () => { expect(postMessageSpy).not.toHaveBeenCalledWith(expect.objectContaining({ type: "action" })) }) + test("postStateToWebviewWithoutTaskHistory waits for the webview post boundary", async () => { + let releasePost!: () => void + const pendingPost = new Promise((resolve) => { + releasePost = resolve + }) + let statePostSettled = false + + vi.spyOn(provider, "getStateToPostToWebview").mockResolvedValue({ + taskHistory: [], + } as unknown as ExtensionState) + const postMessageSpy = vi.spyOn(provider, "postMessageToWebview").mockReturnValue(pendingPost) + + const statePost = provider.postStateToWebviewWithoutTaskHistory() + void statePost.then(() => { + statePostSettled = true + }) + await Promise.resolve() + + expect(postMessageSpy).toHaveBeenCalledOnce() + expect(statePostSettled).toBe(false) + + releasePost() + await statePost + expect(statePostSettled).toBe(true) + }) + + test.each([ + [ + "postStateToWebviewWithoutTaskHistory", + (currentProvider: ClineProvider) => currentProvider.postStateToWebviewWithoutTaskHistory(), + ], + [ + "postStateToWebviewWithoutClineMessages", + (currentProvider: ClineProvider) => currentProvider.postStateToWebviewWithoutClineMessages(), + ], + ])("%s skips task history computation", async (_methodName, postState) => { + const getAllSpy = vi.spyOn(provider.taskHistoryStore, "getAll") + const postMessageSpy = vi.spyOn(provider, "postMessageToWebview").mockResolvedValue(undefined) + + await postState(provider) + + expect(getAllSpy).not.toHaveBeenCalled() + expect(postMessageSpy).toHaveBeenCalledOnce() + expect(postMessageSpy.mock.calls[0]?.[0].state).not.toHaveProperty("taskHistory") + }) + + test("getStateToPostToWebview computes task history once after its base state resolves", async () => { + const historyItem = { + id: "history-task", + number: 1, + ts: 1, + task: "History task", + tokensIn: 0, + tokensOut: 0, + totalCost: 0, + } + const originalGetState = provider.getState.bind(provider) + let baseStateResolved = false + const getStateSpy = vi.spyOn(provider, "getState").mockImplementation(async (options) => { + const state = await originalGetState(options) + baseStateResolved = true + return state + }) + const historyReadPhases: boolean[] = [] + const getAllSpy = vi.spyOn(provider.taskHistoryStore, "getAll").mockImplementation(() => { + historyReadPhases.push(baseStateResolved) + return [historyItem] + }) + + const state = await provider.getStateToPostToWebview() + + expect(getStateSpy).toHaveBeenCalledOnce() + expect(getStateSpy).toHaveBeenCalledWith({ includeTaskHistory: false }) + expect(getAllSpy).toHaveBeenCalledOnce() + expect(historyReadPhases).toEqual([true]) + expect(state.taskHistory).toEqual([historyItem]) + }) + + describe("postStateToWebviewThrottled", () => { + beforeEach(() => { + vi.useFakeTimers() + }) + + afterEach(async () => { + await provider.dispose() + vi.useRealTimers() + }) + + test("posts on the leading edge and coalesces a burst into one trailing post", async () => { + const postStateSpy = vi.spyOn(provider, "postStateToWebviewWithoutTaskHistory").mockResolvedValue(undefined) + + await provider.postStateToWebviewThrottled() + await provider.postStateToWebviewThrottled() + await provider.postStateToWebviewThrottled() + + expect(postStateSpy).toHaveBeenCalledTimes(1) + + await vi.advanceTimersByTimeAsync(499) + expect(postStateSpy).toHaveBeenCalledTimes(1) + + await vi.advanceTimersByTimeAsync(1) + expect(postStateSpy).toHaveBeenCalledTimes(2) + }) + + test("does not starve state posts during continuous updates", async () => { + const postStateSpy = vi.spyOn(provider, "postStateToWebviewWithoutTaskHistory").mockResolvedValue(undefined) + + await provider.postStateToWebviewThrottled() + await vi.advanceTimersByTimeAsync(400) + await provider.postStateToWebviewThrottled() + await vi.advanceTimersByTimeAsync(400) + await provider.postStateToWebviewThrottled() + await vi.advanceTimersByTimeAsync(199) + + expect(postStateSpy).toHaveBeenCalledTimes(1) + + await vi.advanceTimersByTimeAsync(1) + expect(postStateSpy).toHaveBeenCalledTimes(2) + }) + + test("flushes a pending trailing post exactly once and waits for it", async () => { + let releasePost!: () => void + const pendingPost = new Promise((resolve) => { + releasePost = resolve + }) + const postStateSpy = vi + .spyOn(provider, "postStateToWebviewWithoutTaskHistory") + .mockResolvedValueOnce(undefined) + .mockReturnValueOnce(pendingPost) + + await provider.postStateToWebviewThrottled() + await provider.postStateToWebviewThrottled() + expect(postStateSpy).toHaveBeenCalledTimes(1) + + let flushSettled = false + const flushPromise = provider.flushPostStateToWebviewThrottled() + void flushPromise.then(() => { + flushSettled = true + }) + await Promise.resolve() + + expect(postStateSpy).toHaveBeenCalledTimes(2) + expect(flushSettled).toBe(false) + + releasePost() + await flushPromise + expect(flushSettled).toBe(true) + + await vi.advanceTimersByTimeAsync(1000) + expect(postStateSpy).toHaveBeenCalledTimes(2) + }) + + test("does not duplicate an idle leading post when flushed", async () => { + const postStateSpy = vi.spyOn(provider, "postStateToWebviewWithoutTaskHistory").mockResolvedValue(undefined) + + await provider.postStateToWebviewThrottled() + await provider.flushPostStateToWebviewThrottled() + await vi.advanceTimersByTimeAsync(1000) + + expect(postStateSpy).toHaveBeenCalledOnce() + }) + + test("handles state post failures inside the debounced callback", async () => { + const error = new Error("state post failed") + const logSpy = vi.spyOn(provider, "log").mockImplementation(() => {}) + vi.spyOn(provider, "postStateToWebviewWithoutTaskHistory").mockRejectedValue(error) + + await expect(provider.postStateToWebviewThrottled()).resolves.toBeUndefined() + expect(logSpy).toHaveBeenCalledWith( + "[ClineProvider#postStateToWebviewThrottled] Failed to post state: state post failed", + ) + }) + + test("stringifies non-Error state post failures inside the debounced callback", async () => { + const logSpy = vi.spyOn(provider, "log").mockImplementation(() => {}) + vi.spyOn(provider, "postStateToWebviewWithoutTaskHistory").mockRejectedValue("state post failed") + + await expect(provider.postStateToWebviewThrottled()).resolves.toBeUndefined() + expect(logSpy).toHaveBeenCalledWith( + "[ClineProvider#postStateToWebviewThrottled] Failed to post state: state post failed", + ) + }) + + test("handles state post failures while flushing a pending trailing post", async () => { + const error = new Error("state post failed") + const logSpy = vi.spyOn(provider, "log").mockImplementation(() => {}) + const postStateSpy = vi + .spyOn(provider, "postStateToWebviewWithoutTaskHistory") + .mockResolvedValueOnce(undefined) + .mockRejectedValueOnce(error) + + await provider.postStateToWebviewThrottled() + await provider.postStateToWebviewThrottled() + await expect(provider.flushPostStateToWebviewThrottled()).resolves.toBeUndefined() + + expect(postStateSpy).toHaveBeenCalledTimes(2) + expect(logSpy).toHaveBeenCalledWith( + "[ClineProvider#postStateToWebviewThrottled] Failed to post state: state post failed", + ) + }) + + test("cancels pending work on dispose and ignores later schedule or flush calls", async () => { + const postStateSpy = vi.spyOn(provider, "postStateToWebviewWithoutTaskHistory").mockResolvedValue(undefined) + + await provider.postStateToWebviewThrottled() + await provider.postStateToWebviewThrottled() + expect(postStateSpy).toHaveBeenCalledTimes(1) + + await provider.dispose() + await vi.advanceTimersByTimeAsync(1000) + await provider.postStateToWebviewThrottled() + await provider.flushPostStateToWebviewThrottled() + + expect(postStateSpy).toHaveBeenCalledTimes(1) + }) + }) + test("postMessageToWebview skips postMessage after dispose", async () => { await provider.resolveWebviewView(mockWebviewView) diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index b79747eaa5..25aec24cfc 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -1,4 +1,13 @@ -import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react" +import React, { + forwardRef, + useCallback, + useEffect, + useImperativeHandle, + useLayoutEffect, + useMemo, + useRef, + useState, +} from "react" import { useDeepCompareEffect, useEvent } from "react-use" import { Virtuoso, type VirtuosoHandle } from "react-virtuoso" import removeMd from "remove-markdown" @@ -77,6 +86,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction { + currentTaskIdRef.current = currentTaskId + }, [currentTaskId]) useEffect(() => { messagesRef.current = messages @@ -514,13 +529,14 @@ const ChatViewComponent: React.ForwardRefRenderFunction { - const newMap = new Map(prev) - newMap.set(message.text!, message.aggregatedCosts!) - return newMap - }) + if (message.text && message.text === currentTaskIdRef.current && message.aggregatedCosts) { + setAggregatedCostsMap(new Map([[message.text, message.aggregatedCosts]])) } break } @@ -1630,6 +1642,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction 0 - ) - } + aggregatedCost={currentTaskAggregatedCosts?.totalCost} + hasSubtasks={(currentTaskAggregatedCosts?.childrenCost ?? 0) > 0} parentTaskId={currentTaskItem?.parentTaskId} costBreakdown={ - currentTaskItem?.id && aggregatedCostsMap.has(currentTaskItem.id) - ? getCostBreakdownIfNeeded(aggregatedCostsMap.get(currentTaskItem.id)!, { + currentTaskAggregatedCosts + ? getCostBreakdownIfNeeded(currentTaskAggregatedCosts, { own: t("common:costs.own"), subtasks: t("common:costs.subtasks"), }) diff --git a/webview-ui/src/components/chat/__tests__/ChatView.spec.tsx b/webview-ui/src/components/chat/__tests__/ChatView.spec.tsx index 123e0014f3..6b2fa177c9 100644 --- a/webview-ui/src/components/chat/__tests__/ChatView.spec.tsx +++ b/webview-ui/src/components/chat/__tests__/ChatView.spec.tsx @@ -82,6 +82,25 @@ vi.mock("../ChatRow", () => ({ }, })) +const mockTaskHeaderState = vi.hoisted(() => ({ + renders: [] as Array<{ taskId?: string; aggregatedCost?: number }>, +})) + +vi.mock("../TaskHeader", () => ({ + default: function MockTaskHeader({ task, aggregatedCost }: { task: ClineMessage; aggregatedCost?: number }) { + mockTaskHeaderState.renders.push({ taskId: task.text, aggregatedCost }) + + return ( +
+ ) + }, +})) + vi.mock("../AutoApproveMenu", () => ({ default: () => null, })) @@ -339,6 +358,51 @@ const mockPostMessage = (state: Record) => { ) } +const dispatchExtensionMessage = async (data: Record) => { + await act(async () => { + window.dispatchEvent(new MessageEvent("message", { data })) + }) +} + +const dispatchTaskState = async (id: string, taskTs: number, childIds: string[] = []) => { + await dispatchExtensionMessage({ + type: "state", + state: makeExtensionState({ + clineMessages: [ + { + type: "say", + say: "task", + ts: taskTs, + text: id, + }, + ], + currentTaskId: id, + currentTaskItem: { + id, + number: 1, + ts: taskTs, + task: id, + tokensIn: 0, + tokensOut: 0, + totalCost: 0, + childIds, + }, + }), + }) +} + +const dispatchAggregatedCosts = async (taskId: string, totalCost: number) => { + await dispatchExtensionMessage({ + type: "taskWithAggregatedCosts", + text: taskId, + aggregatedCosts: { + totalCost, + ownCost: 1, + childrenCost: totalCost - 1, + }, + }) +} + const defaultProps: ChatViewProps = { isHidden: false, showAnnouncement: false, @@ -398,6 +462,65 @@ describe("ChatView - Tool Batching Tests", () => { }) }) +describe("ChatView - Aggregated Costs Lifecycle", () => { + beforeEach(() => { + vi.clearAllMocks() + mockTaskHeaderState.renders.length = 0 + }) + + it("clears cached aggregated costs when switching tasks", async () => { + const { getByTestId } = renderChatView() + + await dispatchTaskState("task-a", 1_000, ["child-a"]) + await dispatchAggregatedCosts("task-a", 9) + + await waitFor(() => { + expect(getByTestId("task-header")).toHaveAttribute("data-aggregated-cost", "9") + }) + + // Use the same message timestamp to prove task identity, rather than task.ts, + // drives the reset. + await dispatchTaskState("task-b", 1_000) + await waitFor(() => { + expect(getByTestId("task-header")).toHaveAttribute("data-task-id", "task-b") + expect(getByTestId("task-header")).toHaveAttribute("data-aggregated-cost", "") + }) + + await dispatchTaskState("task-a", 1_000, ["child-a"]) + await waitFor(() => { + expect(getByTestId("task-header")).toHaveAttribute("data-task-id", "task-a") + expect(getByTestId("task-header")).toHaveAttribute("data-aggregated-cost", "") + }) + }) + + it("rejects a delayed aggregated-cost response from the previous task", async () => { + const { getByTestId } = renderChatView() + + await dispatchTaskState("task-a", 1_001, ["child-a"]) + await dispatchTaskState("task-b", 2_001) + await dispatchAggregatedCosts("task-a", 13) + + await waitFor(() => { + expect(getByTestId("task-header")).toHaveAttribute("data-task-id", "task-b") + expect(getByTestId("task-header")).toHaveAttribute("data-aggregated-cost", "") + }) + + mockTaskHeaderState.renders.length = 0 + await dispatchTaskState("task-a", 1_001, ["child-a"]) + + await waitFor(() => { + expect(getByTestId("task-header")).toHaveAttribute("data-task-id", "task-a") + expect(getByTestId("task-header")).toHaveAttribute("data-aggregated-cost", "") + }) + + expect( + mockTaskHeaderState.renders.some( + ({ taskId, aggregatedCost }) => taskId === "task-a" && aggregatedCost === 13, + ), + ).toBe(false) + }) +}) + describe("ChatView - Sound Playing Tests", () => { beforeEach(() => vi.clearAllMocks()) From 61cad5b0d73c49e6fc6e094b8aad52d620292abc Mon Sep 17 00:00:00 2001 From: Para <62068271+murd0cc@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:30:28 +0300 Subject: [PATCH 21/66] test: wire AutoApprove visual tests to manual follow-up timer snapshots --- ...pproveSettings.manualSnapshots.fixture.tsx | 14 +++++----- .../__tests__/AutoApproveSettings.visual.tsx | 25 +++++------------- .../__screenshots__/screenshot (1).png | Bin 149965 -> 0 bytes .../__screenshots__/screenshot (2).png | Bin 100889 -> 0 bytes .../__screenshots__/screenshot (3).png | Bin 152280 -> 0 bytes 5 files changed, 14 insertions(+), 25 deletions(-) delete mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (1).png delete mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (2).png delete mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (3).png diff --git a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.manualSnapshots.fixture.tsx b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.manualSnapshots.fixture.tsx index 4110f8fbed..8d7a745462 100644 --- a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.manualSnapshots.fixture.tsx +++ b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.manualSnapshots.fixture.tsx @@ -1,8 +1,8 @@ import React from "react" -import screenshot1 from "./__screenshots__/screenshot (1).png" -import screenshot2 from "./__screenshots__/screenshot (2).png" -import screenshot3 from "./__screenshots__/screenshot (3).png" +import screenshot1 from "./__screenshots__/screenshot-1-.png" +import screenshot2 from "./__screenshots__/screenshot-2-.png" +import screenshot3 from "./__screenshots__/screenshot-3-.png" const SnapshotImage = ({ src, alt }: { src: string; alt: string }) => (
@@ -10,6 +10,10 @@ const SnapshotImage = ({ src, alt }: { src: string; alt: string }) => (
) +export const AutoApproveSettingsManualSnapshot1Fixture = () => ( + +) + export const AutoApproveSettingsManualSnapshot2Fixture = () => ( ) @@ -17,7 +21,3 @@ export const AutoApproveSettingsManualSnapshot2Fixture = () => ( export const AutoApproveSettingsManualSnapshot3Fixture = () => ( ) - -export const AutoApproveSettingsManualSnapshot1Fixture = () => ( - -) diff --git a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx index 48d633e9e9..d2e5995758 100644 --- a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx +++ b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx @@ -1,23 +1,16 @@ import React from "react" import { expect, test } from "../../../../playwright/coverage-fixture" -import screenshot1 from "./__screenshots__/screenshot (1).png" -import screenshot2 from "./__screenshots__/screenshot (2).png" -import screenshot3 from "./__screenshots__/screenshot (3).png" import { AutoApproveSettingsManualSnapshot1Fixture, AutoApproveSettingsManualSnapshot2Fixture, AutoApproveSettingsManualSnapshot3Fixture, -} from "./AutoApproveSettings.visual.fixture" - -const manualReferencePngs = [screenshot1, screenshot2, screenshot3] - -test("matches provided manual snapshot (1)", async ({ mount }) => { - expect(manualReferencePngs[0]).toBeTruthy() +} from "./AutoApproveSettings.manualSnapshots.fixture" +test("matches provided manual snapshot (1)", async ({ mount, page }) => { const component = await mount() - await component.evaluate(async () => { + await page.evaluate(async () => { await document.fonts.ready await new Promise((resolve) => requestAnimationFrame(() => resolve())) }) @@ -25,12 +18,10 @@ test("matches provided manual snapshot (1)", async ({ mount }) => { await expect(component).toHaveScreenshot("screenshot-1-.png") }) -test("matches provided manual snapshot (2)", async ({ mount }) => { - expect(manualReferencePngs[1]).toBeTruthy() - +test("matches provided manual snapshot (2)", async ({ mount, page }) => { const component = await mount() - await component.evaluate(async () => { + await page.evaluate(async () => { await document.fonts.ready await new Promise((resolve) => requestAnimationFrame(() => resolve())) }) @@ -38,12 +29,10 @@ test("matches provided manual snapshot (2)", async ({ mount }) => { await expect(component).toHaveScreenshot("screenshot-2-.png") }) -test("matches provided manual snapshot (3)", async ({ mount }) => { - expect(manualReferencePngs[2]).toBeTruthy() - +test("matches provided manual snapshot (3)", async ({ mount, page }) => { const component = await mount() - await component.evaluate(async () => { + await page.evaluate(async () => { await document.fonts.ready await new Promise((resolve) => requestAnimationFrame(() => resolve())) }) diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (1).png b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (1).png deleted file mode 100644 index a7370a4685745640aef8306814dc079c62334da8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 149965 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
GrK2#^Fu*4&gTDfWo%ju0v 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%0A?`bP%%lqs!n=y!(L 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 diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (2).png b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (2).png deleted file mode 100644 index d82607ca753a4c7668e2d4ca708fadbb96428538..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 100889 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 A*Z=?k From 3901fec1196611931507484781a0e0dd686d4e8d Mon Sep 17 00:00:00 2001 From: Para <62068271+murd0cc@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:37:54 +0300 Subject: [PATCH 22/66] missing snapshot --- .../model-info-service-tier-pricing-dark.png | Bin 0 -> 11241 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/model-info-service-tier-pricing-dark.png diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/model-info-service-tier-pricing-dark.png b/webview-ui/src/components/settings/__tests__/__screenshots__/model-info-service-tier-pricing-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..44bb9d09cbe91c37e58ae9b158e2b39ca131db4c GIT binary patch literal 11241 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 RU>-RG0LdszS4f(K{4XIQTiyTw literal 0 HcmV?d00001 From dfc839e86ec84240b144efeab7ae7d9b939143a3 Mon Sep 17 00:00:00 2001 From: Para <62068271+murd0cc@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:43:13 +0300 Subject: [PATCH 23/66] Updated screenshot assertion --- .../components/settings/__tests__/ModelInfoView.visual.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/webview-ui/src/components/settings/__tests__/ModelInfoView.visual.tsx b/webview-ui/src/components/settings/__tests__/ModelInfoView.visual.tsx index 0b5074e761..62e0d5cc12 100644 --- a/webview-ui/src/components/settings/__tests__/ModelInfoView.visual.tsx +++ b/webview-ui/src/components/settings/__tests__/ModelInfoView.visual.tsx @@ -11,5 +11,7 @@ test("renders OpenAI service tier pricing in the VS Code dark theme", async ({ m await new Promise((resolve) => requestAnimationFrame(() => resolve())) }) - await expect(component).toHaveScreenshot("model-info-service-tier-pricing-dark.png") + await expect(component).toHaveScreenshot("model-info-service-tier-pricing-dark.png", { + maxDiffPixelRatio: 0.05, + }) }) From 9081dde63dbd5cdc0c1e28166c922932563c31e9 Mon Sep 17 00:00:00 2001 From: Alexei Gubin <36731953+WebMad@users.noreply.github.com> Date: Sun, 16 Aug 2026 21:51:54 +0000 Subject: [PATCH 24/66] refactor(webview): canonicalize provider and model message identifiers (#1143) * refactor(webview): canonicalize provider settings identifiers * refactor(webview): centralize model message identifiers --- .../src/__tests__/model-message-types.test.ts | 47 +++++ packages/types/src/__tests__/nanogpt.test.ts | 9 +- packages/types/src/model.ts | 15 ++ packages/types/src/providers/lm-studio.ts | 10 + packages/types/src/providers/ollama.ts | 10 + packages/types/src/providers/openai.ts | 10 + packages/types/src/providers/vscode-llm.ts | 10 + packages/types/src/vscode-extension-host.ts | 30 +-- src/api/providers/__tests__/nanogpt.spec.ts | 8 +- src/api/providers/nanogpt.ts | 3 +- src/core/webview/webviewMessageHandler.ts | 41 ++-- .../src/components/settings/ApiOptions.tsx | 14 +- .../components/settings/providers/Kenari.tsx | 3 +- .../settings/providers/KimiCode.tsx | 10 +- .../settings/providers/LMStudio.tsx | 9 +- .../components/settings/providers/LiteLLM.tsx | 60 ++++-- .../settings/providers/Moonshot.tsx | 57 ++++-- .../components/settings/providers/NanoGPT.tsx | 8 +- .../components/settings/providers/Ollama.tsx | 41 ++-- .../settings/providers/OpenAICompatible.tsx | 3 +- .../settings/providers/OpenCodeGo.tsx | 45 +++-- .../src/components/settings/providers/Poe.tsx | 54 +++-- .../settings/providers/Requesty.tsx | 9 +- .../components/settings/providers/Unbound.tsx | 7 +- .../settings/providers/VSCodeLM.tsx | 9 +- .../settings/providers/VercelAiGateway.tsx | 3 +- .../settings/providers/ZooGateway.tsx | 3 +- .../providers/__tests__/KimiCode.spec.tsx | 75 ++++++- .../providers/__tests__/LiteLLM.spec.tsx | 187 ++++++++++++++++++ .../providers/__tests__/Moonshot.spec.tsx | 126 ++++++++++-- .../providers/__tests__/NanoGPT.spec.tsx | 10 +- .../settings/providers/__tests__/Poe.spec.tsx | 150 ++++++++++++++ .../__tests__/ProviderRouting.spec.tsx | 82 ++++++++ .../providers/__tests__/Requesty.spec.tsx | 57 ++++++ .../components/ui/hooks/useLmStudioModels.ts | 6 +- .../components/ui/hooks/useOllamaModels.ts | 6 +- .../components/ui/hooks/useRouterModels.ts | 15 +- .../ui/hooks/useZooGatewayRouterModelsSync.ts | 13 +- .../src/context/ExtensionStateContext.tsx | 3 +- 39 files changed, 1072 insertions(+), 186 deletions(-) create mode 100644 packages/types/src/__tests__/model-message-types.test.ts create mode 100644 webview-ui/src/components/settings/providers/__tests__/LiteLLM.spec.tsx create mode 100644 webview-ui/src/components/settings/providers/__tests__/Poe.spec.tsx create mode 100644 webview-ui/src/components/settings/providers/__tests__/ProviderRouting.spec.tsx create mode 100644 webview-ui/src/components/settings/providers/__tests__/Requesty.spec.tsx diff --git a/packages/types/src/__tests__/model-message-types.test.ts b/packages/types/src/__tests__/model-message-types.test.ts new file mode 100644 index 0000000000..453de78be1 --- /dev/null +++ b/packages/types/src/__tests__/model-message-types.test.ts @@ -0,0 +1,47 @@ +import { + OllamaModelsMessageType, + ollamaModelsMessageTypeSchema, + ollamaModelsMessageTypes, +} from "../providers/ollama.js" +import { OpenAiModelsMessageType, openAiModelsMessageTypeSchema } from "../providers/openai.js" +import { LmStudioModelsMessageType, lmStudioModelsMessageTypeSchema } from "../providers/lm-studio.js" +import { VsCodeLmModelsMessageType, vsCodeLmModelsMessageTypeSchema } from "../providers/vscode-llm.js" + +describe("OllamaModelsMessageType", () => { + it("exposes the request and response message types", () => { + expect(ollamaModelsMessageTypes).toEqual(["requestOllamaModels", "ollamaModels"]) + expect(OllamaModelsMessageType.requestOllamaModels).toBe("requestOllamaModels") + expect(OllamaModelsMessageType.ollamaModels).toBe("ollamaModels") + }) + + it("validates supported message types", () => { + expect(ollamaModelsMessageTypeSchema.safeParse("requestOllamaModels").success).toBe(true) + expect(ollamaModelsMessageTypeSchema.safeParse("ollamaModels").success).toBe(true) + expect(ollamaModelsMessageTypeSchema.safeParse("requestUnknownModels").success).toBe(false) + }) +}) + +describe.each([ + ["OpenAI", OpenAiModelsMessageType, openAiModelsMessageTypeSchema, "requestOpenAiModels", "openAiModels"], + [ + "LM Studio", + LmStudioModelsMessageType, + lmStudioModelsMessageTypeSchema, + "requestLmStudioModels", + "lmStudioModels", + ], + [ + "VS Code LM", + VsCodeLmModelsMessageType, + vsCodeLmModelsMessageTypeSchema, + "requestVsCodeLmModels", + "vsCodeLmModels", + ], +])("%s model message types", (_provider, messageType, schema, requestType, responseType) => { + it("exposes and validates its request and response types", () => { + expect(messageType).toMatchObject({ [requestType]: requestType, [responseType]: responseType }) + expect(schema.safeParse(requestType).success).toBe(true) + expect(schema.safeParse(responseType).success).toBe(true) + expect(schema.safeParse("unknownModelsMessage").success).toBe(false) + }) +}) diff --git a/packages/types/src/__tests__/nanogpt.test.ts b/packages/types/src/__tests__/nanogpt.test.ts index 50eacdd276..717d05ec59 100644 --- a/packages/types/src/__tests__/nanogpt.test.ts +++ b/packages/types/src/__tests__/nanogpt.test.ts @@ -13,13 +13,16 @@ import { describe("NanoGPT shared contract", () => { it("registers the stable dynamic-provider identity and default model", () => { expect(providerIdentifiers.nanogpt).toBe("nanogpt") - expect(dynamicProviders).toContain("nanogpt") - expect(getProviderDefaultModelId("nanogpt")).toBe(nanoGptDefaultModelId) + expect(dynamicProviders).toContain(providerIdentifiers.nanogpt) + expect(getProviderDefaultModelId(providerIdentifiers.nanogpt)).toBe(nanoGptDefaultModelId) }) it("classifies the API key as secret and resolves missing routing to auto", () => { expect(isSecretStateKey("nanoGptApiKey")).toBe(true) - const settings = providerSettingsSchema.parse({ apiProvider: "nanogpt", nanoGptModelId: "model" }) + const settings = providerSettingsSchema.parse({ + apiProvider: providerIdentifiers.nanogpt, + nanoGptModelId: "model", + }) expect(settings.nanoGptRoutingPreference ?? nanoGptDefaultRoutingPreference).toBe("auto") expect(getModelId(settings)).toBe("model") }) diff --git a/packages/types/src/model.ts b/packages/types/src/model.ts index 9fbf9e358b..cedf2280b3 100644 --- a/packages/types/src/model.ts +++ b/packages/types/src/model.ts @@ -186,3 +186,18 @@ export type ModelInfo = z.infer export type ModelRecord = Record export type RouterModels = Record + +export const routerModelsMessageTypes = [ + "flushRouterModels", + "requestRouterModels", + "routerModels", + "singleRouterModelFetchResponse", +] as const + +export const routerModelsMessageTypeSchema = z.enum(routerModelsMessageTypes) + +export const RouterModelsMessageType = routerModelsMessageTypeSchema.enum + +export type RouterModelsMessageType = z.infer + +export const allRouterModelsProvider = "all" as const diff --git a/packages/types/src/providers/lm-studio.ts b/packages/types/src/providers/lm-studio.ts index d0df134470..5360178840 100644 --- a/packages/types/src/providers/lm-studio.ts +++ b/packages/types/src/providers/lm-studio.ts @@ -1,5 +1,15 @@ +import { z } from "zod" + import type { ModelInfo } from "../model.js" +export const lmStudioModelsMessageTypes = ["requestLmStudioModels", "lmStudioModels"] as const + +export const lmStudioModelsMessageTypeSchema = z.enum(lmStudioModelsMessageTypes) + +export const LmStudioModelsMessageType = lmStudioModelsMessageTypeSchema.enum + +export type LmStudioModelsMessageType = z.infer + export const LMSTUDIO_DEFAULT_TEMPERATURE = 0 // LM Studio diff --git a/packages/types/src/providers/ollama.ts b/packages/types/src/providers/ollama.ts index 160083511f..e97a480b88 100644 --- a/packages/types/src/providers/ollama.ts +++ b/packages/types/src/providers/ollama.ts @@ -1,7 +1,17 @@ +import { z } from "zod" + import type { ModelInfo } from "../model.js" // Ollama // https://ollama.com/models +export const ollamaModelsMessageTypes = ["requestOllamaModels", "ollamaModels"] as const + +export const ollamaModelsMessageTypeSchema = z.enum(ollamaModelsMessageTypes) + +export const OllamaModelsMessageType = ollamaModelsMessageTypeSchema.enum + +export type OllamaModelsMessageType = z.infer + export const ollamaDefaultModelId = "devstral:24b" export const ollamaDefaultModelInfo: ModelInfo = { maxTokens: 4096, diff --git a/packages/types/src/providers/openai.ts b/packages/types/src/providers/openai.ts index b090509bc2..acf5649624 100644 --- a/packages/types/src/providers/openai.ts +++ b/packages/types/src/providers/openai.ts @@ -1,6 +1,16 @@ +import { z } from "zod" + import type { ModelInfo } from "../model.js" // https://openai.com/api/pricing/ +export const openAiModelsMessageTypes = ["requestOpenAiModels", "openAiModels"] as const + +export const openAiModelsMessageTypeSchema = z.enum(openAiModelsMessageTypes) + +export const OpenAiModelsMessageType = openAiModelsMessageTypeSchema.enum + +export type OpenAiModelsMessageType = z.infer + export type OpenAiNativeModelId = keyof typeof openAiNativeModels export const OPENAI_API_PROTOCOL = "openai" diff --git a/packages/types/src/providers/vscode-llm.ts b/packages/types/src/providers/vscode-llm.ts index 5286b0ed28..7069f49f54 100644 --- a/packages/types/src/providers/vscode-llm.ts +++ b/packages/types/src/providers/vscode-llm.ts @@ -1,5 +1,15 @@ +import { z } from "zod" + import type { ModelInfo } from "../model.js" +export const vsCodeLmModelsMessageTypes = ["requestVsCodeLmModels", "vsCodeLmModels"] as const + +export const vsCodeLmModelsMessageTypeSchema = z.enum(vsCodeLmModelsMessageTypes) + +export const VsCodeLmModelsMessageType = vsCodeLmModelsMessageTypeSchema.enum + +export type VsCodeLmModelsMessageType = z.infer + export type VscodeLlmModelId = keyof typeof vscodeLlmModels export const vscodeLlmDefaultModelId: VscodeLlmModelId = "claude-sonnet-4.5" diff --git a/packages/types/src/vscode-extension-host.ts b/packages/types/src/vscode-extension-host.ts index 63d5be87a8..ea52c09599 100644 --- a/packages/types/src/vscode-extension-host.ts +++ b/packages/types/src/vscode-extension-host.ts @@ -12,7 +12,11 @@ import type { CloudUserInfo, CloudOrganizationMembership, OrganizationAllowList, import type { SerializedCustomToolDefinition } from "./custom-tool.js" import type { GitCommit } from "./git.js" import type { McpServer } from "./mcp.js" -import type { ModelRecord, RouterModels } from "./model.js" +import { RouterModelsMessageType, type ModelRecord, type RouterModels } from "./model.js" +import { LmStudioModelsMessageType } from "./providers/lm-studio.js" +import { OllamaModelsMessageType } from "./providers/ollama.js" +import { OpenAiModelsMessageType } from "./providers/openai.js" +import { VsCodeLmModelsMessageType } from "./providers/vscode-llm.js" import type { OpenAiCodexRateLimitInfo } from "./providers/openai-codex-rate-limits.js" import type { SkillMetadata } from "./skills.js" import type { RuleMetadata } from "./rules.js" @@ -38,12 +42,12 @@ export interface ExtensionMessage { | "enhancedPrompt" | "commitSearchResults" | "listApiConfig" - | "routerModels" + | typeof RouterModelsMessageType.routerModels | "zooGatewayCredentialsReady" - | "openAiModels" - | "ollamaModels" - | "lmStudioModels" - | "vsCodeLmModels" + | typeof OpenAiModelsMessageType.openAiModels + | typeof OllamaModelsMessageType.ollamaModels + | typeof LmStudioModelsMessageType.lmStudioModels + | typeof VsCodeLmModelsMessageType.vsCodeLmModels | "vsCodeLmApiAvailable" | "updatePrompt" | "systemPrompt" @@ -69,7 +73,7 @@ export interface ExtensionMessage { | "authenticatedUser" | "condenseTaskContextStarted" | "condenseTaskContextResponse" - | "singleRouterModelFetchResponse" + | typeof RouterModelsMessageType.singleRouterModelFetchResponse | "indexingStatusUpdate" | "indexCleared" | "codebaseIndexConfig" @@ -474,13 +478,13 @@ export interface WebviewMessage { | "importSettings" | "exportSettings" | "resetState" - | "flushRouterModels" - | "requestRouterModels" - | "requestOpenAiModels" - | "requestOllamaModels" - | "requestLmStudioModels" + | typeof RouterModelsMessageType.flushRouterModels + | typeof RouterModelsMessageType.requestRouterModels + | typeof OpenAiModelsMessageType.requestOpenAiModels + | typeof OllamaModelsMessageType.requestOllamaModels + | typeof LmStudioModelsMessageType.requestLmStudioModels | "requestRooModels" - | "requestVsCodeLmModels" + | typeof VsCodeLmModelsMessageType.requestVsCodeLmModels | "openImage" | "saveImage" | "openFile" diff --git a/src/api/providers/__tests__/nanogpt.spec.ts b/src/api/providers/__tests__/nanogpt.spec.ts index 878663f1e2..6ac9a17d61 100644 --- a/src/api/providers/__tests__/nanogpt.spec.ts +++ b/src/api/providers/__tests__/nanogpt.spec.ts @@ -5,7 +5,7 @@ vi.mock("vscode", () => ({ import { Anthropic } from "@anthropic-ai/sdk" import OpenAI from "openai" -import { nanoGptDefaultModelId } from "@roo-code/types" +import { nanoGptDefaultModelId, providerIdentifiers } from "@roo-code/types" import { buildApiHandler } from "../../index" import { asyncStreamFrom, collectStream } from "../../../test-utils/stream" @@ -49,7 +49,7 @@ describe("NanoGptHandler", () => { }) it("is constructed by the backend provider registry", () => { - expect(buildApiHandler({ apiProvider: "nanogpt" })).toBeInstanceOf(NanoGptHandler) + expect(buildApiHandler({ apiProvider: providerIdentifiers.nanogpt })).toBeInstanceOf(NanoGptHandler) }) it("keeps the canonical model ID while applying request-only routing", async () => { @@ -187,7 +187,9 @@ describe("NanoGptHandler", () => { vi.mocked(getModels).mockResolvedValue({}) mockCreate.mockResolvedValue(asyncStreamFrom([])) await collectStream(new NanoGptHandler({ nanoGptModelId: "model:thinking" }).createMessage("sys", messages)) - expect(getModels).toHaveBeenLastCalledWith(expect.objectContaining({ provider: "nanogpt", apiKey: undefined })) + expect(getModels).toHaveBeenLastCalledWith( + expect.objectContaining({ provider: providerIdentifiers.nanogpt, apiKey: undefined }), + ) }) it("maps usage with root-field precedence and no reasoning double count", async () => { diff --git a/src/api/providers/nanogpt.ts b/src/api/providers/nanogpt.ts index 73ce199d23..38fb54c384 100644 --- a/src/api/providers/nanogpt.ts +++ b/src/api/providers/nanogpt.ts @@ -6,6 +6,7 @@ import { NANOGPT_BASE_URL, nanoGptDefaultModelId, nanoGptDefaultModelInfo, + providerIdentifiers, type NanoGptRoutingPreference, } from "@roo-code/types" @@ -58,7 +59,7 @@ export class NanoGptHandler extends RouterProvider implements SingleCompletionHa constructor(options: ApiHandlerOptions) { super({ options, - name: "nanogpt", + name: providerIdentifiers.nanogpt, baseURL: NANOGPT_BASE_URL, apiKey: options.nanoGptApiKey, modelId: options.nanoGptModelId, diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index f0fc33501f..e88fd864cd 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -23,6 +23,11 @@ import { checkoutRestorePayloadSchema, getCompletionCheckpoint, providerIdentifiers, + LmStudioModelsMessageType, + OllamaModelsMessageType, + OpenAiModelsMessageType, + RouterModelsMessageType, + VsCodeLmModelsMessageType, } from "@roo-code/types" import { customToolRegistry } from "@roo-code/core" import { CloudService } from "@roo-code/cloud" @@ -1044,13 +1049,13 @@ export const webviewMessageHandler = async ( case "resetState": await provider.resetState() break - case "flushRouterModels": + case RouterModelsMessageType.flushRouterModels: const routerNameFlush: RouterName = toRouterName(message.text) // Note: flushRouterModels is a generic flush without credentials // For providers that need credentials, use their specific handlers await flushModels({ provider: routerNameFlush } as GetModelsOptions, true) break - case "requestRouterModels": { + case RouterModelsMessageType.requestRouterModels: { const { apiConfiguration } = await provider.getState() // Optional single provider filter from webview @@ -1225,12 +1230,12 @@ export const webviewMessageHandler = async ( // same key-scoped options for refresh and retrieval. const nanoGptApiKey = message?.values?.nanoGptApiKey ?? apiConfiguration.nanoGptApiKey if (message?.values?.nanoGptApiKey !== undefined) { - await flushModels({ provider: "nanogpt", apiKey: nanoGptApiKey }, true) + await flushModels({ provider: providerIdentifiers.nanogpt, apiKey: nanoGptApiKey }, true) } candidates.push({ - key: "nanogpt", - options: { provider: "nanogpt", apiKey: nanoGptApiKey }, + key: providerIdentifiers.nanogpt, + options: { provider: providerIdentifiers.nanogpt, apiKey: nanoGptApiKey }, }) if (!providerFilter || providerFilter === "kimi-code") { @@ -1282,7 +1287,7 @@ export const webviewMessageHandler = async ( routerModels[routerName] = {} // Ensure it's an empty object in the main routerModels message. void provider.postMessageToWebview({ - type: "singleRouterModelFetchResponse", + type: RouterModelsMessageType.singleRouterModelFetchResponse, success: false, error: errorMessage, values: { provider: routerName }, @@ -1291,13 +1296,13 @@ export const webviewMessageHandler = async ( }) await provider.postMessageToWebview({ - type: "routerModels", + type: RouterModelsMessageType.routerModels, routerModels, values: providerFilter ? { provider: requestedProvider } : undefined, }) break } - case "requestOllamaModels": { + case OllamaModelsMessageType.requestOllamaModels: { // Specific handler for Ollama models only. const { apiConfiguration: ollamaApiConfig } = await provider.getState() // Prefer the baseUrl/apiKey from the message values (which reflect @@ -1321,7 +1326,7 @@ export const webviewMessageHandler = async ( const errorMsg = error instanceof Error ? error.message : String(error) provider.log(`[requestOllamaModels] Failed to refresh model cache for ${logBaseUrl}: ${errorMsg}`) await provider.postMessageToWebview({ - type: "ollamaModels", + type: OllamaModelsMessageType.ollamaModels, ollamaModels: {}, error: errorMsg, }) @@ -1333,19 +1338,19 @@ export const webviewMessageHandler = async ( // Always post a response so the webview refresh status can // transition out of "loading" — even when no models are found. - await provider.postMessageToWebview({ type: "ollamaModels", ollamaModels }) + await provider.postMessageToWebview({ type: OllamaModelsMessageType.ollamaModels, ollamaModels }) } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error) provider.log(`[requestOllamaModels] Failed to read models for ${logBaseUrl}: ${errorMsg}`) await provider.postMessageToWebview({ - type: "ollamaModels", + type: OllamaModelsMessageType.ollamaModels, ollamaModels: {}, error: errorMsg, }) } break } - case "requestLmStudioModels": { + case LmStudioModelsMessageType.requestLmStudioModels: { // Specific handler for LM Studio models only. const { apiConfiguration: lmStudioApiConfig } = await provider.getState() try { @@ -1366,7 +1371,7 @@ export const webviewMessageHandler = async ( if (Object.keys(lmStudioModels).length > 0) { await provider.postMessageToWebview({ - type: "lmStudioModels", + type: LmStudioModelsMessageType.lmStudioModels, lmStudioModels: lmStudioModels, }) } @@ -1378,14 +1383,14 @@ export const webviewMessageHandler = async ( } case "requestRooModels": { await provider.postMessageToWebview({ - type: "singleRouterModelFetchResponse", + type: RouterModelsMessageType.singleRouterModelFetchResponse, success: false, error: getRouterRemovalMessage(), values: { provider: "roo" }, }) break } - case "requestOpenAiModels": + case OpenAiModelsMessageType.requestOpenAiModels: if (message?.values?.baseUrl && message?.values?.apiKey) { const openAiModels = await getOpenAiModels( message?.values?.baseUrl, @@ -1393,14 +1398,14 @@ export const webviewMessageHandler = async ( message?.values?.openAiHeaders, ) - await provider.postMessageToWebview({ type: "openAiModels", openAiModels }) + await provider.postMessageToWebview({ type: OpenAiModelsMessageType.openAiModels, openAiModels }) } break - case "requestVsCodeLmModels": + case VsCodeLmModelsMessageType.requestVsCodeLmModels: const vsCodeLmModels = await getVsCodeLmModels() // TODO: Cache like we do for OpenRouter, etc? - await provider.postMessageToWebview({ type: "vsCodeLmModels", vsCodeLmModels }) + await provider.postMessageToWebview({ type: VsCodeLmModelsMessageType.vsCodeLmModels, vsCodeLmModels }) break case "openImage": await openImage(message.text!, { values: message.values }) diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx index f3375abfaf..3e1495baff 100644 --- a/webview-ui/src/components/settings/ApiOptions.tsx +++ b/webview-ui/src/components/settings/ApiOptions.tsx @@ -10,6 +10,10 @@ import { isRetiredProvider, providerIdentifiers, DEFAULT_CONSECUTIVE_MISTAKE_LIMIT, + OllamaModelsMessageType, + OpenAiModelsMessageType, + RouterModelsMessageType, + VsCodeLmModelsMessageType, } from "@roo-code/types" import { @@ -214,7 +218,7 @@ const ApiOptions = ({ const headerObject = convertHeadersToObject(customHeaders) vscode.postMessage({ - type: "requestOpenAiModels", + type: OpenAiModelsMessageType.requestOpenAiModels, values: { baseUrl: apiConfiguration?.openAiBaseUrl, apiKey: apiConfiguration?.openAiApiKey, @@ -224,7 +228,7 @@ const ApiOptions = ({ }) } else if (selectedProvider === providerIdentifiers.ollama) { vscode.postMessage({ - type: "requestOllamaModels", + type: OllamaModelsMessageType.requestOllamaModels, values: { baseUrl: apiConfiguration?.ollamaBaseUrl, apiKey: apiConfiguration?.ollamaApiKey, @@ -233,17 +237,17 @@ const ApiOptions = ({ } else if (selectedProvider === providerIdentifiers.lmstudio) { requestLmStudioModels(apiConfiguration?.lmStudioBaseUrl) } else if (selectedProvider === providerIdentifiers.vscodeLm) { - vscode.postMessage({ type: "requestVsCodeLmModels" }) + vscode.postMessage({ type: VsCodeLmModelsMessageType.requestVsCodeLmModels }) } else if (selectedProvider === providerIdentifiers.litellm) { vscode.postMessage({ - type: "requestRouterModels", + type: RouterModelsMessageType.requestRouterModels, values: { litellmApiKey: apiConfiguration?.litellmApiKey, litellmBaseUrl: apiConfiguration?.litellmBaseUrl, }, }) } else if (selectedProvider === providerIdentifiers.poe) { - vscode.postMessage({ type: "requestRouterModels" }) + vscode.postMessage({ type: RouterModelsMessageType.requestRouterModels }) } }, 250, diff --git a/webview-ui/src/components/settings/providers/Kenari.tsx b/webview-ui/src/components/settings/providers/Kenari.tsx index 577a44ac71..e8d2f5cdb9 100644 --- a/webview-ui/src/components/settings/providers/Kenari.tsx +++ b/webview-ui/src/components/settings/providers/Kenari.tsx @@ -6,6 +6,7 @@ import { type OrganizationAllowList, type RouterModels, kenariDefaultModelId, + providerIdentifiers, } from "@roo-code/types" import { useAppTranslation } from "@src/i18n/TranslationContext" @@ -69,7 +70,7 @@ export const Kenari = ({ apiConfiguration={apiConfiguration} setApiConfigurationField={setApiConfigurationField} defaultModelId={kenariDefaultModelId} - models={routerModels?.["kenari"] ?? {}} + models={routerModels?.[providerIdentifiers.kenari] ?? {}} modelIdKey="kenariModelId" serviceName="Kenari" serviceUrl="https://kenari.id/docs" diff --git a/webview-ui/src/components/settings/providers/KimiCode.tsx b/webview-ui/src/components/settings/providers/KimiCode.tsx index 4e9d3ff561..a0350c9471 100644 --- a/webview-ui/src/components/settings/providers/KimiCode.tsx +++ b/webview-ui/src/components/settings/providers/KimiCode.tsx @@ -7,6 +7,8 @@ import { type KimiCodeAuthMethod, type ModelRecord, type ProviderSettings, + providerIdentifiers, + RouterModelsMessageType, } from "@roo-code/types" import { useAppTranslation } from "@src/i18n/TranslationContext" @@ -37,10 +39,10 @@ export const KimiCode = ({ const { t } = useAppTranslation() const authMethod = apiConfiguration.kimiCodeAuthMethod ?? "oauth" const { data, refetch, isFetching } = useRouterModels({ - provider: "kimi-code", + provider: providerIdentifiers.kimiCode, enabled: authMethod === "oauth" ? kimiCodeIsAuthenticated : !!apiConfiguration.kimiCodeApiKey, }) - const discoveredModels = data?.["kimi-code"] + const discoveredModels = data?.[providerIdentifiers.kimiCode] const models: ModelRecord = discoveredModels && Object.keys(discoveredModels).length > 0 ? discoveredModels : kimiCodeModels @@ -50,9 +52,9 @@ export const KimiCode = ({ const refreshModels = () => { vscode.postMessage({ - type: "requestRouterModels", + type: RouterModelsMessageType.requestRouterModels, values: { - provider: "kimi-code", + provider: providerIdentifiers.kimiCode, refresh: true, kimiCodeAuthMethod: authMethod, kimiCodeApiKey: apiConfiguration.kimiCodeApiKey, diff --git a/webview-ui/src/components/settings/providers/LMStudio.tsx b/webview-ui/src/components/settings/providers/LMStudio.tsx index 786c3f4474..64c12606c1 100644 --- a/webview-ui/src/components/settings/providers/LMStudio.tsx +++ b/webview-ui/src/components/settings/providers/LMStudio.tsx @@ -4,7 +4,12 @@ import { Trans } from "react-i18next" import { Checkbox } from "vscrui" import { VSCodeLink, VSCodeTextField } from "@vscode/webview-ui-toolkit/react" -import type { ProviderSettings, ExtensionMessage, ModelRecord } from "@roo-code/types" +import { + type ProviderSettings, + type ExtensionMessage, + type ModelRecord, + LmStudioModelsMessageType, +} from "@roo-code/types" import { useAppTranslation } from "@src/i18n/TranslationContext" import { requestLmStudioModels } from "@src/components/ui/hooks/useLmStudioModels" @@ -40,7 +45,7 @@ export const LMStudio = ({ apiConfiguration, setApiConfigurationField }: LMStudi const message: ExtensionMessage = event.data switch (message.type) { - case "lmStudioModels": + case LmStudioModelsMessageType.lmStudioModels: { const newModels = message.lmStudioModels ?? {} setLmStudioModels(newModels) diff --git a/webview-ui/src/components/settings/providers/LiteLLM.tsx b/webview-ui/src/components/settings/providers/LiteLLM.tsx index 2a8dcb8d67..5f3b7dc27b 100644 --- a/webview-ui/src/components/settings/providers/LiteLLM.tsx +++ b/webview-ui/src/components/settings/providers/LiteLLM.tsx @@ -7,6 +7,9 @@ import { type OrganizationAllowList, type ExtensionMessage, litellmDefaultModelId, + providerIdentifiers, + allRouterModelsProvider, + RouterModelsMessageType, } from "@roo-code/types" import { RouterName } from "@roo/api" @@ -27,6 +30,13 @@ type LiteLLMProps = { simplifySettings?: boolean } +enum RefreshStatus { + Idle = "idle", + Loading = "loading", + Success = "success", + Error = "error", +} + export const LiteLLM = ({ apiConfiguration, setApiConfigurationField, @@ -37,32 +47,35 @@ export const LiteLLM = ({ const { t } = useAppTranslation() const queryClient = useQueryClient() const { routerModels } = useExtensionState() - const [refreshStatus, setRefreshStatus] = useState<"idle" | "loading" | "success" | "error">("idle") + const [refreshStatus, setRefreshStatus] = useState(RefreshStatus.Idle) const [refreshError, setRefreshError] = useState() const litellmErrorJustReceived = useRef(false) useEffect(() => { const handleMessage = (event: MessageEvent) => { const message = event.data - if (message.type === "singleRouterModelFetchResponse" && !message.success) { + if (message.type === RouterModelsMessageType.singleRouterModelFetchResponse && !message.success) { const providerName = message.values?.provider as RouterName - if (providerName === "litellm") { + if (providerName === providerIdentifiers.litellm) { litellmErrorJustReceived.current = true - setRefreshStatus("error") + setRefreshStatus(RefreshStatus.Error) setRefreshError(message.error) } - } else if (message.type === "routerModels") { + } else if (message.type === RouterModelsMessageType.routerModels) { // If we were loading and no specific error for litellm was just received, mark as success. // The ModelPicker will show available models or "no models found". - if (refreshStatus === "loading") { + if (refreshStatus === RefreshStatus.Loading) { if (!litellmErrorJustReceived.current) { - setRefreshStatus("success") - // Invalidate only the LiteLLM router-models query so useSelectedModel - // picks up the refreshed list. useSelectedModel reads LiteLLM under the - // compound key ["routerModels", "litellm"] (see useRouterModels), so we - // target that exact key rather than the bare ["routerModels"] prefix, - // which would needlessly invalidate every other provider's query too. - queryClient.invalidateQueries({ queryKey: ["routerModels", "litellm"] }) + setRefreshStatus(RefreshStatus.Success) + // Refresh the provider-scoped cache used by useSelectedModel and the shared cache used by + // ApiOptions. Target both exact keys rather than the bare ["routerModels"] prefix, which + // would needlessly invalidate every other provider's query too. + void queryClient.invalidateQueries({ + queryKey: [RouterModelsMessageType.routerModels, providerIdentifiers.litellm], + }) + void queryClient.invalidateQueries({ + queryKey: [RouterModelsMessageType.routerModels, allRouterModelsProvider], + }) } // If litellmErrorJustReceived.current is true, status is already (or will be) "error". } @@ -88,19 +101,22 @@ export const LiteLLM = ({ const handleRefreshModels = useCallback(() => { litellmErrorJustReceived.current = false // Reset flag on new refresh action - setRefreshStatus("loading") + setRefreshStatus(RefreshStatus.Loading) setRefreshError(undefined) const key = apiConfiguration.litellmApiKey const url = apiConfiguration.litellmBaseUrl if (!key || !url) { - setRefreshStatus("error") + setRefreshStatus(RefreshStatus.Error) setRefreshError(t("settings:providers.refreshModels.missingConfig")) return } - vscode.postMessage({ type: "requestRouterModels", values: { litellmApiKey: key, litellmBaseUrl: url } }) + vscode.postMessage({ + type: RouterModelsMessageType.requestRouterModels, + values: { litellmApiKey: key, litellmBaseUrl: url }, + }) }, [apiConfiguration, setRefreshStatus, setRefreshError, t]) return ( @@ -130,11 +146,13 @@ export const LiteLLM = ({ variant="outline" onClick={handleRefreshModels} disabled={ - refreshStatus === "loading" || !apiConfiguration.litellmApiKey || !apiConfiguration.litellmBaseUrl + refreshStatus === RefreshStatus.Loading || + !apiConfiguration.litellmApiKey || + !apiConfiguration.litellmBaseUrl } className="w-full">
- {refreshStatus === "loading" ? ( + {refreshStatus === RefreshStatus.Loading ? ( ) : ( @@ -142,15 +160,15 @@ export const LiteLLM = ({ {t("settings:providers.refreshModels.label")}
- {refreshStatus === "loading" && ( + {refreshStatus === RefreshStatus.Loading && (
{t("settings:providers.refreshModels.loading")}
)} - {refreshStatus === "success" && ( + {refreshStatus === RefreshStatus.Success && (
{t("settings:providers.refreshModels.success")}
)} - {refreshStatus === "error" && ( + {refreshStatus === RefreshStatus.Error && (
{refreshError || t("settings:providers.refreshModels.error")}
diff --git a/webview-ui/src/components/settings/providers/Moonshot.tsx b/webview-ui/src/components/settings/providers/Moonshot.tsx index 2d6c7d849a..ed561f2b9f 100644 --- a/webview-ui/src/components/settings/providers/Moonshot.tsx +++ b/webview-ui/src/components/settings/providers/Moonshot.tsx @@ -2,8 +2,14 @@ import { useCallback, useState, useEffect, useRef } from "react" import { VSCodeTextField, VSCodeDropdown, VSCodeOption } from "@vscode/webview-ui-toolkit/react" import { useQueryClient } from "@tanstack/react-query" -import type { ProviderSettings, ExtensionMessage } from "@roo-code/types" -import { moonshotDefaultModelId } from "@roo-code/types" +import { + type ProviderSettings, + type ExtensionMessage, + moonshotDefaultModelId, + providerIdentifiers, + allRouterModelsProvider, + RouterModelsMessageType, +} from "@roo-code/types" import { RouterName } from "@roo/api" @@ -14,7 +20,6 @@ import { vscode } from "@src/utils/vscode" import { Button } from "@src/components/ui" import { ModelPicker } from "../ModelPicker" import { handleModelChangeSideEffects } from "../utils/providerModelConfig" -import type { ProviderName } from "@roo-code/types" import { inputEventTransform } from "../transforms" @@ -24,29 +29,41 @@ type MoonshotProps = { simplifySettings?: boolean } +enum RefreshStatus { + Idle = "idle", + Loading = "loading", + Success = "success", + Error = "error", +} + export const Moonshot = ({ apiConfiguration, setApiConfigurationField, simplifySettings }: MoonshotProps) => { const { t } = useAppTranslation() const { routerModels } = useExtensionState() const queryClient = useQueryClient() - const [refreshStatus, setRefreshStatus] = useState<"idle" | "loading" | "success" | "error">("idle") + const [refreshStatus, setRefreshStatus] = useState(RefreshStatus.Idle) const [refreshError, setRefreshError] = useState() const moonshotErrorJustReceived = useRef(false) useEffect(() => { const handleMessage = (event: MessageEvent) => { const message = event.data - if (message.type === "singleRouterModelFetchResponse" && !message.success) { + if (message.type === RouterModelsMessageType.singleRouterModelFetchResponse && !message.success) { const providerName = message.values?.provider as RouterName - if (providerName === "moonshot" && refreshStatus === "loading") { + if (providerName === providerIdentifiers.moonshot && refreshStatus === RefreshStatus.Loading) { moonshotErrorJustReceived.current = true - setRefreshStatus("error") + setRefreshStatus(RefreshStatus.Error) setRefreshError(message.error) } - } else if (message.type === "routerModels") { - if (refreshStatus === "loading") { + } else if (message.type === RouterModelsMessageType.routerModels) { + if (refreshStatus === RefreshStatus.Loading) { if (!moonshotErrorJustReceived.current) { - setRefreshStatus("success") - queryClient.invalidateQueries({ queryKey: ["routerModels"] }) + setRefreshStatus(RefreshStatus.Success) + void queryClient.invalidateQueries({ + queryKey: [RouterModelsMessageType.routerModels, providerIdentifiers.moonshot], + }) + void queryClient.invalidateQueries({ + queryKey: [RouterModelsMessageType.routerModels, allRouterModelsProvider], + }) } } } @@ -71,19 +88,19 @@ export const Moonshot = ({ apiConfiguration, setApiConfigurationField, simplifyS const handleRefreshModels = useCallback(() => { moonshotErrorJustReceived.current = false - setRefreshStatus("loading") + setRefreshStatus(RefreshStatus.Loading) setRefreshError(undefined) const key = apiConfiguration.moonshotApiKey if (!key) { - setRefreshStatus("error") + setRefreshStatus(RefreshStatus.Error) setRefreshError(t("settings:providers.refreshModels.missingConfig")) return } vscode.postMessage({ - type: "requestRouterModels", + type: RouterModelsMessageType.requestRouterModels, values: { moonshotApiKey: key, moonshotBaseUrl: apiConfiguration.moonshotBaseUrl }, }) }, [apiConfiguration, t]) @@ -138,15 +155,15 @@ export const Moonshot = ({ apiConfiguration, setApiConfigurationField, simplifyS serviceUrl="https://platform.moonshot.ai" simplifySettings={simplifySettings} onModelChange={(modelId) => - handleModelChangeSideEffects("moonshot" as ProviderName, modelId, setApiConfigurationField) + handleModelChangeSideEffects(providerIdentifiers.moonshot, modelId, setApiConfigurationField) } /> - {refreshStatus === "loading" && ( + {refreshStatus === RefreshStatus.Loading && (
{t("settings:providers.refreshModels.loading")}
)} - {refreshStatus === "success" && ( + {refreshStatus === RefreshStatus.Success && (
{t("settings:providers.refreshModels.success")}
)} - {refreshStatus === "error" && ( + {refreshStatus === RefreshStatus.Error && (
{refreshError || t("settings:providers.refreshModels.error")}
diff --git a/webview-ui/src/components/settings/providers/NanoGPT.tsx b/webview-ui/src/components/settings/providers/NanoGPT.tsx index cc7b7a431f..11e0005604 100644 --- a/webview-ui/src/components/settings/providers/NanoGPT.tsx +++ b/webview-ui/src/components/settings/providers/NanoGPT.tsx @@ -9,6 +9,8 @@ import { nanoGptDefaultModelId, nanoGptDefaultRoutingPreference, nanoGptRoutingPreferences, + providerIdentifiers, + RouterModelsMessageType, } from "@roo-code/types" import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink" @@ -62,9 +64,9 @@ export const NanoGPT = ({ useEffect(() => { vscode.postMessage({ - type: "requestRouterModels", + type: RouterModelsMessageType.requestRouterModels, values: { - provider: "nanogpt", + provider: providerIdentifiers.nanogpt, nanoGptApiKey: apiConfiguration.nanoGptApiKey, }, }) @@ -93,7 +95,7 @@ export const NanoGPT = ({ apiConfiguration={apiConfiguration} setApiConfigurationField={setApiConfigurationField} defaultModelId={nanoGptDefaultModelId} - models={routerModels?.nanogpt ?? {}} + models={routerModels?.[providerIdentifiers.nanogpt] ?? {}} modelIdKey="nanoGptModelId" serviceName={t("settings:providers.nanoGpt.provider")} serviceUrl="https://nano-gpt.com/api" diff --git a/webview-ui/src/components/settings/providers/Ollama.tsx b/webview-ui/src/components/settings/providers/Ollama.tsx index 9b11c85369..8d1e7348f4 100644 --- a/webview-ui/src/components/settings/providers/Ollama.tsx +++ b/webview-ui/src/components/settings/providers/Ollama.tsx @@ -2,7 +2,13 @@ import { useState, useCallback, useMemo, useEffect, useRef } from "react" import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react" import { Checkbox } from "vscrui" -import { type ProviderSettings, type ExtensionMessage, type ModelRecord, ollamaDefaultModelInfo } from "@roo-code/types" +import { + type ProviderSettings, + type ExtensionMessage, + type ModelRecord, + ollamaDefaultModelInfo, + OllamaModelsMessageType, +} from "@roo-code/types" import { useAppTranslation } from "@src/i18n/TranslationContext" import { useRouterModels } from "@src/components/ui/hooks/useRouterModels" @@ -18,11 +24,18 @@ type OllamaProps = { setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void } +enum RefreshStatus { + Idle = "idle", + Loading = "loading", + Success = "success", + Error = "error", +} + export const Ollama = ({ apiConfiguration, setApiConfigurationField }: OllamaProps) => { const { t } = useAppTranslation() const [ollamaModels, setOllamaModels] = useState({}) - const [refreshStatus, setRefreshStatus] = useState<"idle" | "loading" | "success" | "error">("idle") + const [refreshStatus, setRefreshStatus] = useState(RefreshStatus.Idle) const [refreshError, setRefreshError] = useState() const refreshStatusRef = useRef(refreshStatus) const routerModels = useRouterModels() @@ -42,13 +55,13 @@ export const Ollama = ({ apiConfiguration, setApiConfigurationField }: OllamaPro const handleMessage = (event: MessageEvent) => { const message: ExtensionMessage = event.data - if (message.type === "ollamaModels") { + if (message.type === OllamaModelsMessageType.ollamaModels) { if (!message.error) { setOllamaModels(message.ollamaModels ?? {}) } - if (refreshStatusRef.current === "loading") { - const nextStatus = message.error ? "error" : "success" + if (refreshStatusRef.current === RefreshStatus.Loading) { + const nextStatus = message.error ? RefreshStatus.Error : RefreshStatus.Success refreshStatusRef.current = nextStatus setRefreshStatus(nextStatus) setRefreshError(message.error) @@ -63,11 +76,11 @@ export const Ollama = ({ apiConfiguration, setApiConfigurationField }: OllamaPro }, []) const handleRefreshModels = useCallback(() => { - refreshStatusRef.current = "loading" - setRefreshStatus("loading") + refreshStatusRef.current = RefreshStatus.Loading + setRefreshStatus(RefreshStatus.Loading) setRefreshError(undefined) vscode.postMessage({ - type: "requestOllamaModels", + type: OllamaModelsMessageType.requestOllamaModels, values: { baseUrl: apiConfiguration?.ollamaBaseUrl, apiKey: apiConfiguration?.ollamaApiKey, @@ -78,7 +91,7 @@ export const Ollama = ({ apiConfiguration, setApiConfigurationField }: OllamaPro // Refresh models on mount useEffect(() => { // Request fresh models - the handler now flushes cache automatically - vscode.postMessage({ type: "requestOllamaModels" }) + vscode.postMessage({ type: OllamaModelsMessageType.requestOllamaModels }) }, []) // Check if the selected model exists in the fetched models @@ -130,10 +143,10 @@ export const Ollama = ({ apiConfiguration, setApiConfigurationField }: OllamaPro - {refreshStatus === "loading" && ( + {refreshStatus === RefreshStatus.Loading && (
{t("settings:providers.refreshModels.loading")}
)} - {refreshStatus === "success" && ( + {refreshStatus === RefreshStatus.Success && (
{t("settings:providers.refreshModels.success")}
)} - {refreshStatus === "error" && ( + {refreshStatus === RefreshStatus.Error && (
{refreshError || t("settings:providers.refreshModels.error")}
diff --git a/webview-ui/src/components/settings/providers/OpenAICompatible.tsx b/webview-ui/src/components/settings/providers/OpenAICompatible.tsx index f9a021812b..7870b21f32 100644 --- a/webview-ui/src/components/settings/providers/OpenAICompatible.tsx +++ b/webview-ui/src/components/settings/providers/OpenAICompatible.tsx @@ -12,6 +12,7 @@ import { azureOpenAiDefaultApiVersion, isAzureOpenAiBaseUrl, openAiModelInfoSaneDefaults, + OpenAiModelsMessageType, } from "@roo-code/types" import { useAppTranslation } from "@src/i18n/TranslationContext" @@ -115,7 +116,7 @@ export const OpenAICompatible = ({ const message: ExtensionMessage = event.data switch (message.type) { - case "openAiModels": { + case OpenAiModelsMessageType.openAiModels: { const updatedModels = message.openAiModels ?? [] setOpenAiModels(Object.fromEntries(updatedModels.map((item) => [item, openAiModelInfoSaneDefaults]))) break diff --git a/webview-ui/src/components/settings/providers/OpenCodeGo.tsx b/webview-ui/src/components/settings/providers/OpenCodeGo.tsx index f004d32f91..249e2de534 100644 --- a/webview-ui/src/components/settings/providers/OpenCodeGo.tsx +++ b/webview-ui/src/components/settings/providers/OpenCodeGo.tsx @@ -7,6 +7,8 @@ import { type RouterModels, type ExtensionMessage, opencodeGoDefaultModelId, + providerIdentifiers, + RouterModelsMessageType, } from "@roo-code/types" import type { RouterName } from "@roo/api" @@ -28,6 +30,13 @@ type OpenCodeGoProps = { simplifySettings?: boolean } +enum RefreshStatus { + Idle = "idle", + Loading = "loading", + Success = "success", + Error = "error", +} + export const OpenCodeGo = ({ apiConfiguration, setApiConfigurationField, @@ -37,24 +46,24 @@ export const OpenCodeGo = ({ simplifySettings, }: OpenCodeGoProps) => { const { t } = useAppTranslation() - const [refreshStatus, setRefreshStatus] = useState<"idle" | "loading" | "success" | "error">("idle") + const [refreshStatus, setRefreshStatus] = useState(RefreshStatus.Idle) const [refreshError, setRefreshError] = useState() const errorJustReceived = useRef(false) useEffect(() => { const handleMessage = (event: MessageEvent) => { const message = event.data - if (message.type === "singleRouterModelFetchResponse" && !message.success) { + if (message.type === RouterModelsMessageType.singleRouterModelFetchResponse && !message.success) { const providerName = message.values?.provider as RouterName - if (providerName === "opencode-go") { + if (providerName === providerIdentifiers.opencodeGo) { errorJustReceived.current = true - setRefreshStatus("error") + setRefreshStatus(RefreshStatus.Error) setRefreshError(message.error) } - } else if (message.type === "routerModels") { - if (refreshStatus === "loading") { + } else if (message.type === RouterModelsMessageType.routerModels) { + if (refreshStatus === RefreshStatus.Loading) { if (!errorJustReceived.current) { - setRefreshStatus("success") + setRefreshStatus(RefreshStatus.Success) } } } @@ -79,11 +88,15 @@ export const OpenCodeGo = ({ const handleRefreshModels = useCallback(() => { errorJustReceived.current = false - setRefreshStatus("loading") + setRefreshStatus(RefreshStatus.Loading) setRefreshError(undefined) vscode.postMessage({ - type: "requestRouterModels", - values: { provider: "opencode-go", refresh: true, opencodeGoApiKey: apiConfiguration.opencodeGoApiKey }, + type: RouterModelsMessageType.requestRouterModels, + values: { + provider: providerIdentifiers.opencodeGo, + refresh: true, + opencodeGoApiKey: apiConfiguration.opencodeGoApiKey, + }, }) }, [apiConfiguration.opencodeGoApiKey]) @@ -108,10 +121,10 @@ export const OpenCodeGo = ({ - {refreshStatus === "loading" && ( + {refreshStatus === RefreshStatus.Loading && (
{t("settings:providers.refreshModels.loading")}
)} - {refreshStatus === "success" && ( + {refreshStatus === RefreshStatus.Success && (
{t("settings:providers.refreshModels.success")}
)} - {refreshStatus === "error" && ( + {refreshStatus === RefreshStatus.Error && (
{refreshError || t("settings:providers.refreshModels.error")}
@@ -136,7 +149,7 @@ export const OpenCodeGo = ({ apiConfiguration={apiConfiguration} setApiConfigurationField={setApiConfigurationField} defaultModelId={opencodeGoDefaultModelId} - models={routerModels?.["opencode-go"] ?? {}} + models={routerModels?.[providerIdentifiers.opencodeGo] ?? {}} modelIdKey="opencodeGoModelId" serviceName="Opencode Go" serviceUrl="https://opencode.ai/docs/go/" diff --git a/webview-ui/src/components/settings/providers/Poe.tsx b/webview-ui/src/components/settings/providers/Poe.tsx index 7b79ed8510..b549b8aae1 100644 --- a/webview-ui/src/components/settings/providers/Poe.tsx +++ b/webview-ui/src/components/settings/providers/Poe.tsx @@ -7,7 +7,9 @@ import { type OrganizationAllowList, type ExtensionMessage, poeDefaultModelId, - type ProviderName, + providerIdentifiers, + allRouterModelsProvider, + RouterModelsMessageType, } from "@roo-code/types" import { RouterName } from "@roo/api" @@ -30,6 +32,13 @@ type PoeProps = { simplifySettings?: boolean } +enum RefreshStatus { + Idle = "idle", + Loading = "loading", + Success = "success", + Error = "error", +} + export const Poe = ({ apiConfiguration, setApiConfigurationField, @@ -40,27 +49,32 @@ export const Poe = ({ const { t } = useAppTranslation() const queryClient = useQueryClient() const { routerModels } = useExtensionState() - const [refreshStatus, setRefreshStatus] = useState<"idle" | "loading" | "success" | "error">("idle") + const [refreshStatus, setRefreshStatus] = useState(RefreshStatus.Idle) const [refreshError, setRefreshError] = useState() const poeErrorJustReceived = useRef(false) useEffect(() => { const handleMessage = (event: MessageEvent) => { const message = event.data - if (message.type === "singleRouterModelFetchResponse" && !message.success) { + if (message.type === RouterModelsMessageType.singleRouterModelFetchResponse && !message.success) { const providerName = message.values?.provider as RouterName - if (providerName === "poe") { + if (providerName === providerIdentifiers.poe) { poeErrorJustReceived.current = true - setRefreshStatus("error") + setRefreshStatus(RefreshStatus.Error) setRefreshError(message.error) } - } else if (message.type === "routerModels") { - if (refreshStatus === "loading") { + } else if (message.type === RouterModelsMessageType.routerModels) { + if (refreshStatus === RefreshStatus.Loading) { if (!poeErrorJustReceived.current) { - setRefreshStatus("success") - // Invalidate the react-query router models cache so - // validation in ApiOptions picks up the refreshed list. - queryClient.invalidateQueries({ queryKey: ["routerModels"] }) + setRefreshStatus(RefreshStatus.Success) + // Refresh the provider-scoped cache used by useSelectedModel and the shared cache used by + // ApiOptions without invalidating every other provider's query. + void queryClient.invalidateQueries({ + queryKey: [RouterModelsMessageType.routerModels, providerIdentifiers.poe], + }) + void queryClient.invalidateQueries({ + queryKey: [RouterModelsMessageType.routerModels, allRouterModelsProvider], + }) } } } @@ -85,19 +99,19 @@ export const Poe = ({ const handleRefreshModels = useCallback(() => { poeErrorJustReceived.current = false - setRefreshStatus("loading") + setRefreshStatus(RefreshStatus.Loading) setRefreshError(undefined) const key = apiConfiguration.poeApiKey if (!key) { - setRefreshStatus("error") + setRefreshStatus(RefreshStatus.Error) setRefreshError(t("settings:providers.refreshModels.missingConfig")) return } vscode.postMessage({ - type: "requestRouterModels", + type: RouterModelsMessageType.requestRouterModels, values: { poeApiKey: key, poeBaseUrl: apiConfiguration.poeBaseUrl }, }) }, [apiConfiguration, t]) @@ -123,9 +137,9 @@ export const Poe = ({ - {refreshStatus === "loading" && ( + {refreshStatus === RefreshStatus.Loading && (
{t("settings:providers.refreshModels.loading")}
)} - {refreshStatus === "success" && ( + {refreshStatus === RefreshStatus.Success && (
{t("settings:providers.refreshModels.success")}
)} - {refreshStatus === "error" && ( + {refreshStatus === RefreshStatus.Error && (
{refreshError || t("settings:providers.refreshModels.error")}
@@ -158,7 +172,7 @@ export const Poe = ({ errorMessage={modelValidationError} simplifySettings={simplifySettings} onModelChange={(modelId) => - handleModelChangeSideEffects("poe" as ProviderName, modelId, setApiConfigurationField) + handleModelChangeSideEffects(providerIdentifiers.poe, modelId, setApiConfigurationField) } /> diff --git a/webview-ui/src/components/settings/providers/Requesty.tsx b/webview-ui/src/components/settings/providers/Requesty.tsx index ba24a6aafb..4149dbc2c8 100644 --- a/webview-ui/src/components/settings/providers/Requesty.tsx +++ b/webview-ui/src/components/settings/providers/Requesty.tsx @@ -6,6 +6,8 @@ import { type OrganizationAllowList, type RouterModels, requestyDefaultModelId, + providerIdentifiers, + RouterModelsMessageType, } from "@roo-code/types" import { vscode } from "@src/utils/vscode" @@ -59,7 +61,7 @@ export const Requesty = ({ ) const getApiKeyUrl = () => { - const callbackUrl = getCallbackUrl("requesty", uriScheme) + const callbackUrl = getCallbackUrl(providerIdentifiers.requesty, uriScheme) const baseUrl = toRequestyServiceUrl(apiConfiguration.requestyBaseUrl, "app") const authUrl = new URL(`oauth/authorize?callback_url=${callbackUrl}`, baseUrl) @@ -129,7 +131,10 @@ export const Requesty = ({ + ), +})) + +vi.mock("../../ModelPicker", () => ({ + ModelPicker: () =>
- {/* Delete confirmation dialog */} - {deleteId && ( -
-
e.stopPropagation()}> -
- Are you sure you want to delete this todo item? -
-
- - -
-
-
- )} + + + Delete todo item + Are you sure you want to delete this todo item? + + + Cancel + + + Delete + + + + ) } diff --git a/webview-ui/src/components/chat/__tests__/AutoApproveDropdown.spec.tsx b/webview-ui/src/components/chat/__tests__/AutoApproveDropdown.spec.tsx new file mode 100644 index 0000000000..113a088138 --- /dev/null +++ b/webview-ui/src/components/chat/__tests__/AutoApproveDropdown.spec.tsx @@ -0,0 +1,58 @@ +import { render, screen } from "@/utils/test-utils" +import { describe, expect, test, vi } from "vitest" + +import { AutoApproveDropdown } from "../AutoApproveDropdown" + +vi.mock("@/utils/vscode", () => ({ vscode: { postMessage: vi.fn() } })) + +vi.mock("@/context/ExtensionStateContext", () => ({ + useExtensionState: () => ({ + autoApprovalEnabled: false, + setAutoApprovalEnabled: vi.fn(), + setAlwaysAllowReadOnly: vi.fn(), + setAlwaysAllowWrite: vi.fn(), + setAlwaysAllowExecute: vi.fn(), + setAlwaysAllowMcp: vi.fn(), + setAlwaysAllowModeSwitch: vi.fn(), + setAlwaysAllowSubtasks: vi.fn(), + setAlwaysAllowFollowupQuestions: vi.fn(), + }), +})) + +vi.mock("@/i18n/TranslationContext", () => ({ + useAppTranslation: () => ({ t: (key: string) => key }), +})) + +vi.mock("@/hooks/useAutoApprovalToggles", () => ({ + useAutoApprovalToggles: () => ({ + alwaysAllowReadOnly: false, + alwaysAllowWrite: false, + alwaysAllowExecute: false, + alwaysAllowMcp: false, + alwaysAllowModeSwitch: false, + alwaysAllowSubtasks: false, + alwaysAllowFollowupQuestions: false, + }), +})) + +vi.mock("@/hooks/useAutoApprovalState", () => ({ + useAutoApprovalState: () => ({ effectiveAutoApprovalEnabled: false }), +})) + +vi.mock("@/components/ui/hooks/useRooPortal", () => ({ + useRooPortal: () => document.body, +})) + +describe("AutoApproveDropdown", () => { + test("enables the trigger by default", () => { + render() + + expect(screen.getByTestId("auto-approve-dropdown-trigger")).toBeEnabled() + }) + + test("disables the trigger when auto-approval controls are unavailable", () => { + render() + + expect(screen.getByTestId("auto-approve-dropdown-trigger")).toBeDisabled() + }) +}) diff --git a/webview-ui/src/components/chat/__tests__/ModeSelector.spec.tsx b/webview-ui/src/components/chat/__tests__/ModeSelector.spec.tsx index 6393021e62..ac8c324efd 100644 --- a/webview-ui/src/components/chat/__tests__/ModeSelector.spec.tsx +++ b/webview-ui/src/components/chat/__tests__/ModeSelector.spec.tsx @@ -76,6 +76,20 @@ describe("ModeSelector", () => { expect(screen.getByTestId("mode-selector-trigger")).toBeInTheDocument() }) + test("disables the trigger when mode selection is unavailable", () => { + render( + , + ) + + expect(screen.getByTestId("mode-selector-trigger")).toBeDisabled() + }) + test("shows search bar when there are more than 6 modes", () => { mockModes = Array.from({ length: 7 }, (_, i) => ({ slug: `mode-${i}`, diff --git a/webview-ui/src/components/chat/__tests__/ThemeAwareControls.visual.tsx b/webview-ui/src/components/chat/__tests__/ThemeAwareControls.visual.tsx new file mode 100644 index 0000000000..540317a958 --- /dev/null +++ b/webview-ui/src/components/chat/__tests__/ThemeAwareControls.visual.tsx @@ -0,0 +1,90 @@ +import React from "react" + +import { expect, test } from "../../../../playwright/coverage-fixture" +import UpdateTodoListToolBlock from "../UpdateTodoListToolBlock" +import { SelectDropdown } from "@/components/ui/select-dropdown" + +const themes = [ + { + name: "dark", + bodyClass: "vscode-dark", + themeId: "Default Dark Modern", + expected: { + background: "rgb(30, 30, 30)", + description: "rgb(157, 157, 157)", + dropdownBorder: "rgb(60, 60, 60)", + hoverBackground: "rgb(42, 45, 46)", + focusBorder: "rgb(0, 127, 212)", + error: "rgb(244, 135, 113)", + panelBorder: "rgb(43, 43, 43)", + }, + }, + { + name: "light", + bodyClass: "vscode-light", + themeId: "Default Light Modern", + expected: { + background: "rgb(255, 255, 255)", + description: "rgb(113, 113, 113)", + dropdownBorder: "rgb(206, 206, 206)", + hoverBackground: "rgb(232, 232, 232)", + focusBorder: "rgb(0, 144, 241)", + error: "rgb(161, 38, 13)", + panelBorder: "rgb(206, 206, 206)", + }, + }, +] as const + +for (const theme of themes) { + test(`renders selectors and confirmation dialogs in the VS Code ${theme.name} theme`, async ({ mount, page }) => { + await page.evaluate(({ bodyClass, themeId }) => { + document.documentElement.className = bodyClass + document.body.className = bodyClass + document.body.dataset.vscodeThemeId = themeId + }, theme) + + const component = await mount( +
+ undefined} /> + undefined} + /> +
, + ) + + await component.evaluate(async () => { + await document.fonts.ready + await new Promise((resolve) => requestAnimationFrame(() => resolve())) + }) + + await expect(component).toHaveScreenshot(`chat-controls-resting-${theme.name}.png`) + + const trigger = component.getByTestId("dropdown-trigger") + await expect(trigger).toHaveCSS("border-color", theme.expected.dropdownBorder) + await trigger.hover() + await expect(trigger).toHaveCSS("background-color", theme.expected.hoverBackground) + await expect(trigger).toHaveCSS("border-color", theme.expected.focusBorder) + await page.keyboard.press("Tab") + await expect(trigger).toBeFocused() + await expect + .poll(() => trigger.evaluate((element) => getComputedStyle(element).boxShadow)) + .toContain(theme.expected.focusBorder) + + await expect(component).toHaveScreenshot(`chat-controls-focus-${theme.name}.png`) + + await component.getByRole("button", { name: "Edit" }).click() + await component.getByTitle("Remove").click() + const dialog = page.getByRole("alertdialog") + await expect(dialog).toBeVisible() + await expect(dialog).toHaveCSS("background-color", theme.expected.background) + await expect(dialog).toHaveCSS("border-color", theme.expected.panelBorder) + await expect(page.getByText("Are you sure you want to delete this todo item?")).toHaveCSS( + "color", + theme.expected.description, + ) + await expect(page.getByRole("button", { name: "Delete" })).toHaveCSS("color", theme.expected.error) + + await expect(dialog).toHaveScreenshot(`chat-controls-delete-dialog-${theme.name}.png`) + }) +} diff --git a/webview-ui/src/components/chat/__tests__/UpdateTodoListToolBlock.spec.tsx b/webview-ui/src/components/chat/__tests__/UpdateTodoListToolBlock.spec.tsx new file mode 100644 index 0000000000..eb7d0ab93c --- /dev/null +++ b/webview-ui/src/components/chat/__tests__/UpdateTodoListToolBlock.spec.tsx @@ -0,0 +1,44 @@ +import { fireEvent, render, screen, waitFor } from "@testing-library/react" +import { beforeEach, describe, expect, it, vi } from "vitest" + +import UpdateTodoListToolBlock from "../UpdateTodoListToolBlock" + +describe("UpdateTodoListToolBlock", () => { + const onChange = vi.fn() + + beforeEach(() => { + vi.clearAllMocks() + }) + + function renderEditableList() { + return render( + , + ) + } + + it("cancels deletion without changing the todo list", async () => { + renderEditableList() + fireEvent.click(screen.getByRole("button", { name: "Edit" })) + fireEvent.click(screen.getByTitle("Remove")) + + expect(screen.getByRole("alertdialog")).toBeInTheDocument() + expect(screen.getByText("Are you sure you want to delete this todo item?")).toBeInTheDocument() + fireEvent.click(screen.getByRole("button", { name: "Cancel" })) + + await waitFor(() => expect(screen.queryByRole("alertdialog")).not.toBeInTheDocument()) + expect(onChange).not.toHaveBeenCalled() + }) + + it("deletes the selected todo after confirmation", async () => { + renderEditableList() + fireEvent.click(screen.getByRole("button", { name: "Edit" })) + fireEvent.click(screen.getByTitle("Remove")) + fireEvent.click(screen.getByRole("button", { name: "Delete" })) + + await waitFor(() => expect(screen.queryByRole("alertdialog")).not.toBeInTheDocument()) + expect(onChange).toHaveBeenCalledWith([]) + }) +}) diff --git a/webview-ui/src/components/chat/__tests__/__screenshots__/chat-controls-delete-dialog-dark.png b/webview-ui/src/components/chat/__tests__/__screenshots__/chat-controls-delete-dialog-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..f4ab51d95c0f2fae3891328c727bfccae0174593 GIT binary patch literal 4945 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 literal 0 HcmV?d00001 diff --git a/webview-ui/src/components/chat/__tests__/__screenshots__/chat-controls-delete-dialog-light.png b/webview-ui/src/components/chat/__tests__/__screenshots__/chat-controls-delete-dialog-light.png new file mode 100644 index 0000000000000000000000000000000000000000..36d78736c02202b6b992e9fcb2869154822e2120 GIT binary patch literal 5113 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 E2Xig90ssI2 literal 0 HcmV?d00001 diff --git a/webview-ui/src/components/chat/__tests__/__screenshots__/chat-controls-focus-dark.png b/webview-ui/src/components/chat/__tests__/__screenshots__/chat-controls-focus-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..420036041cc6969d21de6b469052ef7f590fcc26 GIT binary patch literal 5327 zcmbVQWmJ_>vwjI_IUpTU(kLHl^N0v|=sI+F^Wk0V z-rwK4fA*TS*Iu({X3xx?=LvhK`t~^%ITio_&%p|^8UTRg_axh4AV00y>6#S)fCqqO z-)MQH?=66IH8X+{Y0p$j^`gKY0J?-@)vN z9M}URj}M;_UHs5d%u1#B5IvW9J{U z0B|#{QbHpgkltp|^jCN~qDVZMq!_=IR{7GMD4&D%l&ji&P)OWtGe&on0v)AZ?nO1I(Xczpydtd;Qn~r;u1>V>ONT_ zx5IEr!X|mYUn9AAe+!zIrlqRH$JVydWw_hAlw3NG-}Jeys&;WkdeZMcdFD4wNOXR2 zA;2%VHgi+S$;Eo}$#5Y=Qzu3!N`{%gxM=f7#*xtI?35kX^t@w;^3d6rUx#lZ3pWj7 zp!^wPilgI$x*1ixrYIG1!wDE_lvA&O&Q<{x;73`d1^hVs-CC0x2Av+%JLWsfpz8Oj zOHfqOAhFf=gK^jlMGVV{bKgORCc5#Ra}qidU`H^C)5Z9kX?1n;@7z-5zS_c($%hhv z3%`2L{(iamZ8)#2i#JGdRFyDrM1!BldnR8=T$|_h`>;vnR1ckN_?*%n zeIeMB_<%`!+El5@o|MeF&zT84(eQHEOp$EI%ENm}-y&qbx9Szy(!$vvwPX6)mdATR z3Qka#DN~}@$^C+7WZTl`x;0LG(X(THUr4RhDetv(cI>u@;}+q+uu+~FuswV`J^1u5 zzYur*G8ht=&w)@{3>rXc6i+OMqjv>Ofi}kR6#z6|J1jf2xv4S_B0%o(2eg?&WJo|~ zdgs>w(-6r&eevO_Z?5TLc$B7ZeV@|WuKfWK<4oG|^B!u1Tz#8hjH#eW3HJJJyTW7C z$i@aNe=-4A>G-^TtR8@5_)*>{dp(d^>{W@mJP^>TOUH7Zf#V@7$p4Bl$^q0Dl`K>i zV=XuYdq7eVOAOhu#R>NJ>09;VmXO7Is<6>|hqK0D)R#`ya2Q03_fe8Zrie$BQQg_$7Y@kbzzt)c@va)5cIy_B)Knq@EQT z07$ltCkSqACd@$x98Q(#M`btgFq*{xzosBw3-*9UQ^}{Y;*2uKQAnH{=07F43=_Ce<1iIND0g)+bX*aBGDsSZTGc)oext+p8Yiloovx z3B}IOO0s3R9xY1ON(uz*+6oWH1jlh|wjxqQ`~sU0qSP9211r62IFyU@s@axnpG8}) z#7g2i!mv_c(o*1vxME%pBKt$Q@v)bIy7@zE5L>+s2fiTn{9_W_@&G%mWo_=ezRP0s z&dy{25}&A@eA@CwS7hx>>)j1x&b6!?x8ZL4T%zAaMH#Hc$}$mR*ZBu&-L4cm^D~zY zyHHJqLN#flWH{=*<%XFOb%jAD*wAo&U#$7jAp$xLBVFva*VZP+8{?lEXf~K>CHPrC zJ&l8R*2%X`kaRc3u{5+-R{X%dbIq=QvlYKP)qkY!G1aHvut5-2^TIYK^0uKYDYLjj z*djy-sY+VmfZfMK(+GLjF*4c4Kg=eUec`4O;U3hY{A$xEa|=n`-RIIcV=&?^^V(*I z4`7j6bupzQvDdPg@vfGZbV0kug6SqF{l@@^I)T7RMZMU_%C@ZBx)4%0MHZ^xSX-1Q zl~$0~T3c23;9)qD6~i>bY+#(4$#{WFYV}%mZi1L@D*gJx^Qr3@4rxJh z*Ry>5h?iS7wne4Z6wU=E)fG?WiFAuus;BD7l3ILK~V9S6z`T7s)0jw!U*Xx{T~SrkQ)QY7EpsJR)5D1kT+f4>f$BE9)H52X>aL5+#i7|3FA4g&{z zcT-6|@T4|~M@1bhanP+rEfCHhbTg{#x*2PAv=)Hg_gx?BFYj&PHj*6i!vcX~)wzR8 zZgXB)QIYHnWPzQFeWK7KZAo}uVLhpw`d0kZEXC^wIa!R(j7AV5Urw%Hb)J^*M^QyK z>qwo;ekp-Cjk-J-0xqb@-azoy@^qBhKv@i-jfP~|DnJD_%T&VQwd?iOZ{3by@C5z0 zfI`k>NUw;u(DjL&Hh zvEyDAE5&a3;@>Y;zXX3-vj15gAM{uIrWcvMKeo>ppR`}QGxdj%AJM8LD1cb0BQLip zD9DTCA@>%A{Si!KMBeXLwQ$R-g9{0n*-|kpYp%)gupZM+l&{Fpk&9ZD+m$88yS*TX zLd+kwa&#j>d>Y0POlnHsUP&AML~Q$4y|5_I6Ud7G!wAf9{HBbRrJ*5>2_f4b;id{f z9}8ke${Sv2T=UlZcD+{8cB`85PP$ub=H!|_?31lpXxa^^1?JLRkUDLp`Dd8#=_xDA z#dVzzM0ldiA+mV6-U>m!KXacE*q=%?oSLHZwj)Oq*{Wx2FM6IK+-DIC9xtvH>%eoz zt8T}ZdsC){1ejz=Wf}jH4K)O$)Q>%QWNa;qMUTu!lA|n55xuuC`6J0hWX=Zj(vE$s zj(=;yUZOU9eSFEF!dlK$()>tK|kp_%n z9WFEQ>Q$eqzCX39p+B|T?+z2rVyVLE!8-;wZu|_0Q-~c{XtjFD*@-M)y=3Xbn+=H?RY9tXfKC)sbiLsD05!Q3p5scT4|hy^QaeTxA#c zxj(O5$_=A_%||H-|J>C=bP_F8oIv?Q;xWV9g{AEHi~Bl9&}9a3p=ILcLjHyxEc5R0 z@=+r65wyN_sNq@OHOg(AP5r@=Hpo?1^Ci!_&mSh z&)((DJ#()`#Rnsf@khYsb}PgA?!KmDP=?35_(E=hI>Q6^P^XA#sP`DuIuWZ`l+r1z zwEWm#<>#F@OzigW?5*~89IAgFVyW}I!!cw(K2buAd#hTc7tYpk-+8~QsJ&|j<=8|Q z*X->J6+hwkRsH;#H5^MKROq>SKgxFm`R;qoL0}$P<6uy#A#zd45P!tt?u~51?O!(U znF3jx+qQ+42b5Jzz@aVY+;9EqD`l<5K{q15r=bIuN7j`lP*Qy`(10tR8x2&vc@T!* zH49$j`vUshJ3kZc5p?rRh`4P`)el3t=1yzS*AUFn?)YUYCPO_`?;7=IlGnZ zuHA_7!2BMVG^ctVv=x}{k*nbt?H29 zydfZ0;Y6(VgU5jUc!f+(=+r`zxu|indXJfZOD)a2xi=~8%P6D)5zb%kq65Pvv6dI3 zfq9XfXR!~eu;A`*awSJ?Vw`E$Z+G&eNOC0DLoo(1joc%$#=3iy4kB`(?;V|bYko3& zo-KT*K+7CDXVLZ1Z2Mv?jxaV`YJvN%f)r(<&D|v$#)y@*e>x$}{K_gSiAhty(pZ7l z4^^m0mkb1)n69uBkUsJ-P!G{0*Q!i5^rkvb zZE18ODvb>^F#KKe>LZFvU8k+h@K%NbnB z`tDq%OD4Qf#}~v*7JDk~!)d`i4QzuiP5eyZi4L0 z)Y$yfT1qtV1)@SG)p*F;)6J&4xZOY^vDB%bu4Z3JT6FXNkd5f#d)OMR`~-x(B+kI? zCCrJvG>WSAhaXns1TQLRKN{EN3{R!}+K1Uy3{y6`B-;*)5Nk-9v0XV~K*H}^H?Jw+ zjbohO{SX$6mMu9^{$ADyl5sHf@fp)BM!MI5PuCD8ziI3R#Z80#MNwp1L&f5;WHi;)p+%DwIS(7hjcw5&>t zX*qL#Z?z!%(x+M|&?X(c8!Q_KoSYc0IfE&al4Mx@>ATXv{L!z*mt7Hz)fFy@0t#s_ z#6S$MSwqz9a&c%6<3%}2-_!QSGA-$Pm<%_ua_-;H7YtA*V|ChE3NU4ZgDPpn|IA85 zs!}fU#G|gVXKPRJyDt^=7t>eMY#cC5A)HV&CM3mB zJKm}f3_DoWGP8`}hVshsb7t(~n+w;WcFYNgBx*J4=52q!jY& z5^K*JdyEyyN%$&QVCd97bhb5Drz@x1S*jv^Wivv)(tnCg_1rifa-}7R8SK9Qaj`V) zs+hq}f59ImuY5HG+So();wW{IAf<2%!Y!aaHP>Zp&2g)Ud~y}r53{ zX9Ez_@mi{;i3rj}`y(DUW~=W(yjHF|fn8N=$BSaT=G@C8{svQ9_Nm7wEtoUBlGVlZ zw9QJ|Q_{+!1VA}&n2ciV9up9RI~==o&lUTA}(PQAqFC?Eg6>0YwI0Q_=bNGpv^ z!eJ-?@Zrdi`-wm3tXV;Ng5Ki)xP<=>b=xr$Nq=5psFaR>y@@MNBo|`6M=Ui3t>}8iozlIQb6!Xp7ME)A(>rqfn#QHZT)s5w99aJ z?`w&7Qx$rzZx7mZQj4xZkAA#%n_mAom!Mxf$0(f%bF6vIgFnu}H6HMWoE`t&YkB$J zsJ;PBz_frMFw5fb9O5OEd^xQCOAvE&dq*HhUyg<;?>Odq)QM@Ic|$|G^8lbtD4d8u z4bgQ4d3&%0NgLso%f`~Z*nAT*HN_url_nh(_@M zm)OoF#^pC;{5y*gX~%@*F3k6l6%7jwxeD2gH8y#AAK`BCp6D~4G}@krS_Gv=sMRm0Jks(??#tvsHJ}r9R81o;zNC+XCK7 zQ&h%aSKUL$>4Z^++}1&28iBF)pwMsUpxtCcHM={gXr=!-KMs(zS@sr7PhTHI8UFL9 z(3PvP@tg{iZ(M9FMTKzUwsX1wt9!i)1vm#}qxXY2e_Vu?8Y5ai~@jUT1XNkTOs{>E- z8%mdg^G(ZbvlaRIUt^RfeY>KNU98~-zxC9jb(}q}8XZ5j1ZxR@5z=vTwqx^AzZ%N% zod^Q}L1VIMnOAq{>h3Rj!7bac^ZCpA;EMMVIN|J6#s`*Y}Ic5`EUPCwdPE0g${&DEZo~mC@Hn9NFZ+6rp zEXR{Ni0|fekK3;grG_Sr`Tg7{{hR`-bmm2PioNj#@BzNRSqjaE@}%8zhvf5TR!H8f z@5Fzb8|9;ZJi}jen=^TRj}Eb1&m#r_I4=={CKLD&X?D-qaeE&x09gD>%l~-t5E~z8 zqsC|c{}-JINZTUZOKSIat6I{phT7#M8#m<@aQXX_+%FyWhu+f{5YHx&1tb@)9rOC# z^~h!#wwc}?%O=cv!!aNJ;65<326@}?HVSK0aQ=5UN;i~c*n#7XjfKdc>j)- zlU|hOtjSy*m0=3=IT2jTi-~GH4C*4%$y6bk+sZU>Tv= zC#f1TMkr3D38$;na=FeZX{_3H7D~#m2pt$dnWvkJb2ZXfd|Mbb_PtDD0r*A1G-#@O zWF(y~!`20d9yghOQjWE;pFF)m>K`4c-UJD2%OE(C&)B{R=r`*^JEK2VKuXoboJb6c zO!S!ZpB)wFz!gjnx17?8%s%f0^;8!wq8zUyDv<_XXa-EDbrfD85^SrtNSbRC-&Zv- zD`2}~C;e()w~?-uc=2ns;=_0A9dnU|zE&@RI}%K^mGohE7h$NZ|E{xtGKU;j?MegF z7+xlFDV`yuDgPsZ<~VK#g+b!phwo*N%ldgHEjctB!_OV?H<$Dp9u!zz${Q7APshI5hN=L-lXF{r}>mhIz9d=zo|*PIV+scE|2%KJ!oNBQs-af6QM6E z5J!zTc4X-l^0-xvN89G89SQHeoO82$#x8m_kM65NK#Reif{2_YTJS?WL{yE(Znzi= zs+b#NFmIdT5-h**>b2Ne3@r#`pK_mZeUA)E`Uj#cNLqON@S$th+RhNB#X?-|3-j?z z*~as~Y>iH-Fka2x-b>X9c>?sE1Xj}1`mJb`=i489SKIv9hDiqXj0*WGHj^p0>%*F0 z`kRuC=z)~j{BvY|$Km$r=&-5R@pO|}tQfKEEGA2QOg17flqW*ByHMA4L@XpyU&*Kh zq(#FG-Xz_hGgNt9Eh2rGY7|_!_qUF8n}MVw`hm(v<08FO!UT1$o{b|C{}=gHe|vLN z@3yBn8TE`1m3i-;tP0P?lnffe(7EP8S~g(jGM~*n&4FxjF6br2F!JD+;5)S+(Jw~y zV6Y0+YC=Lc%E*cSBjs#foq=tlB&czFV^>nVB3mm{|G3G_=H zyx%j;+IA-G|iGM99Wo8DP;=+2%Rb@U6u*I| z2>u<~7g-J-HauET2wSuj;404i>aw^M@l#BkLmMWUg91})*jrYxNO23Ra`)8R+Zorf zy;A4N?JO&X2dXZ!UX~87I!o$ShS#%yDC~bE96#W0Y=a|y6gU1Jk|U(&THj&DjQlR_ zF%$K^MNG92+@Krs^LutFA3We%fxuFS?a&6Fz4ehE`t>4m~(?77m2O$T-jSmLoU z6K?jl;M2NsV&AzWH>LLSXT-D*54Zqirjw?4Oe4) zZ{%JXYDx?|$Q)fyDJB3G5~0f_FO6i>rNXo2PU8a6b6A9sjHtW}`KtQF&EIiTF0NmJ z_9q`F&jaD>_rl$e*7 z52ua0yOpygzW$*xPJ11!`+QMx`E{|wIE`zLohTc+*X#R!;`X&t>NK6?r{1obOBtt) z(&Np>Au9oDO;!4`M~mc{&qTBW?ZL#mdGCV@Yj55N)>=9ua(C#UNHd=@bVG;Yrj&c4@$>BJpp&nXdLC(@(Ia(ovwj>-}(>Y;u-q*wA ze`R-CC^HiH1TK{mndJ%l9)^>XS$H_PjzSSXOaO_Staz#;Tc~D+5GAr_dUYz$p0Bcl z*O^k2D72Ah7F}$W7Sl}yQadKDX6tsvB~y{3%G1}_^queM%lJ%$pT3XsH~Yx8o6|&2 zx@|3q@eg(gkJ7Uo?yHc#=uB*W=Zxxx!{cleiq;}Ytu!u($Gr0dcDK?&T0Em#2ojVu zrlDQ3N#B$ut9lIhH8)&4`{jSOVYi-7Pis8+f>+IZlM{BDlJI%mF|hNRu@AD)ju%ro zq@RjkSLXwnj+kq38rT<=x>=}-vn7HdKXcFd75=)>dso-7TzNhvPq8<2d6*5i=0qeYdC7}H@ z07y#4!N&S;Q9$+z_^qMVWdwFeGSj{pCgScwi=#=q$XXW9&j2LP1j@pH2>didt z!Ho5w>UOukLNHouaNSv`x{dIraxY}|O`*N$Nd`Bq2&KrK^hRfU7FK@i)R4Vz?pA6U zf_sM?SZFlHJXvq;fHXH%PIAnbHOta19~&nW?REchMy?bKOk6k)CF?aWEUK1HTD;hI zM5*)(T%x^jJzyPPvvj9$Nr9@xqCsF*f`c&Q%U<}gsWThi$Bmwwip~Puu75@vD1NH! zG4``{tXVJ1Cp)7?h5J`GDPwS}RrZXQCsJE~?`%kHne&nlVe*WkXvXVGOZU7wk9-5m zngw@Rjm%hfq2c5NOLaU?b4)b|;VoOAeETwR#o-?dBtdrOz5mQmPqU5mO2fwM(oXgBd9{o0)I6NNR7(;6LUBU5vOLkp$nUYk0 zZ5Fc!^f~~5L;LS6K*G>=W84(N^BDfO-`etZT)*Q;07f2Ik@=rj|6;9aOYXi3s5g*xZ=rIvrQ;Vt4*&xfsbXs{8BhujsS`F zw?$Uosb!C?=j*38^{kj(oGCR|d6OusA1~U(NR;AcK1@A!WB=PPzO>`QjZxj0jdkcI z8D5hp!c&deD))drQu1jTGpqCeK3J0G9s*Q=dv;FHW4Q23sM6hBRMHJm)yzwn}k z4==)$17o%CwlkYN!DzS;k-fQ4;vQp5C^+i1ixoN?ED7CEbNpl&I=pry?E&j~k*Xos zsZDioMwD_&FFzaxBB@UBOm){PNg=lkVTDplmSdDz6F@ifTT@s)MT$oAo+6s9mN;#@ zb`p4*(r3#Yft~Bt58?DWX&)S{F@+2zD3WN)Nj)l$^LiChB~evbGmD!(XR1miBfmht z2B^tzy#X>Ax>%O=V8;Wc#_LXDE0ZRVUP zBJGH2Z~AP|VAV1JNoM=dbon)57YllIj zhpB?#C*xkMFFBUYS)q<63sh8>5-}%51-C_V*ONnI7Oy6%d$=)>mMy=)6?MHR*#(cM z71%L@n9;+oejd)Ow)acFl87uny|9z?omCz2Eu{R?%yl*|EJmvNCzDnQj#c?RxN$AI z+U&S41lD8q)VJU`olb&eE64M$3p2_pWjCCbm-YEa(NJYnYD{n;`T(1L>UleD7b|SB zxH%zKIxc;sYez@1FUnA~(E0=sD)=?M>D#Zm-~%#PI(h#Xu^8-E&<)Si;fN^5yS0Mf zfi{F$M=qJY;^d*vP1HiYwN>;+_*C6;**~v?7E?18JVZu>GxL3DZ)u|~9Za^Tb|3>V zd26ur0`2v*9Hg_kEG2J@^5EN_4>y097R|#WH!b!2bX~M-J=& literal 0 HcmV?d00001 diff --git a/webview-ui/src/components/chat/__tests__/__screenshots__/chat-controls-resting-dark.png b/webview-ui/src/components/chat/__tests__/__screenshots__/chat-controls-resting-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..12fb563475ddcdda156a44c2c540a8ac0fe54941 GIT binary patch literal 5187 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 literal 0 HcmV?d00001 diff --git a/webview-ui/src/components/chat/__tests__/__screenshots__/chat-controls-resting-light.png b/webview-ui/src/components/chat/__tests__/__screenshots__/chat-controls-resting-light.png new file mode 100644 index 0000000000000000000000000000000000000000..ac809ce7166e5e569e65333a660a92dd7b28f771 GIT binary patch literal 5112 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 Ur#0E0y_5iY5F@Q>4g1Ld0!ZkJ2mk;8 literal 0 HcmV?d00001 diff --git a/webview-ui/src/components/ui/select-dropdown.tsx b/webview-ui/src/components/ui/select-dropdown.tsx index d9ee99ebbb..5258123e04 100644 --- a/webview-ui/src/components/ui/select-dropdown.tsx +++ b/webview-ui/src/components/ui/select-dropdown.tsx @@ -6,6 +6,7 @@ import { useTranslation } from "react-i18next" import { cn } from "@/lib/utils" import { useRooPortal } from "./hooks/useRooPortal" +import { enabledSelectorTriggerClassName, selectorTriggerClassName } from "./selectorTriggerStyles" import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui" import { StandardTooltip } from "@/components/ui" @@ -193,11 +194,9 @@ export const SelectDropdown = React.memo( data-testid="dropdown-trigger" className={cn( "w-full min-w-0 max-w-full inline-flex items-center gap-1.5 relative whitespace-nowrap px-1.5 py-1 text-xs", - "bg-transparent border border-[rgba(255,255,255,0.08)] rounded-md text-vscode-foreground w-auto", - "transition-all duration-150 focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder focus-visible:ring-inset", - disabled - ? "opacity-50 cursor-not-allowed" - : "opacity-90 hover:opacity-100 hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)] cursor-pointer", + selectorTriggerClassName, + "w-auto", + disabled ? "opacity-50 cursor-not-allowed" : enabledSelectorTriggerClassName, triggerClassName, )}> diff --git a/webview-ui/src/components/ui/selectorTriggerStyles.ts b/webview-ui/src/components/ui/selectorTriggerStyles.ts new file mode 100644 index 0000000000..f009c6a073 --- /dev/null +++ b/webview-ui/src/components/ui/selectorTriggerStyles.ts @@ -0,0 +1,5 @@ +export const selectorTriggerClassName = + "bg-transparent border border-vscode-dropdown-border rounded-md text-vscode-foreground transition-all duration-150 focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder focus-visible:ring-inset" + +export const enabledSelectorTriggerClassName = + "opacity-90 hover:opacity-100 hover:bg-vscode-toolbar-hoverBackground hover:border-vscode-focusBorder cursor-pointer" From 39bdfb188827a5520109ec38b3091a4d4bb9e4c2 Mon Sep 17 00:00:00 2001 From: "zoomote[bot]" <305051434+zoomote[bot]@users.noreply.github.com> Date: Fri, 21 Aug 2026 15:15:01 +0000 Subject: [PATCH 39/66] [Fix] Remaining chat controls fade into light IDE themes (#1312) * fix(webview): finish light theme token cleanup * test(webview): add visual regression screenshots for remaining theme controls --------- Co-authored-by: Roomote Co-authored-by: Elliott de Launay --- webview-ui/playwright/vscode-theme-light.css | 2 + .../src/components/chat/ChatTextArea.tsx | 37 ++++----- .../components/chat/CodebaseSearchResult.tsx | 8 +- webview-ui/src/components/chat/IconButton.tsx | 8 +- .../components/chat/IndexingStatusBadge.tsx | 3 +- .../src/components/chat/LucideIconButton.tsx | 6 +- .../chat/UpdateTodoListToolBlock.tsx | 22 ++---- .../src/components/chat/WorktreeSelector.tsx | 3 +- .../__tests__/ChatControlButtons.spec.tsx | 42 +++++++++++ .../__tests__/CodebaseSearchResult.spec.tsx | 38 ++++++++++ .../__tests__/ThemeTokenCleanup.visual.tsx | 70 ++++++++++++++++++ .../UpdateTodoListToolBlock.spec.tsx | 12 ++- .../remaining-controls-active-dark.png | Bin 0 -> 1662 bytes .../remaining-controls-active-light.png | Bin 0 -> 1623 bytes .../remaining-controls-resting-dark.png | Bin 0 -> 1501 bytes .../remaining-controls-resting-light.png | Bin 0 -> 1506 bytes .../src/components/chat/chatControlStyles.ts | 5 ++ .../components/ui/__tests__/checkbox.spec.tsx | 12 +++ webview-ui/src/components/ui/checkbox.tsx | 7 +- 19 files changed, 216 insertions(+), 59 deletions(-) create mode 100644 webview-ui/src/components/chat/__tests__/ChatControlButtons.spec.tsx create mode 100644 webview-ui/src/components/chat/__tests__/CodebaseSearchResult.spec.tsx create mode 100644 webview-ui/src/components/chat/__tests__/ThemeTokenCleanup.visual.tsx create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/remaining-controls-active-dark.png create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/remaining-controls-active-light.png create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/remaining-controls-resting-dark.png create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/remaining-controls-resting-light.png create mode 100644 webview-ui/src/components/chat/chatControlStyles.ts create mode 100644 webview-ui/src/components/ui/__tests__/checkbox.spec.tsx diff --git a/webview-ui/playwright/vscode-theme-light.css b/webview-ui/playwright/vscode-theme-light.css index 3edfff4899..3c2046e97d 100644 --- a/webview-ui/playwright/vscode-theme-light.css +++ b/webview-ui/playwright/vscode-theme-light.css @@ -7,6 +7,7 @@ --vscode-focusBorder: #0090f1; --vscode-editor-foreground: #333333; --vscode-editor-background: #ffffff; + --vscode-editorGroup-border: #cecece; --vscode-button-foreground: #ffffff; --vscode-button-background: #007acc; --vscode-button-hoverBackground: #0062a3; @@ -25,6 +26,7 @@ --vscode-panel-border: #cecece; --vscode-widget-border: #d4d4d4; --vscode-widget-shadow: #00000029; + --vscode-textLink-foreground: #006ab1; --vscode-menu-foreground: #3b3b3b; --vscode-menu-background: #ffffff; --vscode-editorHoverWidget-foreground: #3b3b3b; diff --git a/webview-ui/src/components/chat/ChatTextArea.tsx b/webview-ui/src/components/chat/ChatTextArea.tsx index 4cf57d1e3e..db2ca80609 100644 --- a/webview-ui/src/components/chat/ChatTextArea.tsx +++ b/webview-ui/src/components/chat/ChatTextArea.tsx @@ -33,6 +33,7 @@ import ContextMenu from "./ContextMenu" import { IndexingStatusBadge } from "./IndexingStatusBadge" import { ZooCodeAuthBadge } from "./ZooCodeAuthBadge" import { usePromptHistory } from "./hooks/usePromptHistory" +import { disabledChatControlClassName, enabledChatControlClassName } from "./chatControlStyles" interface ChatTextAreaProps { inputValue: string @@ -1136,14 +1137,11 @@ export const ChatTextArea = forwardRef( "transition-all duration-1000", "cursor-pointer", !shouldDisableImages - ? "opacity-50 hover:opacity-100 delay-750 pointer-events-auto" + ? "opacity-50 delay-750 pointer-events-auto" : "opacity-0 pointer-events-none duration-200 delay-0", - !shouldDisableImages && - "hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]", + !shouldDisableImages && enabledChatControlClassName, "focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder", - !shouldDisableImages && "active:bg-[rgba(255,255,255,0.1)]", - shouldDisableImages && - "opacity-40 cursor-not-allowed grayscale-[30%] hover:bg-transparent hover:border-[rgba(255,255,255,0.08)] active:bg-transparent", + shouldDisableImages && disabledChatControlClassName, )}> @@ -1158,11 +1156,10 @@ export const ChatTextArea = forwardRef( "relative inline-flex items-center justify-center", "bg-transparent border-none p-1.5", "rounded-md min-w-[28px] min-h-[28px]", - "opacity-60 hover:opacity-100 text-vscode-descriptionForeground hover:text-vscode-foreground", + "opacity-60 text-vscode-descriptionForeground hover:text-vscode-foreground", "transition-all duration-150", - "hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]", + enabledChatControlClassName, "focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder", - "active:bg-[rgba(255,255,255,0.1)]", "cursor-pointer", )}> @@ -1182,12 +1179,10 @@ export const ChatTextArea = forwardRef( "transition-all duration-1000", "cursor-pointer", hasInputContent - ? "opacity-50 hover:opacity-100 delay-750 pointer-events-auto" + ? "opacity-50 delay-750 pointer-events-auto" : "opacity-0 pointer-events-none duration-200 delay-0", - hasInputContent && - "hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]", + hasInputContent && enabledChatControlClassName, "focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder", - hasInputContent && "active:bg-[rgba(255,255,255,0.1)]", )}> ( "rounded-md min-w-[28px] min-h-[28px]", "text-vscode-descriptionForeground hover:text-vscode-foreground", "transition-all duration-200", - "opacity-100 hover:opacity-100 pointer-events-auto", - "hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]", + "opacity-100 pointer-events-auto", + enabledChatControlClassName, "focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder", - "active:bg-[rgba(255,255,255,0.1)]", "cursor-pointer", )}> @@ -1244,16 +1238,14 @@ export const ChatTextArea = forwardRef( "text-vscode-descriptionForeground hover:text-vscode-foreground", "transition-all duration-200", isEditMode || isStreaming || hasInputContent - ? "opacity-100 hover:opacity-100 pointer-events-auto" + ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none", (isEditMode || isStreaming || hasInputContent) && - "hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]", + enabledChatControlClassName, "focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder", - (isEditMode || isStreaming || hasInputContent) && - "active:bg-[rgba(255,255,255,0.1)]", (isEditMode || isStreaming || hasInputContent) && "cursor-pointer", isStreaming && - "bg-vscode-button-background hover:bg-vscode-button-background", + "bg-vscode-button-background hover:bg-vscode-button-background active:bg-vscode-button-background", )}> {isStreaming ? ( @@ -1333,9 +1325,8 @@ export const ChatTextArea = forwardRef( "rounded-md min-w-[28px] min-h-[28px]", "text-vscode-foreground opacity-85", "transition-all duration-150", - "hover:opacity-100 hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]", + enabledChatControlClassName, "focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder", - "active:bg-[rgba(255,255,255,0.1)]", "cursor-pointer", )}> diff --git a/webview-ui/src/components/chat/CodebaseSearchResult.tsx b/webview-ui/src/components/chat/CodebaseSearchResult.tsx index 8280ea3d47..74249c6f73 100644 --- a/webview-ui/src/components/chat/CodebaseSearchResult.tsx +++ b/webview-ui/src/components/chat/CodebaseSearchResult.tsx @@ -30,15 +30,15 @@ const CodebaseSearchResult: React.FC = ({ filePath, s
+ className="group p-2 border border-vscode-editorGroup-border cursor-pointer hover:bg-vscode-list-hoverBackground">
- + {filePath.split("/").at(-1)}:{startLine === endLine ? startLine : `${startLine}-${endLine}`} - + {filePath.split("/").slice(0, -1).join("/")} - + {score.toFixed(3)}
diff --git a/webview-ui/src/components/chat/IconButton.tsx b/webview-ui/src/components/chat/IconButton.tsx index 00210ac5b3..d2acd53b00 100644 --- a/webview-ui/src/components/chat/IconButton.tsx +++ b/webview-ui/src/components/chat/IconButton.tsx @@ -1,5 +1,6 @@ import { cn } from "@src/lib/utils" import { Button, StandardTooltip } from "@src/components/ui" +import { disabledChatControlClassName, enabledChatControlClassName } from "./chatControlStyles" interface IconButtonProps extends React.ButtonHTMLAttributes { iconClass: string @@ -30,12 +31,9 @@ export const IconButton: React.FC = ({ "rounded-md min-w-[28px] min-h-[28px]", "text-vscode-foreground opacity-85", "transition-all duration-150", - "hover:opacity-100 hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]", "focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder", - "active:bg-[rgba(255,255,255,0.1)]", - !disabled && "cursor-pointer", - disabled && - "opacity-40 cursor-not-allowed grayscale-[30%] hover:bg-transparent hover:border-[rgba(255,255,255,0.08)] active:bg-transparent", + !disabled && cn("cursor-pointer", enabledChatControlClassName), + disabled && disabledChatControlClassName, className, )} disabled={disabled} diff --git a/webview-ui/src/components/chat/IndexingStatusBadge.tsx b/webview-ui/src/components/chat/IndexingStatusBadge.tsx index 227df3e645..22dbe8f9d5 100644 --- a/webview-ui/src/components/chat/IndexingStatusBadge.tsx +++ b/webview-ui/src/components/chat/IndexingStatusBadge.tsx @@ -11,6 +11,7 @@ import { useExtensionState } from "@src/context/ExtensionStateContext" import { PopoverTrigger, StandardTooltip, Button } from "@src/components/ui" import { CodeIndexPopover } from "./CodeIndexPopover" +import { enabledChatControlClassName } from "./chatControlStyles" interface IndexingStatusBadgeProps { className?: string @@ -96,7 +97,7 @@ export const IndexingStatusBadge: React.FC = ({ classN className={cn( "relative h-5 w-5 p-0", "text-vscode-foreground opacity-85", - "hover:opacity-100 hover:bg-[rgba(255,255,255,0.03)]", + enabledChatControlClassName, "focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder", className, )}> diff --git a/webview-ui/src/components/chat/LucideIconButton.tsx b/webview-ui/src/components/chat/LucideIconButton.tsx index a527df3f1d..4f53b1248b 100644 --- a/webview-ui/src/components/chat/LucideIconButton.tsx +++ b/webview-ui/src/components/chat/LucideIconButton.tsx @@ -2,6 +2,7 @@ import { forwardRef } from "react" import { cn } from "@src/lib/utils" import { Button, StandardTooltip } from "@src/components/ui" import { Loader2, LucideIcon } from "lucide-react" +import { disabledChatControlClassName, enabledChatControlClassName } from "./chatControlStyles" interface LucideIconButtonProps extends React.ButtonHTMLAttributes { icon: LucideIcon @@ -27,9 +28,8 @@ export const LucideIconButton = forwardRef Math.random().toString(36).slice(2, 10) @@ -345,7 +333,7 @@ const UpdateTodoListToolBlock: React.FC = ({ style={{ border: "none", background: "transparent", - color: "#f14c4c", + color: "var(--vscode-errorForeground)", cursor: "pointer", fontSize: 14, marginLeft: 2, @@ -380,7 +368,7 @@ const UpdateTodoListToolBlock: React.FC = ({ fontSize: 13, marginRight: 6, padding: "1px 3px", - borderBottom: "1px solid #eee", + borderBottom: "1px solid var(--vscode-input-border)", }} /> + +
, + ) + + await component.evaluate(async () => { + await document.fonts.ready + await new Promise((resolve) => requestAnimationFrame(() => resolve())) + }) + + await expect(component).toHaveScreenshot(`remaining-controls-resting-${theme.name}.png`) + + const iconButton = component.getByRole("button", { name: "Settings" }) + await iconButton.hover() + await expect(iconButton).toHaveCSS("background-color", theme.expected.hover) + await iconButton.focus() + await page.mouse.down() + await expect(iconButton).toHaveCSS("background-color", theme.expected.active) + await page.mouse.up() + + await expect(component).toHaveScreenshot(`remaining-controls-active-${theme.name}.png`) + + const checkbox = component.getByRole("checkbox", { name: "Include optional context" }) + await expect(checkbox).toHaveCSS("background-color", theme.expected.description) + await expect(checkbox).toHaveCSS("color", theme.expected.background) + }) +} diff --git a/webview-ui/src/components/chat/__tests__/UpdateTodoListToolBlock.spec.tsx b/webview-ui/src/components/chat/__tests__/UpdateTodoListToolBlock.spec.tsx index eb7d0ab93c..b9397abca0 100644 --- a/webview-ui/src/components/chat/__tests__/UpdateTodoListToolBlock.spec.tsx +++ b/webview-ui/src/components/chat/__tests__/UpdateTodoListToolBlock.spec.tsx @@ -1,5 +1,5 @@ import { fireEvent, render, screen, waitFor } from "@testing-library/react" -import { beforeEach, describe, expect, it, vi } from "vitest" +import { beforeEach, describe, expect, it, test, vi } from "vitest" import UpdateTodoListToolBlock from "../UpdateTodoListToolBlock" @@ -41,4 +41,14 @@ describe("UpdateTodoListToolBlock", () => { await waitFor(() => expect(screen.queryByRole("alertdialog")).not.toBeInTheDocument()) expect(onChange).toHaveBeenCalledWith([]) }) + + test("renders theme-aware edit controls", () => { + renderEditableList() + fireEvent.click(screen.getByRole("button", { name: "Edit" })) + + expect(screen.getByTitle("Remove")).toBeInTheDocument() + expect(screen.getByDisplayValue("Ship the follow-up")).toBeInTheDocument() + fireEvent.click(screen.getByRole("button", { name: "+ Add Todo" })) + expect(screen.getByPlaceholderText("Enter todo item, press Enter to add")).toBeInTheDocument() + }) }) diff --git a/webview-ui/src/components/chat/__tests__/__screenshots__/remaining-controls-active-dark.png b/webview-ui/src/components/chat/__tests__/__screenshots__/remaining-controls-active-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..e6f84c0a585330fbc7cdab9d5cfd239850216cef GIT binary patch literal 1662 zcmV-^27&pBP)SF>=8usP0sye^-j9whEh+gpeQf~kfU>ebLHYo| z+e9NAck!ckYv0eUZKj9fE6SPhgcOal*K8MwELNY$ zSWOm((onuX+j(JM-JnPS-oQ-k1QYO6OoTqK$RN92S6yS_T#PE-m|s%7lMxQozdTGB zl`bP&XR`F$MMiDNNRtG!#o_3x-rhw3{wD;G|B|begdezVw(%0(viCMu@9vhlcu)G! zW+%5WFC{`wh{X4{)-;>kad{;hbdijD@2>ZLpG;mItCF_vkvCl#(wDCDbU@sP<%e@g z|EN4hqhjT5?$_oEjb?`=i^(k5lBs2hB#idj*rXWC>B>ee`T67W;fnAtSSrj-`2GbAQxBa{pgdCnoyFk;kew-%?kuOHdDeaGQeL6=`*d{-Q3 zZ8UMhVDpiajZIgsS%uNt=a1Ex{+@b%JVvFF_0}ESv2EA4{j!xg#t4Q{8}oBx9W52x zckFMlYV;o{J#|W5POesHtk}Ez%e^PsMXez*f+66a5J3J*wEc9X;^IAdV)n+eudB{q zIe(}mBZ1}+6OoV-A@p1`a}tpp=C*D=Qa_)JpiRzi_vk)E9J4vxjFOefB4b#WwX2Vl zBlwYtYazz<;v=C_!4^f^Uk`3ALY zW>XbsOi>fg!in5K56`a7NK|?9LaELAyfAIHh?aR?ru&P+^x(= zjP&fo#AbbUye!poaLF+|$O$y1(Es==bU=Q~*;`lrJzb3|J6ROThPYjS+53BbIM!xz zNW{@`x{fW#J6M$`5k~H|wVa`AV$ z?Abp@M+ty;c^20;=B9Y2kR;yH-qe6|4uSmVVpIYE;0r-RLqkzfQ3{1((V|5J0AS$> zg3#C3S6*Ho5Ed5pz`O&me#Rz-JIZ0N^v8KO_qc4K)}H%a$!uC=@R(8Xq6OfB$}0SJ%YE z1OWi>k^rq%TUc1AR4V5zbvm83wYA6~0PvPT+WX8WeJEPCX3ZJ`0N^FT%a<>oe|2nZ zECB%Uk~g~=9+%DofEUfZ3N|t_QdwE~=+Pqr0N_<~+?I!?Pg7IViWMuCE?r6h0KDpT z0rcR(1DZZbNlEGH=>!14+h&JgT!nwpArcK}#8vjL<~C<+P+9zT9eGiWA#j7H0s!D8fwykm62*DluA7#1c6Jf~051tzvSi7?z`)|gi)ruks=G7OMS6?H zLg%M31Ooss3W$n|A^-rs@DBh00RR8}C12bC000I_L_t&o03MKT;n&1x^#A|>07*qo IM6N<$f`CyJ3;+NC literal 0 HcmV?d00001 diff --git a/webview-ui/src/components/chat/__tests__/__screenshots__/remaining-controls-active-light.png b/webview-ui/src/components/chat/__tests__/__screenshots__/remaining-controls-active-light.png new file mode 100644 index 0000000000000000000000000000000000000000..bf6fa9c6c54099a5ecb5298e06dd7578beb1ecb0 GIT binary patch literal 1623 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 { + test("renders the description variant as checked", () => { + render() + + expect(screen.getByRole("checkbox", { name: "Include optional context" })).toBeChecked() + }) +}) diff --git a/webview-ui/src/components/ui/checkbox.tsx b/webview-ui/src/components/ui/checkbox.tsx index a4b005d00a..bfc069f852 100644 --- a/webview-ui/src/components/ui/checkbox.tsx +++ b/webview-ui/src/components/ui/checkbox.tsx @@ -15,7 +15,7 @@ const checkboxVariants = cva( default: "border-vscode-foreground data-[state=checked]:bg-primary data-[state=checked]:text-foreground", description: - "border-vscode-descriptionForeground data-[state=checked]:bg-vscode-descriptionForeground data-[state=checked]:text-white", + "border-vscode-descriptionForeground data-[state=checked]:bg-vscode-descriptionForeground data-[state=checked]:text-vscode-editor-background", }, }, defaultVariants: { @@ -25,14 +25,13 @@ const checkboxVariants = cva( ) export interface CheckboxProps - extends React.ComponentPropsWithoutRef, - VariantProps {} + extends React.ComponentPropsWithoutRef, VariantProps {} const Checkbox = React.forwardRef, CheckboxProps>( ({ className, variant, ...props }, ref) => ( - + ), From 1ad8f528d403a65709d5af20c9d99cb9f6a1548a Mon Sep 17 00:00:00 2001 From: edelauna <54631123+edelauna@users.noreply.github.com> Date: Fri, 21 Aug 2026 16:24:21 +0000 Subject: [PATCH 40/66] fix(telemetry): default telemetry to opt-out with explicit consent UI (#1069) * fix(telemetry): default telemetry to opt-out with explicit consent UI * test(webview-ui): add visual snapshot for TelemetryBanner * fix(webview): guard telemetry queue and fix visual test CI failures * fix(codecov): cover telemetry guard branch, exempt CT-only fixtures * fix(telemetry): address parallel-review findings on consent PR * fix(telemetry): require explicit banner consent --- PRIVACY.md | 18 +- codecov.yml | 8 + .../telemetry.isTelemetryOptedIn.test.ts | 21 ++ packages/types/src/telemetry.ts | 12 + packages/types/src/vscode-extension-host.ts | 5 + src/__tests__/extension.spec.ts | 207 ++++++++++++- src/core/webview/ClineProvider.ts | 2 + .../telemetrySettingsTracking.spec.ts | 45 ++- .../__tests__/webviewMessageHandler.spec.ts | 279 ++++++++++++++++++ src/core/webview/webviewMessageHandler.ts | 100 +++++-- src/eslint-suppressions.json | 5 - src/extension.ts | 38 ++- webview-ui/playwright/vscode-theme-dark.css | 24 ++ webview-ui/src/App.tsx | 14 +- .../src/__tests__/TelemetryClient.spec.ts | 61 +++- .../ChatView.scroll-debug-repro.spec.tsx | 3 + .../src/components/common/TelemetryBanner.tsx | 36 ++- .../common/__tests__/TelemetryBanner.spec.tsx | 61 ++++ .../TelemetryBanner.visual.fixture.tsx | 18 ++ .../__tests__/TelemetryBanner.visual.i18n.ts | 36 +++ .../__tests__/TelemetryBanner.visual.tsx | 18 ++ .../__screenshots__/telemetry-banner-dark.png | Bin 0 -> 12206 bytes webview-ui/src/components/settings/About.tsx | 4 +- .../settings/__tests__/About.spec.tsx | 30 ++ webview-ui/src/i18n/locales/ca/settings.json | 4 +- webview-ui/src/i18n/locales/ca/welcome.json | 4 +- webview-ui/src/i18n/locales/de/settings.json | 4 +- webview-ui/src/i18n/locales/de/welcome.json | 4 +- webview-ui/src/i18n/locales/en/settings.json | 4 +- webview-ui/src/i18n/locales/en/welcome.json | 4 +- webview-ui/src/i18n/locales/es/settings.json | 4 +- webview-ui/src/i18n/locales/es/welcome.json | 4 +- webview-ui/src/i18n/locales/fr/settings.json | 4 +- webview-ui/src/i18n/locales/fr/welcome.json | 4 +- webview-ui/src/i18n/locales/hi/settings.json | 4 +- webview-ui/src/i18n/locales/hi/welcome.json | 4 +- webview-ui/src/i18n/locales/id/settings.json | 4 +- webview-ui/src/i18n/locales/id/welcome.json | 4 +- webview-ui/src/i18n/locales/it/settings.json | 4 +- webview-ui/src/i18n/locales/it/welcome.json | 4 +- webview-ui/src/i18n/locales/ja/settings.json | 4 +- webview-ui/src/i18n/locales/ja/welcome.json | 4 +- webview-ui/src/i18n/locales/ko/settings.json | 4 +- webview-ui/src/i18n/locales/ko/welcome.json | 4 +- webview-ui/src/i18n/locales/nl/settings.json | 4 +- webview-ui/src/i18n/locales/nl/welcome.json | 4 +- webview-ui/src/i18n/locales/pl/settings.json | 4 +- webview-ui/src/i18n/locales/pl/welcome.json | 4 +- .../src/i18n/locales/pt-BR/settings.json | 4 +- .../src/i18n/locales/pt-BR/welcome.json | 4 +- webview-ui/src/i18n/locales/ru/settings.json | 4 +- webview-ui/src/i18n/locales/ru/welcome.json | 4 +- webview-ui/src/i18n/locales/tr/settings.json | 4 +- webview-ui/src/i18n/locales/tr/welcome.json | 4 +- webview-ui/src/i18n/locales/vi/settings.json | 4 +- webview-ui/src/i18n/locales/vi/welcome.json | 4 +- .../src/i18n/locales/zh-CN/settings.json | 4 +- .../src/i18n/locales/zh-CN/welcome.json | 4 +- .../src/i18n/locales/zh-TW/settings.json | 4 +- .../src/i18n/locales/zh-TW/welcome.json | 4 +- webview-ui/src/utils/TelemetryClient.ts | 11 +- 61 files changed, 1050 insertions(+), 150 deletions(-) create mode 100644 packages/types/src/__tests__/telemetry.isTelemetryOptedIn.test.ts create mode 100644 webview-ui/src/components/common/__tests__/TelemetryBanner.spec.tsx create mode 100644 webview-ui/src/components/common/__tests__/TelemetryBanner.visual.fixture.tsx create mode 100644 webview-ui/src/components/common/__tests__/TelemetryBanner.visual.i18n.ts create mode 100644 webview-ui/src/components/common/__tests__/TelemetryBanner.visual.tsx create mode 100644 webview-ui/src/components/common/__tests__/__screenshots__/telemetry-banner-dark.png diff --git a/PRIVACY.md b/PRIVACY.md index 2f589cf3ea..f43760023d 100644 --- a/PRIVACY.md +++ b/PRIVACY.md @@ -1,6 +1,6 @@ # Zoo Code Privacy Policy -**Last Updated: May 13th, 2026** +**Last Updated: August 15th, 2026** Zoo Code respects your privacy and is committed to transparency about how we handle your data. Below is a simple breakdown of where key pieces of data @@ -32,14 +32,18 @@ go—and, importantly, where they don't. - **API Keys & Credentials**: If you enter an API key (e.g., to connect an AI model), it is stored locally on your device and never sent to us or any third party, except the provider you have chosen. -- **Telemetry (Usage Data)**: We collect feature usage and error data to help - us improve Zoo Code. This telemetry is powered by PostHog and includes your - VS Code machine ID, feature usage patterns, and exception reports. The VS Code +- **Telemetry (Usage Data)**: We collect feature usage and error data to help us + improve Zoo Code. This telemetry is powered by PostHog and includes your VS + Code machine ID, feature usage patterns, and exception reports. The VS Code machine ID is a persistent identifier and may be considered personal data in some jurisdictions; we use it only for product analytics and error grouping. - We retain telemetry only as long as needed for product analytics and debugging. - Telemetry does **not** collect your code or AI prompts, and you can opt out at - any time through the settings. + PostHog event data is retained for 12 months under our current project + configuration. This PostHog-based telemetry does **not** collect your code or AI + prompts. Telemetry is on by default. To turn it off, choose "Disabled" in + the settings or in the notice shown on first use. The notice remains until + you explicitly Accept or Decline. Telemetry also follows VS Code's own + global telemetry setting: if you turn that off, Zoo Code stops sending + telemetry right away, even if the Zoo Code setting says "Enabled." - **Marketplace Requests**: When you browse or search the Marketplace for Model Configuration Profiles (MCPs) or Custom Modes, Zoo Code makes a secure API call to Zoo Code's backend servers to retrieve listing information. These diff --git a/codecov.yml b/codecov.yml index 7dd22dfdc2..0d45b50be0 100644 --- a/codecov.yml +++ b/codecov.yml @@ -42,6 +42,14 @@ flag_management: - packages/core/src/ carryforward: true +ignore: + # Playwright CT-only fixtures/helpers: exercised by the webview-ui-ct flag's browser run, not + # Vitest, and excluded from that flag's own lcov by playwright-ct.config.ts's sourceFilter (same + # ".visual." match). Without this, patch coverage sees 0% for these paths on any PR that adds or + # touches one, since no flag's lcov contains them. + - "webview-ui/src/**/*.visual.fixture.tsx" + - "webview-ui/src/**/*.visual.i18n.ts" + component_management: individual_components: - component_id: webview_components diff --git a/packages/types/src/__tests__/telemetry.isTelemetryOptedIn.test.ts b/packages/types/src/__tests__/telemetry.isTelemetryOptedIn.test.ts new file mode 100644 index 0000000000..671f88cc67 --- /dev/null +++ b/packages/types/src/__tests__/telemetry.isTelemetryOptedIn.test.ts @@ -0,0 +1,21 @@ +// pnpm --filter @roo-code/types test src/__tests__/telemetry.isTelemetryOptedIn.test.ts + +import { isTelemetryOptedIn } from "../telemetry.js" + +describe("isTelemetryOptedIn", () => { + it("returns true for an explicit 'enabled' setting", () => { + expect(isTelemetryOptedIn("enabled")).toBe(true) + }) + + it("returns false for an explicit 'disabled' setting", () => { + expect(isTelemetryOptedIn("disabled")).toBe(false) + }) + + it("returns true for 'unset' (disclosed opt-out default applies)", () => { + expect(isTelemetryOptedIn("unset")).toBe(true) + }) + + it("returns true for undefined (treated the same as unset)", () => { + expect(isTelemetryOptedIn(undefined)).toBe(true) + }) +}) diff --git a/packages/types/src/telemetry.ts b/packages/types/src/telemetry.ts index 402cd571c8..d69476836e 100644 --- a/packages/types/src/telemetry.ts +++ b/packages/types/src/telemetry.ts @@ -13,6 +13,18 @@ export const telemetrySettingsSchema = z.enum(telemetrySettings) export type TelemetrySetting = z.infer +/** + * Whether telemetry should be captured for this install. + * + * Telemetry is on by default (disclosed opt-out): "unset" (no choice made yet) and + * "enabled" both mean telemetry may be captured. Only an explicit "disabled" opts out. + * The consent banner's dismiss/close action never writes a setting, so it stays neutral -- + * it just leaves the default in effect rather than recording an affirmative choice either way. + */ +export function isTelemetryOptedIn(telemetrySetting: TelemetrySetting | undefined): boolean { + return telemetrySetting !== "disabled" +} + /** * TelemetryEventName */ diff --git a/packages/types/src/vscode-extension-host.ts b/packages/types/src/vscode-extension-host.ts index ea52c09599..337ad22e2c 100644 --- a/packages/types/src/vscode-extension-host.ts +++ b/packages/types/src/vscode-extension-host.ts @@ -364,6 +364,11 @@ export type ExtensionState = Pick< telemetrySetting: TelemetrySetting telemetryKey?: string machineId?: string + // Live vscode.env.isTelemetryEnabled, so the webview's own PostHog client can respect + // the VS Code global telemetry toggle the same way the extension-side gate does -- + // without this, an explicit user Accept can still send events while VS Code's global + // telemetry is disabled. + vscodeTelemetryEnabled?: boolean renderContext: "sidebar" | "editor" settingsImportedAt?: number diff --git a/src/__tests__/extension.spec.ts b/src/__tests__/extension.spec.ts index 8af352425a..eefe9626ae 100644 --- a/src/__tests__/extension.spec.ts +++ b/src/__tests__/extension.spec.ts @@ -36,6 +36,8 @@ vi.mock("vscode", () => ({ }, env: { language: "en", + isTelemetryEnabled: true, + onDidChangeTelemetryEnabled: vi.fn(), }, ExtensionMode: { Production: 1, @@ -72,19 +74,19 @@ vi.mock("@roo-code/cloud", () => ({ getRooCodeApiUrl: vi.fn().mockReturnValue("https://app.roocode.com"), })) +const mockTelemetryServiceInstance = { + register: vi.fn(), + setProvider: vi.fn(), + shutdown: vi.fn(), + updateTelemetryState: vi.fn(), +} + vi.mock("@roo-code/telemetry", () => ({ TelemetryService: { - createInstance: vi.fn().mockReturnValue({ - register: vi.fn(), - setProvider: vi.fn(), - shutdown: vi.fn(), - }), + createInstance: vi.fn().mockReturnValue(mockTelemetryServiceInstance), + hasInstance: vi.fn().mockReturnValue(true), get instance() { - return { - register: vi.fn(), - setProvider: vi.fn(), - shutdown: vi.fn(), - } + return mockTelemetryServiceInstance }, }, PostHogTelemetryClient: vi.fn(), @@ -114,6 +116,7 @@ vi.mock("../core/config/ContextProxy", () => ({ setValue: vi.fn(), getValues: vi.fn().mockReturnValue({}), getProviderSettings: vi.fn().mockReturnValue({}), + getGlobalState: vi.fn().mockReturnValue("enabled"), }), }, })) @@ -286,7 +289,7 @@ describe("extension.ts", () => { telemetryClient: null, authService: null, hasActiveSession: vi.fn().mockReturnValue(false), - } as any + } as unknown as never }) vi.mocked(CloudService.hasInstance).mockReturnValue(true) @@ -295,7 +298,11 @@ describe("extension.ts", () => { const { activate } = await import("../extension") await activate(mockContext) - const provider = (ClineProvider as any).getVisibleInstance() + const provider = ( + ClineProvider as unknown as { + getVisibleInstance(): { postStateToWebviewWithoutClineMessages: ReturnType } + } + ).getVisibleInstance() provider.postStateToWebviewWithoutClineMessages.mockClear() await authStateChangedHandler!({ @@ -317,4 +324,180 @@ describe("extension.ts", () => { await expect(activate(mockContext)).resolves.toBeDefined() }) }) + + describe("telemetry level reactivity", () => { + beforeEach(async () => { + vi.resetModules() + const vscode = await import("vscode") + ;(vscode.env as { isTelemetryEnabled: boolean }).isTelemetryEnabled = true + }) + + test("registers a listener for vscode.env.onDidChangeTelemetryEnabled", async () => { + const vscode = await import("vscode") + + const { activate } = await import("../extension") + await activate(mockContext) + + expect(vscode.env.onDidChangeTelemetryEnabled).toHaveBeenCalledTimes(1) + expect(vscode.env.onDidChangeTelemetryEnabled).toHaveBeenCalledWith(expect.any(Function)) + }) + + test("re-evaluates telemetry state from stored settings when VS Code's global toggle changes", async () => { + const vscode = await import("vscode") + const { TelemetryService } = await import("@roo-code/telemetry") + const { ContextProxy } = await import("../core/config/ContextProxy") + + const mockContextProxyInstance = await ( + ContextProxy.getInstance as unknown as () => Promise<{ getGlobalState: ReturnType }> + )() + vi.mocked(mockContextProxyInstance.getGlobalState).mockReturnValue("enabled") + ;(vscode.env as { isTelemetryEnabled: boolean }).isTelemetryEnabled = true + + const { activate } = await import("../extension") + await activate(mockContext) + + const updateTelemetryStateMock = vi.mocked(TelemetryService.instance.updateTelemetryState) + updateTelemetryStateMock.mockClear() + + // The real vscode.env.onDidChangeTelemetryEnabled event carries no payload; the handler + // must read the current vscode.env.isTelemetryEnabled value, not any argument it's called with. + const onDidChangeHandler = vi.mocked(vscode.env.onDidChangeTelemetryEnabled).mock.calls[0][0] + onDidChangeHandler(undefined as never) + + expect(updateTelemetryStateMock).toHaveBeenCalledWith(true) + }) + + test("treats a disabled stored setting as opted out even when VS Code telemetry is enabled", async () => { + const vscode = await import("vscode") + const { TelemetryService } = await import("@roo-code/telemetry") + const { ContextProxy } = await import("../core/config/ContextProxy") + + const mockContextProxyInstance = await ( + ContextProxy.getInstance as unknown as () => Promise<{ getGlobalState: ReturnType }> + )() + vi.mocked(mockContextProxyInstance.getGlobalState).mockReturnValue("disabled") + ;(vscode.env as { isTelemetryEnabled: boolean }).isTelemetryEnabled = true + + const { activate } = await import("../extension") + await activate(mockContext) + + const updateTelemetryStateMock = vi.mocked(TelemetryService.instance.updateTelemetryState) + updateTelemetryStateMock.mockClear() + + const onDidChangeHandler = vi.mocked(vscode.env.onDidChangeTelemetryEnabled).mock.calls[0][0] + onDidChangeHandler(undefined as never) + + expect(updateTelemetryStateMock).toHaveBeenCalledWith(false) + }) + + test("treats VS Code's live telemetry-disabled signal as opted out even when the stored setting is enabled", async () => { + const vscode = await import("vscode") + const { TelemetryService } = await import("@roo-code/telemetry") + const { ContextProxy } = await import("../core/config/ContextProxy") + + const mockContextProxyInstance = await ( + ContextProxy.getInstance as unknown as () => Promise<{ getGlobalState: ReturnType }> + )() + vi.mocked(mockContextProxyInstance.getGlobalState).mockReturnValue("enabled") + ;(vscode.env as { isTelemetryEnabled: boolean }).isTelemetryEnabled = true + + const { activate } = await import("../extension") + await activate(mockContext) + + const updateTelemetryStateMock = vi.mocked(TelemetryService.instance.updateTelemetryState) + updateTelemetryStateMock.mockClear() + + // Simulate the user turning off VS Code's global telemetry toggle: the live env value + // flips before the event fires, and the handler must honor it rather than only the + // stored extension setting. + ;(vscode.env as { isTelemetryEnabled: boolean }).isTelemetryEnabled = false + + const onDidChangeHandler = vi.mocked(vscode.env.onDidChangeTelemetryEnabled).mock.calls[0][0] + onDidChangeHandler(undefined as never) + + expect(updateTelemetryStateMock).toHaveBeenCalledWith(false) + }) + + test("pushes a state update to the webview so its own PostHog client picks up the new vscode.env.isTelemetryEnabled value", async () => { + const vscode = await import("vscode") + const { ClineProvider } = await import("../core/webview/ClineProvider") + + const { activate } = await import("../extension") + await activate(mockContext) + + const visibleInstance = ( + ClineProvider as unknown as { + getVisibleInstance(): { postStateToWebviewWithoutClineMessages: ReturnType } + } + ).getVisibleInstance() + vi.mocked(visibleInstance.postStateToWebviewWithoutClineMessages).mockClear() + + const onDidChangeHandler = vi.mocked(vscode.env.onDidChangeTelemetryEnabled).mock.calls[0][0] + onDidChangeHandler(undefined as never) + + expect(visibleInstance.postStateToWebviewWithoutClineMessages).toHaveBeenCalled() + }) + }) + + describe("deactivate", () => { + beforeEach(() => { + vi.resetModules() + }) + + test("still runs terminal cleanup when telemetry shutdown rejects", async () => { + const { TelemetryService } = await import("@roo-code/telemetry") + const { Terminal } = await import("../integrations/terminal/Terminal") + const { TerminalRegistry } = await import("../integrations/terminal/TerminalRegistry") + + vi.mocked(TelemetryService.instance.shutdown).mockRejectedValue(new Error("shutdown failed")) + const setTerminalProfileSpy = vi.spyOn(Terminal, "setTerminalProfile") + + const { activate, deactivate } = await import("../extension") + await activate(mockContext) + + await expect(deactivate()).resolves.toBeUndefined() + + expect(setTerminalProfileSpy).toHaveBeenCalledWith(undefined) + expect(TerminalRegistry.cleanup).toHaveBeenCalledTimes(1) + + setTerminalProfileSpy.mockRestore() + }) + + // Review finding: every other TelemetryService call site touched by this PR checks + // hasInstance() first; deactivate()'s shutdown call didn't. Not a crash today (the mock + // always resolves), but TelemetryService.instance throws for real if no instance exists, + // so the guard keeps this call site consistent with the rest of the file. + test("does not touch TelemetryService.instance when no instance exists", async () => { + const { TelemetryService } = await import("@roo-code/telemetry") + const { Terminal } = await import("../integrations/terminal/Terminal") + const { TerminalRegistry } = await import("../integrations/terminal/TerminalRegistry") + + const setTerminalProfileSpy = vi.spyOn(Terminal, "setTerminalProfile") + + const { activate, deactivate } = await import("../extension") + await activate(mockContext) + + // Flip to false only after activate() completes, so this only exercises + // deactivate()'s own guard rather than any hasInstance() check during activation. + vi.mocked(TelemetryService.hasInstance).mockReturnValue(false) + + // Model the real singleton failure mode: TelemetryService.instance throws when no + // instance exists. If deactivate()'s hasInstance() guard were ever removed, this + // throw would surface instead of the assertion below silently passing regardless. + const instanceGetterSpy = vi.spyOn(TelemetryService, "instance", "get").mockImplementation(() => { + throw new Error("TelemetryService not initialized") + }) + + await expect(deactivate()).resolves.toBeUndefined() + + expect(instanceGetterSpy).not.toHaveBeenCalled() + expect(mockTelemetryServiceInstance.shutdown).not.toHaveBeenCalled() + expect(setTerminalProfileSpy).toHaveBeenCalledWith(undefined) + expect(TerminalRegistry.cleanup).toHaveBeenCalledTimes(1) + + instanceGetterSpy.mockRestore() + + setTerminalProfileSpy.mockRestore() + }) + }) }) diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 021a2fba91..2d00f25107 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -2593,6 +2593,7 @@ export class ClineProvider const telemetryKey = process.env.POSTHOG_API_KEY const machineId = vscode.env.machineId + const vscodeTelemetryEnabled = vscode.env.isTelemetryEnabled const mergedAllowedCommands = this.mergeAllowedCommands(allowedCommands) const mergedDeniedCommands = this.mergeDeniedCommands(deniedCommands) const cwd = this.cwd @@ -2696,6 +2697,7 @@ export class ClineProvider telemetrySetting, telemetryKey, machineId, + vscodeTelemetryEnabled, showRooIgnoredFiles: showRooIgnoredFiles ?? false, enableSubfolderRules: enableSubfolderRules ?? false, language: language ?? formatLanguage(vscode.env.language), diff --git a/src/core/webview/__tests__/telemetrySettingsTracking.spec.ts b/src/core/webview/__tests__/telemetrySettingsTracking.spec.ts index a99c8862a3..0f1e0e1315 100644 --- a/src/core/webview/__tests__/telemetrySettingsTracking.spec.ts +++ b/src/core/webview/__tests__/telemetrySettingsTracking.spec.ts @@ -1,6 +1,6 @@ import { describe, it, expect, vi, beforeEach } from "vitest" import { TelemetryService } from "@roo-code/telemetry" -import { TelemetryEventName, type TelemetrySetting } from "@roo-code/types" +import { TelemetryEventName, type TelemetrySetting, isTelemetryOptedIn } from "@roo-code/types" describe("Telemetry Settings Tracking", () => { let mockTelemetryService: { @@ -31,8 +31,8 @@ describe("Telemetry Settings Tracking", () => { const newSetting = "disabled" as TelemetrySetting // Simulate the logic from webviewMessageHandler - const isOptedIn = newSetting !== "disabled" - const wasPreviouslyOptedIn = previousSetting !== "disabled" + const isOptedIn = isTelemetryOptedIn(newSetting) + const wasPreviouslyOptedIn = isTelemetryOptedIn(previousSetting) // If turning telemetry OFF, fire event BEFORE disabling if (wasPreviouslyOptedIn && !isOptedIn && TelemetryService.hasInstance()) { @@ -50,12 +50,12 @@ describe("Telemetry Settings Tracking", () => { expect(mockTelemetryService.updateTelemetryState).toHaveBeenCalledWith(false) }) - it("should fire event when going from unset to disabled", () => { + it("should fire an opt-out event when going from unset to disabled (explicit Decline)", () => { const previousSetting = "unset" as TelemetrySetting const newSetting = "disabled" as TelemetrySetting - const isOptedIn = newSetting !== "disabled" - const wasPreviouslyOptedIn = previousSetting !== "disabled" + const isOptedIn = isTelemetryOptedIn(newSetting) + const wasPreviouslyOptedIn = isTelemetryOptedIn(previousSetting) if (wasPreviouslyOptedIn && !isOptedIn && TelemetryService.hasInstance()) { TelemetryService.instance.captureTelemetrySettingsChanged(previousSetting, newSetting) @@ -63,7 +63,10 @@ describe("Telemetry Settings Tracking", () => { TelemetryService.instance.updateTelemetryState(isOptedIn) + // "unset" is opted in under the disclosed opt-out default, so unset -> disabled + // is a genuine opt-out transition. expect(mockTelemetryService.captureTelemetrySettingsChanged).toHaveBeenCalledWith("unset", "disabled") + expect(mockTelemetryService.updateTelemetryState).toHaveBeenCalledWith(false) }) }) @@ -72,8 +75,8 @@ describe("Telemetry Settings Tracking", () => { const previousSetting = "disabled" as TelemetrySetting const newSetting = "enabled" as TelemetrySetting - const isOptedIn = newSetting !== "disabled" - const wasPreviouslyOptedIn = previousSetting !== "disabled" + const isOptedIn = isTelemetryOptedIn(newSetting) + const wasPreviouslyOptedIn = isTelemetryOptedIn(previousSetting) // Update the telemetry state first TelemetryService.instance.updateTelemetryState(isOptedIn) @@ -95,8 +98,8 @@ describe("Telemetry Settings Tracking", () => { const previousSetting = "enabled" as TelemetrySetting const newSetting = "enabled" as TelemetrySetting - const isOptedIn = newSetting !== "disabled" - const wasPreviouslyOptedIn = previousSetting !== "disabled" + const isOptedIn = isTelemetryOptedIn(newSetting) + const wasPreviouslyOptedIn = isTelemetryOptedIn(previousSetting) // Neither condition should be met if (wasPreviouslyOptedIn && !isOptedIn && TelemetryService.hasInstance()) { @@ -114,14 +117,13 @@ describe("Telemetry Settings Tracking", () => { expect(mockTelemetryService.updateTelemetryState).toHaveBeenCalledWith(true) }) - it("should fire event when going from unset to enabled (telemetry banner close)", () => { + it("should not fire an event when going from unset to enabled (already opted in by default)", () => { const previousSetting = "unset" as TelemetrySetting const newSetting = "enabled" as TelemetrySetting - const isOptedIn = newSetting !== "disabled" - const wasPreviouslyOptedIn = previousSetting !== "disabled" + const isOptedIn = isTelemetryOptedIn(newSetting) + const wasPreviouslyOptedIn = isTelemetryOptedIn(previousSetting) - // For unset -> enabled, both are opted in, so no event should fire if (wasPreviouslyOptedIn && !isOptedIn && TelemetryService.hasInstance()) { TelemetryService.instance.captureTelemetrySettingsChanged(previousSetting, newSetting) } @@ -132,8 +134,21 @@ describe("Telemetry Settings Tracking", () => { TelemetryService.instance.captureTelemetrySettingsChanged(previousSetting, newSetting) } - // unset is treated as opted-in, so no event should fire + // "unset" is already opted in under the disclosed opt-out default, so explicit + // Accept (unset -> enabled) is a no-op transition, not a new opt-in. expect(mockTelemetryService.captureTelemetrySettingsChanged).not.toHaveBeenCalled() + expect(mockTelemetryService.updateTelemetryState).toHaveBeenCalledWith(true) + }) + }) + + describe("neutral banner dismiss ('unset' left as-is)", () => { + it("leaves the disclosed opt-out default in effect while the setting remains unset", () => { + // A neutral dismiss of the consent banner sends no telemetrySetting message at + // all, so the stored setting stays "unset". Confirm "unset" alone -- with no + // transition, and no affirmative choice recorded either way -- resolves to the + // disclosed default (telemetry on) rather than silently opting the user in via + // dismissal itself. + expect(isTelemetryOptedIn("unset" as TelemetrySetting)).toBe(true) }) }) diff --git a/src/core/webview/__tests__/webviewMessageHandler.spec.ts b/src/core/webview/__tests__/webviewMessageHandler.spec.ts index 3070ca532a..815eb08683 100644 --- a/src/core/webview/__tests__/webviewMessageHandler.spec.ts +++ b/src/core/webview/__tests__/webviewMessageHandler.spec.ts @@ -11,6 +11,10 @@ vi.mock("../../../api/providers/fetchers/lmstudio", () => ({ getLMStudioModels: vi.fn(), })) +vi.mock("../../../integrations/theme/getTheme", () => ({ + getTheme: vi.fn().mockResolvedValue({}), +})) + vi.mock("../../../integrations/openai-codex/oauth", () => ({ openAiCodexOAuthManager: { getAccessToken: vi.fn(), @@ -55,6 +59,16 @@ vi.mock("../rulesMessageHandler", () => ({ handleOpenRulesDirectory: vi.fn(), })) +vi.mock("@roo-code/telemetry", () => ({ + TelemetryService: { + hasInstance: vi.fn().mockReturnValue(false), + instance: { + updateTelemetryState: vi.fn(), + captureTelemetrySettingsChanged: vi.fn(), + }, + }, +})) + import type { ModelRecord } from "@roo-code/types" import { webviewMessageHandler } from "../webviewMessageHandler" @@ -132,6 +146,9 @@ vi.mock("vscode", () => { commands: { executeCommand: vi.fn().mockResolvedValue(undefined), }, + env: { + isTelemetryEnabled: true, + }, } }) @@ -1864,3 +1881,265 @@ describe("webviewMessageHandler - kimiCodeSignOut", () => { expect(vscode.window.showErrorMessage).toHaveBeenCalledWith("Kimi Code sign out failed.") }) }) + +describe("webviewMessageHandler - telemetrySetting", () => { + beforeEach(() => { + vi.clearAllMocks() + vi.mocked(vscode.env).isTelemetryEnabled = true + }) + + // Regression test: TelemetryService.updateTelemetryState must be gated on + // vscode.env.isTelemetryEnabled in addition to the stored setting, matching + // extension.ts's onDidChangeTelemetryEnabled listener. Without this AND, a user + // clicking Accept in the webview could re-enable telemetry even while VS Code's + // global telemetry toggle is off. + it("does not enable telemetry when the user accepts but VS Code's global telemetry toggle is off", async () => { + const { TelemetryService } = await import("@roo-code/telemetry") + vi.mocked(TelemetryService.hasInstance).mockReturnValue(true) + vi.mocked(vscode.env).isTelemetryEnabled = false + vi.mocked(mockClineProvider.contextProxy.getValue).mockReturnValue(undefined) + + await webviewMessageHandler(mockClineProvider, { type: "telemetrySetting", text: "enabled" }) + + expect(TelemetryService.instance.updateTelemetryState).toHaveBeenCalledWith(false) + }) + + it("enables telemetry when the user accepts and VS Code's global telemetry toggle is on", async () => { + const { TelemetryService } = await import("@roo-code/telemetry") + vi.mocked(TelemetryService.hasInstance).mockReturnValue(true) + vi.mocked(vscode.env).isTelemetryEnabled = true + vi.mocked(mockClineProvider.contextProxy.getValue).mockReturnValue(undefined) + + await webviewMessageHandler(mockClineProvider, { type: "telemetrySetting", text: "enabled" }) + + expect(TelemetryService.instance.updateTelemetryState).toHaveBeenCalledWith(true) + }) + + it("keeps telemetry disabled when the user declines, regardless of VS Code's global toggle", async () => { + const { TelemetryService } = await import("@roo-code/telemetry") + vi.mocked(TelemetryService.hasInstance).mockReturnValue(true) + vi.mocked(vscode.env).isTelemetryEnabled = true + vi.mocked(mockClineProvider.contextProxy.getValue).mockReturnValue(undefined) + + await webviewMessageHandler(mockClineProvider, { type: "telemetrySetting", text: "disabled" }) + + expect(TelemetryService.instance.updateTelemetryState).toHaveBeenCalledWith(false) + }) + + // Finding #12 regression: without serialization, two concurrent "telemetrySetting" messages + // each capture their own isOptedIn in a closure and apply it to TelemetryService whenever + // their own persistence write resolves -- with no ordering guarantee between the two + // invocations. A slow first write racing a fast second write could let the *first* + // message's (now-stale) intent win the live telemetry state, even though the *second* + // message reflects the user's actual final choice. + it("applies the most recently sent telemetrySetting last, even if an earlier message's write is slower", async () => { + const { TelemetryService } = await import("@roo-code/telemetry") + vi.mocked(TelemetryService.hasInstance).mockReturnValue(true) + vi.mocked(vscode.env).isTelemetryEnabled = true + + // Track the "stored" setting so the second call's getGlobalState read reflects + // whatever the first call has (or hasn't yet) written -- mirrors ContextProxy's real + // synchronous stateCache update inside setValue. + let storedSetting: string | undefined + vi.mocked(mockClineProvider.contextProxy.getValue).mockImplementation(() => storedSetting) + + let resolveSlowWrite!: () => void + const slowWrite = new Promise((resolve) => { + resolveSlowWrite = resolve + }) + + vi.mocked(mockClineProvider.contextProxy.setValue).mockImplementation(async (_key, value) => { + if (value === "disabled") { + // First message's write is slow -- resolves only after we explicitly release it + // below, once the second (fast) message has already been sent. + await slowWrite + } + storedSetting = value as string + }) + + // First message: turn telemetry off (slow write). + const first = webviewMessageHandler(mockClineProvider, { type: "telemetrySetting", text: "disabled" }) + + // Second message: turn telemetry back on (fast write), sent immediately after. + const second = webviewMessageHandler(mockClineProvider, { type: "telemetrySetting", text: "enabled" }) + + // Now let the first message's write proceed. + resolveSlowWrite() + + await Promise.all([first, second]) + + // The user's final, most-recently-sent choice was "enabled" -- the live telemetry + // state must reflect that, not "disabled" from the stale, slower first message. + const calls = vi.mocked(TelemetryService.instance.updateTelemetryState).mock.calls + expect(calls.at(-1)).toEqual([true]) + }) + + // CodeRabbit follow-up on the finding #12 fix: webviewDidLaunch's telemetry init read state + // via an async provider.getStateToPostToWebview().then(...) continuation, outside + // telemetrySettingQueue -- so it could resolve after a concurrent "telemetrySetting" message + // and clobber that message's queued (correct) update with a stale value. webviewDidLaunch now + // reads getGlobalState synchronously and is routed through the same queue. + it("does not let webviewDidLaunch's telemetry init race and clobber a concurrent telemetrySetting message", async () => { + const { TelemetryService } = await import("@roo-code/telemetry") + vi.mocked(TelemetryService.hasInstance).mockReturnValue(true) + vi.mocked(vscode.env).isTelemetryEnabled = true + + // webviewDidLaunch starts out "unset" (disclosed opt-out default -- opted in). Scoped to + // the "telemetrySetting" key specifically -- webviewDidLaunch also calls + // updateGlobalState("customModes", ...) through the same contextProxy mock, which must + // not clobber storedSetting. + let storedSetting: string | undefined = "unset" + vi.mocked(mockClineProvider.contextProxy.getValue).mockImplementation((key: string) => + key === "telemetrySetting" ? storedSetting : undefined, + ) + vi.mocked(mockClineProvider.contextProxy.setValue).mockImplementation(async (key: string, value) => { + if (key === "telemetrySetting") { + storedSetting = value as string + } + }) + + vi.mocked(mockClineProvider.customModesManager.getCustomModes).mockResolvedValue([]) + const providerForLaunch = mockClineProvider as unknown as { + getMcpHub: ReturnType + providerSettingsManager: { listConfig: ReturnType } + getStateToPostToWebview: ReturnType + } + providerForLaunch.getMcpHub = vi.fn().mockReturnValue(undefined) + providerForLaunch.providerSettingsManager = { + listConfig: vi.fn().mockResolvedValue(undefined), + } + + // Deferred-promise handshake instead of setTimeout delays, so ordering is enforced + // explicitly rather than by racing real clock delays. Signals when webviewDidLaunch has + // taken its (pre-fix) state snapshot -- only fires under the *old* code path + // (provider.getStateToPostToWebview().then(...)); the fix never calls it at all. + let snapshotTaken!: () => void + const snapshotTakenPromise = new Promise((resolve) => { + snapshotTaken = resolve + }) + let releaseSnapshot!: () => void + const snapshotReleased = new Promise((resolve) => { + releaseSnapshot = resolve + }) + + // Snapshots storedSetting at call time (mirroring the real ClineProvider building its + // state object synchronously before any internal awaits), signals it was taken, then + // waits until the test explicitly releases it -- by which point the concurrent + // telemetrySetting write below has already landed, making the snapshot genuinely stale + // once its .then() callback finally runs. + providerForLaunch.getStateToPostToWebview = vi.fn().mockImplementation(async () => { + const snapshot = storedSetting + snapshotTaken() + await snapshotReleased + return { telemetrySetting: snapshot } + }) + + // webviewDidLaunch fires first (e.g. webview reload) -- its telemetry init is now queued + // behind telemetrySettingQueue rather than resolving independently. + const launch = webviewMessageHandler(mockClineProvider, { type: "webviewDidLaunch" }) + + // Wait for webviewDidLaunch to either take its (pre-fix) snapshot, or flush a fixed + // number of microtask turns as a same-tick fallback for the fixed code path (which never + // triggers that signal) -- enough for its synchronous prefix (await getCustomModes(), + // await updateGlobalState()) to run, without relying on a wall-clock timer. + await Promise.race([ + snapshotTakenPromise, + (async () => { + for (let i = 0; i < 10; i++) { + await Promise.resolve() + } + })(), + ]) + + // A concurrent "telemetrySetting" message turns telemetry off, and is awaited to + // completion -- including its own updateTelemetryState(false) call -- *before* the + // deferred (pre-fix-only) snapshot below is released. Against the pre-fix code, this + // proves the snapshot it captured earlier ("unset") is genuinely stale by the time its + // .then() callback finally runs: the user's real, later choice already landed. + const disable = webviewMessageHandler(mockClineProvider, { type: "telemetrySetting", text: "disabled" }) + await disable + + // Now release the deferred snapshot so a getStateToPostToWebview() call, if the old code + // path is exercised, resolves (with its already-captured, now-stale value) only after + // the disable write above has fully landed. + const snapshotResolved = vi.mocked(providerForLaunch.getStateToPostToWebview).mock.results[0]?.value as + | Promise + | undefined + releaseSnapshot() + + await Promise.all([launch, snapshotResolved]) + + // webviewDidLaunch's telemetry init is fire-and-forget from the handler's own point of + // view (the "webviewDidLaunch" case doesn't await it), so even awaiting + // getStateToPostToWebview() directly isn't enough to observe its .then() callback -- + // flush one more microtask turn for that callback to run. + await Promise.resolve() + + // The user's explicit "disabled" choice must be the final state -- webviewDidLaunch's + // queued re-application of the (by-then-stale) "unset"/opted-in state must not run after + // and override it. + const calls = vi.mocked(TelemetryService.instance.updateTelemetryState).mock.calls + expect(calls.at(-1)).toEqual([false]) + }) + + // Review finding: webviewDidLaunch's queued telemetry update wasn't awaited by the + // "webviewDidLaunch" case, so a thrown error inside it was only ever caught by a later, + // unrelated queue link's leading .catch(() => undefined) -- silently swallowed rather than + // logged. Now awaited with its own .catch that logs via provider.log. + it("logs an error via provider.log if the queued telemetry init throws on launch", async () => { + const { TelemetryService } = await import("@roo-code/telemetry") + vi.mocked(TelemetryService.hasInstance).mockReturnValue(true) + + vi.mocked(mockClineProvider.contextProxy.getValue).mockImplementation((key: string) => { + if (key === "telemetrySetting") { + throw new Error("contextProxy read failed") + } + return undefined + }) + vi.mocked(mockClineProvider.customModesManager.getCustomModes).mockResolvedValue([]) + const providerForLaunch = mockClineProvider as unknown as { + getMcpHub: ReturnType + providerSettingsManager: { listConfig: ReturnType } + getStateToPostToWebview: ReturnType + } + providerForLaunch.getMcpHub = vi.fn().mockReturnValue(undefined) + providerForLaunch.providerSettingsManager = { listConfig: vi.fn().mockResolvedValue(undefined) } + providerForLaunch.getStateToPostToWebview = vi.fn().mockResolvedValue({ telemetrySetting: "unset" }) + + await webviewMessageHandler(mockClineProvider, { type: "webviewDidLaunch" }) + + expect(mockClineProvider.log).toHaveBeenCalledWith( + expect.stringContaining("Error initializing telemetry state on launch"), + ) + }) + + // CodeRabbit finding: webviewDidLaunch's queued telemetry update called + // TelemetryService.instance directly, unlike the "telemetrySetting" case a few lines + // below which checks hasInstance() first. If webviewDidLaunch fires before the service + // is created (e.g. during activation), TelemetryService.instance throws -- and since + // this whole chain isn't awaited by the "webviewDidLaunch" case, that throw becomes an + // unhandled promise rejection instead of a no-op. + it("does not throw or update telemetry state when webviewDidLaunch fires before TelemetryService exists", async () => { + const { TelemetryService } = await import("@roo-code/telemetry") + vi.mocked(TelemetryService.hasInstance).mockReturnValue(false) + + vi.mocked(mockClineProvider.contextProxy.getValue).mockReturnValue("unset") + vi.mocked(mockClineProvider.customModesManager.getCustomModes).mockResolvedValue([]) + const providerForLaunch = mockClineProvider as unknown as { + getMcpHub: ReturnType + providerSettingsManager: { listConfig: ReturnType } + getStateToPostToWebview: ReturnType + } + providerForLaunch.getMcpHub = vi.fn().mockReturnValue(undefined) + providerForLaunch.providerSettingsManager = { listConfig: vi.fn().mockResolvedValue(undefined) } + providerForLaunch.getStateToPostToWebview = vi.fn().mockResolvedValue({ telemetrySetting: "unset" }) + + await expect(webviewMessageHandler(mockClineProvider, { type: "webviewDidLaunch" })).resolves.not.toThrow() + + // The queued telemetry update is fire-and-forget from the handler's own point of + // view -- flush a microtask turn so its .then() callback runs before asserting. + await Promise.resolve() + + expect(TelemetryService.instance.updateTelemetryState).not.toHaveBeenCalled() + }) +}) diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index 648269c1b5..8bf1c64777 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -29,6 +29,7 @@ import { OpenAiModelsMessageType, RouterModelsMessageType, VsCodeLmModelsMessageType, + isTelemetryOptedIn, } from "@roo-code/types" import { customToolRegistry } from "@roo-code/core" import { CloudService } from "@roo-code/cloud" @@ -93,6 +94,15 @@ import { getLMStudioModels } from "../../api/providers/fetchers/lmstudio" const ALLOWED_VSCODE_SETTINGS = new Set(["terminal.integrated.inheritEnv"]) +// Serializes handling of "telemetrySetting" messages. Each invocation reads the previous +// setting, awaits a persistence write, then applies the new live telemetry state -- with no +// serialization, two rapid messages (e.g. a fast toggle) can interleave across those awaits: +// each invocation captures its own isOptedIn in a closure, so whichever invocation's tail end +// (TelemetryService.instance.updateTelemetryState) happens to resolve *last* wins, regardless +// of which message the user sent last. Chaining onto this promise ensures a given invocation's +// entire read-write-apply sequence completes before the next one starts. +let telemetrySettingQueue: Promise = Promise.resolve() + import { MarketplaceManager, MarketplaceItemType } from "../../services/marketplace" import { setPendingTodoList } from "../tools/UpdateTodoListTool" import { @@ -639,12 +649,37 @@ export const webviewMessageHandler = async ( ), ) - // Enable telemetry by default (when unset) or when explicitly enabled - await provider.getStateToPostToWebview().then((state) => { - const { telemetrySetting } = state - const isOptedIn = telemetrySetting !== "disabled" - TelemetryService.instance.updateTelemetryState(isOptedIn) - }) + // Telemetry is on by disclosed default: "unset" (no choice made yet) leaves that + // default in effect, same as "enabled". Only an explicit "disabled" opts out. + // vscode.env.isTelemetryEnabled is ANDed in (matching extension.ts's + // onDidChangeTelemetryEnabled listener) so a webview reload can't re-enable + // telemetry while VS Code's global toggle is off. + // + // Read the setting synchronously via getGlobalState (same as the "telemetrySetting" + // handler below) rather than awaiting provider.getStateToPostToWebview() -- that + // async gap let this continuation resolve after a concurrent "telemetrySetting" + // message's queued update and clobber it with a stale value, the same interleaving + // class of bug telemetrySettingQueue exists to prevent. Routing through the queue + // here too means webviewDidLaunch can't race a concurrent telemetrySetting message + // either. + telemetrySettingQueue = telemetrySettingQueue + .catch(() => undefined) + .then(async () => { + if (!TelemetryService.hasInstance()) { + return + } + + const telemetrySetting = getGlobalState("telemetrySetting") || "unset" + TelemetryService.instance.updateTelemetryState( + isTelemetryOptedIn(telemetrySetting) && vscode.env.isTelemetryEnabled, + ) + }) + + await telemetrySettingQueue.catch((error) => + provider.log( + `Error initializing telemetry state on launch: ${error instanceof Error ? error.message : String(error)}`, + ), + ) provider.isViewLaunched = true break @@ -2612,29 +2647,46 @@ export const webviewMessageHandler = async ( } break case "telemetrySetting": { - const telemetrySetting = message.text as TelemetrySetting - const previousSetting = getGlobalState("telemetrySetting") || "unset" - const isOptedIn = telemetrySetting !== "disabled" - const wasPreviouslyOptedIn = previousSetting !== "disabled" + // Chain onto the shared queue so a concurrent "telemetrySetting" message (e.g. a + // rapid toggle) can't interleave its read-write-apply sequence with this one -- see + // the telemetrySettingQueue comment above for why that matters. Swallow a prior + // link's rejection before chaining (rather than letting .then() propagate it) so one + // failed update can't permanently poison every subsequent telemetrySetting message + // for the rest of the session. + const thisUpdate = telemetrySettingQueue + .catch(() => undefined) + .then(async () => { + const telemetrySetting = message.text as TelemetrySetting + const previousSetting = getGlobalState("telemetrySetting") || "unset" + const isOptedIn = isTelemetryOptedIn(telemetrySetting) + const wasPreviouslyOptedIn = isTelemetryOptedIn(previousSetting) + + // If turning telemetry OFF, fire event BEFORE disabling + if (wasPreviouslyOptedIn && !isOptedIn && TelemetryService.hasInstance()) { + TelemetryService.instance.captureTelemetrySettingsChanged(previousSetting, telemetrySetting) + } - // If turning telemetry OFF, fire event BEFORE disabling - if (wasPreviouslyOptedIn && !isOptedIn && TelemetryService.hasInstance()) { - TelemetryService.instance.captureTelemetrySettingsChanged(previousSetting, telemetrySetting) - } + // Update the telemetry state. vscode.env.isTelemetryEnabled is ANDed in + // (matching extension.ts's onDidChangeTelemetryEnabled listener) so this can't + // re-enable telemetry while VS Code's global toggle is off -- the + // captureTelemetrySettingsChanged calls above/below still track the user's + // stored preference transition on its own, independent of that live toggle. + await updateGlobalState("telemetrySetting", telemetrySetting) - // Update the telemetry state - await updateGlobalState("telemetrySetting", telemetrySetting) + if (TelemetryService.hasInstance()) { + TelemetryService.instance.updateTelemetryState(isOptedIn && vscode.env.isTelemetryEnabled) + } - if (TelemetryService.hasInstance()) { - TelemetryService.instance.updateTelemetryState(isOptedIn) - } + // If turning telemetry ON, fire event AFTER enabling + if (!wasPreviouslyOptedIn && isOptedIn && TelemetryService.hasInstance()) { + TelemetryService.instance.captureTelemetrySettingsChanged(previousSetting, telemetrySetting) + } - // If turning telemetry ON, fire event AFTER enabling - if (!wasPreviouslyOptedIn && isOptedIn && TelemetryService.hasInstance()) { - TelemetryService.instance.captureTelemetrySettingsChanged(previousSetting, telemetrySetting) - } + await provider.postStateToWebview() + }) + telemetrySettingQueue = thisUpdate - await provider.postStateToWebview() + await thisUpdate break } case "debugSetting": { diff --git a/src/eslint-suppressions.json b/src/eslint-suppressions.json index f405adc8df..6903a77ab0 100644 --- a/src/eslint-suppressions.json +++ b/src/eslint-suppressions.json @@ -24,11 +24,6 @@ "count": 6 } }, - "__tests__/extension.spec.ts": { - "@typescript-eslint/no-explicit-any": { - "count": 2 - } - }, "__tests__/history-resume-delegation.spec.ts": { "@typescript-eslint/no-explicit-any": { "count": 72 diff --git a/src/extension.ts b/src/extension.ts index b880bee410..e618874f1a 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -16,6 +16,7 @@ if (fs.existsSync(envPath)) { } import type { CloudUserInfo, AuthState } from "@roo-code/types" +import { isTelemetryOptedIn } from "@roo-code/types" import { CloudService } from "@roo-code/cloud" import { TelemetryService, PostHogTelemetryClient } from "@roo-code/telemetry" import { customToolRegistry } from "@roo-code/core" @@ -173,6 +174,29 @@ export async function activate(context: vscode.ExtensionContext) { } const contextProxy = await ContextProxy.getInstance(context) + const updateTelemetryState = () => { + const telemetrySetting = contextProxy.getGlobalState("telemetrySetting") ?? "unset" + TelemetryService.instance.updateTelemetryState( + isTelemetryOptedIn(telemetrySetting) && vscode.env.isTelemetryEnabled, + ) + } + + updateTelemetryState() + + // React live to VS Code's global telemetry toggle (recommended over only reading + // telemetry.telemetryLevel, which PostHogTelemetryClient still checks as a secondary gate). + // vscode.env.isTelemetryEnabled is ANDed in directly because the deprecated + // telemetry.telemetryLevel setting the client checks doesn't reflect this live event. + context.subscriptions.push( + vscode.env.onDidChangeTelemetryEnabled(() => { + updateTelemetryState() + + // Push the new vscode.env.isTelemetryEnabled value to the webview too, so its + // own PostHog client (gated separately in TelemetryClient.ts) can't keep + // sending events after the global toggle flips off mid-session. + void ClineProvider.getVisibleInstance()?.postStateToWebviewWithoutClineMessages() + }), + ) // Initialize code index managers for all workspace folders. const codeIndexManagers: CodeIndexManager[] = [] @@ -389,12 +413,14 @@ export async function deactivate() { await McpServerManager.cleanup(extensionContext) - try { - await TelemetryService.instance.shutdown() - } catch (error) { - outputChannel.appendLine( - `Failed to shut down telemetry service: ${error instanceof Error ? error.message : String(error)}`, - ) + if (TelemetryService.hasInstance()) { + try { + await TelemetryService.instance.shutdown() + } catch (error) { + outputChannel.appendLine( + `Failed to shut down telemetry service: ${error instanceof Error ? error.message : String(error)}`, + ) + } } Terminal.setTerminalProfile(undefined) diff --git a/webview-ui/playwright/vscode-theme-dark.css b/webview-ui/playwright/vscode-theme-dark.css index 30d49f968b..0621461655 100644 --- a/webview-ui/playwright/vscode-theme-dark.css +++ b/webview-ui/playwright/vscode-theme-dark.css @@ -87,3 +87,27 @@ body { #root { padding: 16px; } + +/* The @vscode/webview-ui-toolkit/react mock (aliased in for CT, same as Vitest) renders + VSCodeButton as a bare + ), })) vi.mock("@/components/ui", async (importOriginal) => { diff --git a/webview-ui/src/components/common/TelemetryBanner.tsx b/webview-ui/src/components/common/TelemetryBanner.tsx index 3d39b17115..6ed058d8bf 100644 --- a/webview-ui/src/components/common/TelemetryBanner.tsx +++ b/webview-ui/src/components/common/TelemetryBanner.tsx @@ -1,6 +1,6 @@ -import { memo, useState } from "react" +import { memo } from "react" import { Trans } from "react-i18next" -import { VSCodeLink } from "@vscode/webview-ui-toolkit/react" +import { VSCodeButton, VSCodeLink } from "@vscode/webview-ui-toolkit/react" import type { TelemetrySetting } from "@roo-code/types" @@ -9,13 +9,15 @@ import { useAppTranslation } from "@src/i18n/TranslationContext" const TelemetryBanner = () => { const { t } = useAppTranslation() - const [isDismissed, setIsDismissed] = useState(false) - const handleClose = () => { - setIsDismissed(true) + const handleAccept = () => { vscode.postMessage({ type: "telemetrySetting", text: "enabled" satisfies TelemetrySetting }) } + const handleDecline = () => { + vscode.postMessage({ type: "telemetrySetting", text: "disabled" satisfies TelemetrySetting }) + } + const handleOpenSettings = () => { window.postMessage({ type: "action", @@ -24,22 +26,10 @@ const TelemetryBanner = () => { }) } - if (isDismissed) { - return null - } - return ( -
- {/* Close button (X) */} - - +
{t("welcome:telemetry.helpImprove")}
-
+
{ }} />
+
+ + {t("welcome:telemetry.accept")} + + + {t("welcome:telemetry.decline")} + +
) } diff --git a/webview-ui/src/components/common/__tests__/TelemetryBanner.spec.tsx b/webview-ui/src/components/common/__tests__/TelemetryBanner.spec.tsx new file mode 100644 index 0000000000..ddffaff20a --- /dev/null +++ b/webview-ui/src/components/common/__tests__/TelemetryBanner.spec.tsx @@ -0,0 +1,61 @@ +import { render, screen, fireEvent } from "@testing-library/react" +import { describe, it, expect, vi, beforeEach } from "vitest" + +import TelemetryBanner from "../TelemetryBanner" + +const mockPostMessage = vi.fn() +vi.mock("@src/utils/vscode", () => ({ + vscode: { + postMessage: (message: any) => mockPostMessage(message), + }, +})) + +vi.mock("@src/i18n/TranslationContext", () => ({ + useAppTranslation: () => ({ + t: (key: string) => { + const translations: Record = { + "welcome:telemetry.helpImprove": "Help Improve Zoo Code", + "welcome:telemetry.helpImproveMessage": "Zoo Code collects error and usage data...", + "welcome:telemetry.accept": "Accept", + "welcome:telemetry.decline": "Decline", + } + return translations[key] || key + }, + }), +})) + +describe("TelemetryBanner", () => { + beforeEach(() => { + mockPostMessage.mockClear() + }) + + it("renders explicit Accept and Decline actions", () => { + render() + + expect(screen.getByRole("button", { name: "Accept" })).toBeInTheDocument() + expect(screen.getByRole("button", { name: "Decline" })).toBeInTheDocument() + }) + + it("sends an enabled setting when Accept is clicked", () => { + render() + + fireEvent.click(screen.getByRole("button", { name: "Accept" })) + + expect(mockPostMessage).toHaveBeenCalledWith({ type: "telemetrySetting", text: "enabled" }) + }) + + it("sends a disabled setting when Decline is clicked", () => { + render() + + fireEvent.click(screen.getByRole("button", { name: "Decline" })) + + expect(mockPostMessage).toHaveBeenCalledWith({ type: "telemetrySetting", text: "disabled" }) + }) + + it("requires an explicit telemetry choice", () => { + render() + + expect(screen.getAllByRole("button").map((button) => button.textContent)).toEqual(["Accept", "Decline"]) + expect(mockPostMessage).not.toHaveBeenCalled() + }) +}) diff --git a/webview-ui/src/components/common/__tests__/TelemetryBanner.visual.fixture.tsx b/webview-ui/src/components/common/__tests__/TelemetryBanner.visual.fixture.tsx new file mode 100644 index 0000000000..0df2d5b226 --- /dev/null +++ b/webview-ui/src/components/common/__tests__/TelemetryBanner.visual.fixture.tsx @@ -0,0 +1,18 @@ +import React from "react" +import { I18nextProvider } from "react-i18next" + +import { TranslationContext } from "@src/i18n/TranslationContext" +import TelemetryBanner from "../TelemetryBanner" +import { visualTestI18n, visualTestTranslations } from "./TelemetryBanner.visual.i18n" + +export const TelemetryBannerFixture = () => ( + + visualTestTranslations[key] ?? key, + i18n: null as unknown as typeof import("../../../i18n/setup").default, + }}> + + + +) diff --git a/webview-ui/src/components/common/__tests__/TelemetryBanner.visual.i18n.ts b/webview-ui/src/components/common/__tests__/TelemetryBanner.visual.i18n.ts new file mode 100644 index 0000000000..95e7a8d1b6 --- /dev/null +++ b/webview-ui/src/components/common/__tests__/TelemetryBanner.visual.i18n.ts @@ -0,0 +1,36 @@ +import i18next from "i18next" +import { initReactI18next } from "react-i18next" + +export const visualTestTranslations: Record = { + "welcome:telemetry.helpImprove": "Help Improve Zoo Code", + "welcome:telemetry.helpImproveMessage": + "Zoo Code collects error and usage data, linked to a per-install identifier, to help us fix bugs and improve the extension. This telemetry does not collect your code or prompts. You can turn this off in settings.", + "welcome:telemetry.accept": "Accept", + "welcome:telemetry.decline": "Decline", +} + +// Trans reads from its own react-i18next instance rather than the useAppTranslation +// context, so it needs a real (if minimal) i18next init to resolve helpImproveMessage +// and the settingsLink interpolation instead of rendering nothing. init() returns a +// promise even for inline resources, so callers must await it before mounting. +export const visualTestI18n = i18next.createInstance() + +export const visualTestI18nReady = visualTestI18n.use(initReactI18next).init({ + lng: "en", + fallbackLng: "en", + ns: ["welcome"], + defaultNS: "welcome", + resources: { + en: { + welcome: { + telemetry: { + helpImprove: visualTestTranslations["welcome:telemetry.helpImprove"], + helpImproveMessage: visualTestTranslations["welcome:telemetry.helpImproveMessage"], + accept: visualTestTranslations["welcome:telemetry.accept"], + decline: visualTestTranslations["welcome:telemetry.decline"], + }, + }, + }, + }, + interpolation: { escapeValue: false }, +}) diff --git a/webview-ui/src/components/common/__tests__/TelemetryBanner.visual.tsx b/webview-ui/src/components/common/__tests__/TelemetryBanner.visual.tsx new file mode 100644 index 0000000000..c8889415fe --- /dev/null +++ b/webview-ui/src/components/common/__tests__/TelemetryBanner.visual.tsx @@ -0,0 +1,18 @@ +import React from "react" + +import { expect, test } from "../../../../playwright/coverage-fixture" +import { TelemetryBannerFixture } from "./TelemetryBanner.visual.fixture" +import { visualTestI18nReady } from "./TelemetryBanner.visual.i18n" + +test("renders the telemetry consent banner in the VS Code dark theme", async ({ mount }) => { + await visualTestI18nReady + + const component = await mount() + + await component.evaluate(async () => { + await document.fonts.ready + await new Promise((resolve) => requestAnimationFrame(() => resolve())) + }) + + await expect(component).toHaveScreenshot("telemetry-banner-dark.png") +}) diff --git a/webview-ui/src/components/common/__tests__/__screenshots__/telemetry-banner-dark.png b/webview-ui/src/components/common/__tests__/__screenshots__/telemetry-banner-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..71d5f5d80e6970a471aafeb915d07aca8b0ef6cc GIT binary patch literal 12206 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 { const checked = e.target.checked === true setTelemetrySetting(checked ? "enabled" : "disabled") diff --git a/webview-ui/src/components/settings/__tests__/About.spec.tsx b/webview-ui/src/components/settings/__tests__/About.spec.tsx index 5266be8bae..e9ca86be37 100644 --- a/webview-ui/src/components/settings/__tests__/About.spec.tsx +++ b/webview-ui/src/components/settings/__tests__/About.spec.tsx @@ -151,6 +151,36 @@ describe("About", () => { ) }) + it("shows the telemetry checkbox as checked when the setting is explicitly enabled", () => { + render( + + + , + ) + + expect(screen.getByRole("checkbox", { name: /telemetry/i })).toBeChecked() + }) + + it("shows the telemetry checkbox as checked when the setting is unset (disclosed opt-out default)", () => { + render( + + + , + ) + + expect(screen.getByRole("checkbox", { name: /telemetry/i })).toBeChecked() + }) + + it("does not show the telemetry checkbox as checked when the setting is disabled", () => { + render( + + + , + ) + + expect(screen.getByRole("checkbox", { name: /telemetry/i })).not.toBeChecked() + }) + it("renders export, import, and reset buttons", () => { render( diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index fa5cc11d65..d7d8caed87 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -1002,8 +1002,8 @@ }, "footer": { "telemetry": { - "label": "Permetre informes anònims d'errors i ús", - "description": "Ajuda a millorar Zoo Code enviant dades d'ús anònimes i informes d'error. Aquesta telemetria no recull codi, prompts o informació personal. Consulta la nostra política de privacitat per a més detalls. Pots desactivar-ho en qualsevol moment." + "label": "Permetre informes d'errors i ús", + "description": "Ajuda a millorar Zoo Code enviant dades d'ús i informes d'error, vinculades a un identificador d'instal·lació en lloc del teu nom o compte. Aquesta telemetria no recull el teu codi ni les teves indicacions. Consulta la nostra política de privacitat per a més detalls. Pots desactivar-ho en qualsevol moment." }, "settings": { "import": "Importar", diff --git a/webview-ui/src/i18n/locales/ca/welcome.json b/webview-ui/src/i18n/locales/ca/welcome.json index 06b3fca6ba..6e631fd1fb 100644 --- a/webview-ui/src/i18n/locales/ca/welcome.json +++ b/webview-ui/src/i18n/locales/ca/welcome.json @@ -12,7 +12,9 @@ }, "telemetry": { "helpImprove": "Ajuda a millorar Zoo Code", - "helpImproveMessage": "Zoo Code recopila dades d'errors i ús per ajudar-nos a corregir errors i millorar l'extensió. Aquesta telemetria no recopila codi, indicacions o informació personal. Pots desactivar-la a configuració." + "helpImproveMessage": "Zoo Code recopila dades d'errors i ús, vinculades a un identificador d'instal·lació, per ajudar-nos a corregir errors i millorar l'extensió. Aquesta telemetria no recopila el teu codi ni les teves indicacions. Pots desactivar-la a configuració.", + "accept": "Accepta", + "decline": "Rebutja" }, "importSettings": "Importa la configuració" } diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index 2cb83f7893..e43c74142a 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -1002,8 +1002,8 @@ }, "footer": { "telemetry": { - "label": "Anonyme Fehler- und Nutzungsberichte zulassen", - "description": "Hilf mit, Zoo Code zu verbessern, indem du anonyme Nutzungsdaten und Fehlerberichte sendest. Diese Telemetrie sammelt keine Code-, Prompt- oder persönliche Informationen. Weitere Einzelheiten findest du in unserer Datenschutzrichtlinie." + "label": "Fehler- und Nutzungsberichte zulassen", + "description": "Hilf mit, Zoo Code zu verbessern, indem du Nutzungsdaten und Fehlerberichte sendest, die mit einer installationsbezogenen Kennung statt mit deinem Namen oder Konto verknüpft sind. Diese Telemetrie sammelt nicht deinen Code oder deine Prompts. Weitere Einzelheiten findest du in unserer Datenschutzrichtlinie." }, "settings": { "import": "Importieren", diff --git a/webview-ui/src/i18n/locales/de/welcome.json b/webview-ui/src/i18n/locales/de/welcome.json index 99eef8b9e7..5e1107bb05 100644 --- a/webview-ui/src/i18n/locales/de/welcome.json +++ b/webview-ui/src/i18n/locales/de/welcome.json @@ -12,7 +12,9 @@ }, "telemetry": { "helpImprove": "Hilf, Zoo Code zu verbessern", - "helpImproveMessage": "Zoo Code sammelt Fehler- und Nutzungsdaten, um uns dabei zu helfen, Fehler zu beheben und die Erweiterung zu verbessern. Diese Telemetrie sammelt keine Code-, Prompt- oder persönliche Informationen. Du kannst diese in den Einstellungen deaktivieren." + "helpImproveMessage": "Zoo Code sammelt Fehler- und Nutzungsdaten, verknüpft mit einer installationsbezogenen Kennung, um uns dabei zu helfen, Fehler zu beheben und die Erweiterung zu verbessern. Diese Telemetrie sammelt nicht deinen Code oder deine Prompts. Du kannst dies in den Einstellungen deaktivieren.", + "accept": "Akzeptieren", + "decline": "Ablehnen" }, "importSettings": "Einstellungen importieren" } diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index a5967792a1..4f19e0cf5c 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -1082,8 +1082,8 @@ }, "footer": { "telemetry": { - "label": "Allow anonymous error and usage reporting", - "description": "Help improve Zoo Code by sending anonymous usage data and error reports. This telemetry does not collect code, prompts or personal information. See our privacy policy for more details." + "label": "Allow error and usage reporting", + "description": "Help improve Zoo Code by sending usage data and error reports, linked to a per-install identifier rather than your name or account. This telemetry does not collect your code or prompts. See our privacy policy for more details." }, "settings": { "import": "Import", diff --git a/webview-ui/src/i18n/locales/en/welcome.json b/webview-ui/src/i18n/locales/en/welcome.json index f6bd95ee1c..6a6e977ab7 100644 --- a/webview-ui/src/i18n/locales/en/welcome.json +++ b/webview-ui/src/i18n/locales/en/welcome.json @@ -12,7 +12,9 @@ }, "telemetry": { "helpImprove": "Help Improve Zoo Code", - "helpImproveMessage": "Zoo Code collects error and usage data to help us fix bugs and improve the extension. This telemetry does not collect code, prompts or personal information. You can turn this off in settings." + "helpImproveMessage": "Zoo Code collects error and usage data, linked to a per-install identifier, to help us fix bugs and improve the extension. This telemetry does not collect your code or prompts. You can turn this off in settings.", + "accept": "Accept", + "decline": "Decline" }, "importSettings": "Import Settings" } diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index 305a8dd5d7..9dae860173 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -1002,8 +1002,8 @@ }, "footer": { "telemetry": { - "label": "Permitir informes anónimos de errores y uso", - "description": "Ayuda a mejorar Zoo Code enviando datos de uso anónimos e informes de errores. Esta telemetría no recopila código, prompts o información personal. Consulta nuestra política de privacidad para más detalles." + "label": "Permitir informes de errores y uso", + "description": "Ayuda a mejorar Zoo Code enviando datos de uso e informes de errores, vinculados a un identificador de instalación en lugar de tu nombre o cuenta. Esta telemetría no recopila tu código ni tus prompts. Consulta nuestra política de privacidad para más detalles." }, "settings": { "import": "Importar", diff --git a/webview-ui/src/i18n/locales/es/welcome.json b/webview-ui/src/i18n/locales/es/welcome.json index ddc8b358fe..40820ca451 100644 --- a/webview-ui/src/i18n/locales/es/welcome.json +++ b/webview-ui/src/i18n/locales/es/welcome.json @@ -12,7 +12,9 @@ }, "telemetry": { "helpImprove": "Ayuda a mejorar Zoo Code", - "helpImproveMessage": "Zoo Code recopila datos de errores y uso para ayudarnos a corregir errores y mejorar la extensión. Esta telemetría no recopila código, prompts o información personal. Puedes desactivar esto en la configuración." + "helpImproveMessage": "Zoo Code recopila datos de errores y uso, vinculados a un identificador de instalación, para ayudarnos a corregir errores y mejorar la extensión. Esta telemetría no recopila tu código ni tus prompts. Puedes desactivar esto en la configuración.", + "accept": "Aceptar", + "decline": "Rechazar" }, "importSettings": "Importar configuración" } diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index d5728833dd..c5d5da9082 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -1002,8 +1002,8 @@ }, "footer": { "telemetry": { - "label": "Autoriser les rapports anonymes d'erreurs et d'utilisation", - "description": "Aidez à améliorer Zoo Code en envoyant des données d'utilisation anonymes et des rapports d'erreurs. Cette télémétrie ne collecte pas de code, de prompts ou d'informations personnelles. Consultez notre politique de confidentialité pour plus de détails." + "label": "Autoriser les rapports d'erreurs et d'utilisation", + "description": "Aidez à améliorer Zoo Code en envoyant des données d'utilisation et des rapports d'erreurs, associés à un identifiant lié à l'installation plutôt qu'à votre nom ou votre compte. Cette télémétrie ne collecte pas votre code ni vos prompts. Consultez notre politique de confidentialité pour plus de détails." }, "settings": { "import": "Importer", diff --git a/webview-ui/src/i18n/locales/fr/welcome.json b/webview-ui/src/i18n/locales/fr/welcome.json index b9af536a6b..7a0f14b7df 100644 --- a/webview-ui/src/i18n/locales/fr/welcome.json +++ b/webview-ui/src/i18n/locales/fr/welcome.json @@ -12,7 +12,9 @@ }, "telemetry": { "helpImprove": "Aide à améliorer Zoo Code", - "helpImproveMessage": "Zoo Code collecte des données d'erreurs et d'utilisation pour nous aider à corriger les bugs et améliorer l'extension. Cette télémétrie ne collecte pas de code, de prompts ou d'informations personnelles. Tu peux désactiver ceci dans les paramètres." + "helpImproveMessage": "Zoo Code collecte des données d'erreurs et d'utilisation, associées à un identifiant lié à l'installation, pour nous aider à corriger les bugs et améliorer l'extension. Cette télémétrie ne collecte pas ton code ni tes prompts. Tu peux désactiver ceci dans les paramètres.", + "accept": "Accepter", + "decline": "Refuser" }, "importSettings": "Importer les paramètres" } diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index 3fce97a378..4f4dbce405 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -1002,8 +1002,8 @@ }, "footer": { "telemetry": { - "label": "गुमनाम त्रुटि और उपयोग रिपोर्टिंग की अनुमति दें", - "description": "गुमनाम उपयोग डेटा और त्रुटि रिपोर्ट भेजकर Zoo Code को बेहतर बनाने में मदद करें। यह टेलीमेट्री कोड, प्रॉम्प्ट या व्यक्तिगत जानकारी एकत्र नहीं करती। अधिक विवरण के लिए हमारी गोपनीयता नीति देखें। आप इसे कभी भी बंद कर सकते हैं।" + "label": "त्रुटि और उपयोग रिपोर्टिंग की अनुमति दें", + "description": "आपके नाम या खाते के बजाय एक इंस्टॉल-लिंक्ड पहचानकर्ता से जुड़े उपयोग डेटा और त्रुटि रिपोर्ट भेजकर Zoo Code को बेहतर बनाने में मदद करें। यह टेलीमेट्री आपका कोड या प्रॉम्प्ट एकत्र नहीं करती। अधिक विवरण के लिए हमारी गोपनीयता नीति देखें। आप इसे कभी भी बंद कर सकते हैं।" }, "settings": { "import": "इम्पोर्ट", diff --git a/webview-ui/src/i18n/locales/hi/welcome.json b/webview-ui/src/i18n/locales/hi/welcome.json index 3c3028fc0c..c683ca9818 100644 --- a/webview-ui/src/i18n/locales/hi/welcome.json +++ b/webview-ui/src/i18n/locales/hi/welcome.json @@ -12,7 +12,9 @@ }, "telemetry": { "helpImprove": "Zoo Code को बेहतर बनाने में मदद करें", - "helpImproveMessage": "Zoo Code बग ठीक करने और एक्सटेंशन को बेहतर बनाने में हमारी मदद करने के लिए त्रुटि और उपयोग डेटा एकत्र करता है। यह दूरसंचार कोड, प्रॉम्प्ट या व्यक्तिगत जानकारी एकत्र नहीं करता है। आप इसे सेटिंग्स में अक्षम कर सकते हैं।" + "helpImproveMessage": "Zoo Code बग ठीक करने और एक्सटेंशन को बेहतर बनाने में हमारी मदद करने के लिए, एक इंस्टॉल-लिंक्ड पहचानकर्ता से जुड़ा त्रुटि और उपयोग डेटा एकत्र करता है। यह टेलीमेट्री आपका कोड या प्रॉम्प्ट एकत्र नहीं करती है। आप इसे सेटिंग्स में अक्षम कर सकते हैं।", + "accept": "स्वीकार करें", + "decline": "अस्वीकार करें" }, "importSettings": "सेटिंग्स आयात करें" } diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json index bcdd0ae76d..09ad0eaa60 100644 --- a/webview-ui/src/i18n/locales/id/settings.json +++ b/webview-ui/src/i18n/locales/id/settings.json @@ -1002,8 +1002,8 @@ }, "footer": { "telemetry": { - "label": "Izinkan pelaporan error dan penggunaan anonim", - "description": "Bantu tingkatkan Zoo Code dengan mengirimkan data penggunaan anonim dan laporan error. Telemetri ini tidak mengumpulkan kode, prompt, atau informasi pribadi. Lihat kebijakan privasi kami untuk detail lebih lanjut. Anda dapat menonaktifkannya kapan saja." + "label": "Izinkan pelaporan error dan penggunaan", + "description": "Bantu tingkatkan Zoo Code dengan mengirimkan data penggunaan dan laporan error, yang terkait dengan pengenal instalasi, bukan nama atau akun Anda. Telemetri ini tidak mengumpulkan kode atau prompt Anda. Lihat kebijakan privasi kami untuk detail lebih lanjut. Anda dapat menonaktifkannya kapan saja." }, "settings": { "import": "Impor", diff --git a/webview-ui/src/i18n/locales/id/welcome.json b/webview-ui/src/i18n/locales/id/welcome.json index 9b7acd777f..430c1ae89f 100644 --- a/webview-ui/src/i18n/locales/id/welcome.json +++ b/webview-ui/src/i18n/locales/id/welcome.json @@ -12,7 +12,9 @@ }, "telemetry": { "helpImprove": "Bantu Tingkatkan Zoo Code", - "helpImproveMessage": "Zoo Code mengumpulkan data kesalahan dan penggunaan untuk membantu kami memperbaiki bug dan meningkatkan ekstensi. Telemetri ini tidak mengumpulkan kode, prompt, atau informasi pribadi. Anda dapat menonaktifkannya di pengaturan." + "helpImproveMessage": "Zoo Code mengumpulkan data kesalahan dan penggunaan, yang terkait dengan pengenal instalasi, untuk membantu kami memperbaiki bug dan meningkatkan ekstensi. Telemetri ini tidak mengumpulkan kode atau prompt Anda. Anda dapat menonaktifkannya di pengaturan.", + "accept": "Terima", + "decline": "Tolak" }, "importSettings": "Impor Pengaturan" } diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index b22fb4c652..7b06579697 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -1002,8 +1002,8 @@ }, "footer": { "telemetry": { - "label": "Consenti segnalazioni anonime di errori e utilizzo", - "description": "Aiuta a migliorare Zoo Code inviando dati di utilizzo anonimi e segnalazioni di errori. Questa telemetria non raccoglie codice, prompt o informazioni personali. Consulta la nostra informativa sulla privacy per maggiori dettagli." + "label": "Consenti segnalazioni di errori e utilizzo", + "description": "Aiuta a migliorare Zoo Code inviando dati di utilizzo e segnalazioni di errori, collegati a un identificatore di installazione anziché al tuo nome o account. Questa telemetria non raccoglie il tuo codice o i tuoi prompt. Consulta la nostra informativa sulla privacy per maggiori dettagli. Puoi disattivarla in qualsiasi momento." }, "settings": { "import": "Importa", diff --git a/webview-ui/src/i18n/locales/it/welcome.json b/webview-ui/src/i18n/locales/it/welcome.json index c5b4066964..cd7d418f76 100644 --- a/webview-ui/src/i18n/locales/it/welcome.json +++ b/webview-ui/src/i18n/locales/it/welcome.json @@ -12,7 +12,9 @@ }, "telemetry": { "helpImprove": "Aiuta a migliorare Zoo Code", - "helpImproveMessage": "Zoo Code raccoglie dati di errore e utilizzo per aiutarci a correggere i bug e migliorare l'estensione. Questa telemetria non raccoglie codice, prompt o informazioni personali. Puoi disabilitare questa funzione in impostazioni." + "helpImproveMessage": "Zoo Code raccoglie dati di errore e utilizzo, collegati a un identificatore di installazione, per aiutarci a correggere i bug e migliorare l'estensione. Questa telemetria non raccoglie il tuo codice o i tuoi prompt. Puoi disabilitare questa funzione in impostazioni.", + "accept": "Accetta", + "decline": "Rifiuta" }, "importSettings": "Importa impostazioni" } diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index bbdc5c8e8a..e99c6fdb65 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -1002,8 +1002,8 @@ }, "footer": { "telemetry": { - "label": "匿名のエラーと使用状況レポートを許可", - "description": "匿名の使用データとエラーレポートを送信してZoo Codeの改善にご協力ください。このテレメトリはコード、プロンプト、個人情報を収集しません。詳細についてはプライバシーポリシーをご覧ください。" + "label": "エラーと使用状況レポートを許可", + "description": "お名前やアカウントではなく、インストールに紐づく識別子と関連付けた使用データとエラーレポートを送信してZoo Codeの改善にご協力ください。このテレメトリはあなたのコードやプロンプトを収集しません。詳細についてはプライバシーポリシーをご覧ください。これはいつでも無効にできます。" }, "settings": { "import": "インポート", diff --git a/webview-ui/src/i18n/locales/ja/welcome.json b/webview-ui/src/i18n/locales/ja/welcome.json index 55e8b4e3dd..675a73a2eb 100644 --- a/webview-ui/src/i18n/locales/ja/welcome.json +++ b/webview-ui/src/i18n/locales/ja/welcome.json @@ -12,7 +12,9 @@ }, "telemetry": { "helpImprove": "Zoo Codeの改善にご協力ください", - "helpImproveMessage": "Zoo Codeは、バグを修正し、拡張機能を改善するために、エラーおよび使用データを収集します。このテレメトリはコード、プロンプト、または個人情報を収集しません。これは設定で無効にできます。" + "helpImproveMessage": "Zoo Codeは、バグを修正し、拡張機能を改善するために、インストールに紐づく識別子と関連付けたエラーおよび使用データを収集します。このテレメトリはあなたのコードやプロンプトを収集しません。これは設定で無効にできます。", + "accept": "同意する", + "decline": "拒否する" }, "importSettings": "設定のインポート" } diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index c2062a5335..f77c35bfa8 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -1002,8 +1002,8 @@ }, "footer": { "telemetry": { - "label": "익명 오류 및 사용 보고 허용", - "description": "익명 사용 데이터 및 오류 보고서를 전송하여 Zoo Code 개선에 도움을 주세요. 이 텔레메트리는 코드, 프롬프트 또는 개인 정보를 수집하지 않습니다. 자세한 내용은 개인정보 보호정책을 참조하세요." + "label": "오류 및 사용 보고 허용", + "description": "사용자의 이름이나 계정이 아닌 설치 식별자와 연결된 사용 데이터 및 오류 보고서를 전송하여 Zoo Code 개선에 도움을 주세요. 이 텔레메트리는 사용자의 코드나 프롬프트를 수집하지 않습니다. 자세한 내용은 개인정보 보호정책을 참조하세요. 언제든지 비활성화할 수 있습니다." }, "settings": { "import": "가져오기", diff --git a/webview-ui/src/i18n/locales/ko/welcome.json b/webview-ui/src/i18n/locales/ko/welcome.json index db9407a20a..9c7fe439dd 100644 --- a/webview-ui/src/i18n/locales/ko/welcome.json +++ b/webview-ui/src/i18n/locales/ko/welcome.json @@ -12,7 +12,9 @@ }, "telemetry": { "helpImprove": "Zoo Code 개선에 도움주세요", - "helpImproveMessage": "Zoo Code는 버그를 수정하고 확장을 개선하기 위해 오류 및 사용 데이터를 수집합니다. 이 원격 분석은 코드, 프롬프트 또는 개인 정보를 수집하지 않습니다. 설정에서 이를 비활성화할 수 있습니다." + "helpImproveMessage": "Zoo Code는 버그를 수정하고 확장을 개선하기 위해, 설치 식별자와 연결된 오류 및 사용 데이터를 수집합니다. 이 원격 분석은 사용자의 코드나 프롬프트를 수집하지 않습니다. 설정에서 이를 비활성화할 수 있습니다.", + "accept": "수락", + "decline": "거부" }, "importSettings": "설정 가져오기" } diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json index cf148f5617..f22658a0f2 100644 --- a/webview-ui/src/i18n/locales/nl/settings.json +++ b/webview-ui/src/i18n/locales/nl/settings.json @@ -1002,8 +1002,8 @@ }, "footer": { "telemetry": { - "label": "Anonieme fout- en gebruiksrapportage toestaan", - "description": "Help Zoo Code te verbeteren door anonieme gebruiksgegevens en foutmeldingen te versturen. Deze telemetrie verzamelt geen code, prompts of persoonlijke informatie. Zie ons privacybeleid voor meer details." + "label": "Fout- en gebruiksrapportage toestaan", + "description": "Help Zoo Code te verbeteren door gebruiksgegevens en foutmeldingen te versturen, gekoppeld aan een installatie-identifier in plaats van je naam of account. Deze telemetrie verzamelt niet je code of prompts. Zie ons privacybeleid voor meer details." }, "settings": { "import": "Importeren", diff --git a/webview-ui/src/i18n/locales/nl/welcome.json b/webview-ui/src/i18n/locales/nl/welcome.json index d62f761496..6662db31c3 100644 --- a/webview-ui/src/i18n/locales/nl/welcome.json +++ b/webview-ui/src/i18n/locales/nl/welcome.json @@ -12,7 +12,9 @@ }, "telemetry": { "helpImprove": "Help Zoo Code te verbeteren", - "helpImproveMessage": "Zoo Code verzamelt fout- en gebruiksgegevens om ons te helpen bugs op te lossen en de extensie te verbeteren. Deze telemetrie verzamelt geen code, prompts of persoonlijke informatie. Je kunt dit in instellingen uitschakelen." + "helpImproveMessage": "Zoo Code verzamelt fout- en gebruiksgegevens, gekoppeld aan een installatie-identifier, om ons te helpen bugs op te lossen en de extensie te verbeteren. Deze telemetrie verzamelt niet je code of prompts. Je kunt dit in instellingen uitschakelen.", + "accept": "Accepteren", + "decline": "Weigeren" }, "importSettings": "Instellingen importeren" } diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index ace780f529..d232eeef73 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -1002,8 +1002,8 @@ }, "footer": { "telemetry": { - "label": "Zezwól na anonimowe raportowanie błędów i użycia", - "description": "Pomóż ulepszyć Zoo Code, wysyłając anonimowe dane użytkowania i raporty błędów. Ta telemetria nie zbiera kodu, promptów ani danych osobowych. Zobacz naszą politykę prywatności, aby uzyskać więcej szczegółów. Możesz to wyłączyć w dowolnym momencie." + "label": "Zezwól na raportowanie błędów i użycia", + "description": "Pomóż ulepszyć Zoo Code, wysyłając dane użytkowania i raporty błędów powiązane z identyfikatorem instalacji, a nie z Twoim imieniem czy kontem. Ta telemetria nie zbiera Twojego kodu ani podpowiedzi. Zobacz naszą politykę prywatności, aby uzyskać więcej szczegółów. Możesz to wyłączyć w dowolnym momencie." }, "settings": { "import": "Importuj", diff --git a/webview-ui/src/i18n/locales/pl/welcome.json b/webview-ui/src/i18n/locales/pl/welcome.json index 32037e759e..5f342c5860 100644 --- a/webview-ui/src/i18n/locales/pl/welcome.json +++ b/webview-ui/src/i18n/locales/pl/welcome.json @@ -12,7 +12,9 @@ }, "telemetry": { "helpImprove": "Pomóż ulepszyć Zoo Code", - "helpImproveMessage": "Zoo Code zbiera dane o błędach i użytkowaniu, aby pomóc nam naprawiać błędy i ulepszać rozszerzenie. Ta telemetria nie zbiera kodu, podpowiedzi ani danych osobowych. Możesz je wyłączyć w ustawieniach." + "helpImproveMessage": "Zoo Code zbiera dane o błędach i użytkowaniu, powiązane z identyfikatorem instalacji, aby pomóc nam naprawiać błędy i ulepszać rozszerzenie. Ta telemetria nie zbiera Twojego kodu ani podpowiedzi. Możesz ją wyłączyć w ustawieniach.", + "accept": "Akceptuj", + "decline": "Odrzuć" }, "importSettings": "Importuj ustawienia" } diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index 446aa8ac02..8cf0d30d76 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -1002,8 +1002,8 @@ }, "footer": { "telemetry": { - "label": "Permitir relatórios anônimos de erros e uso", - "description": "Ajude a melhorar o Zoo Code enviando dados de uso anônimos e relatórios de erros. Esta telemetria não coleta código, prompts ou informações pessoais. Consulte nossa política de privacidade para mais detalhes." + "label": "Permitir relatórios de erros e uso", + "description": "Ajude a melhorar o Zoo Code enviando dados de uso e relatórios de erros, vinculados a um identificador de instalação em vez do seu nome ou conta. Esta telemetria não coleta seu código ou seus prompts. Consulte nossa política de privacidade para mais detalhes." }, "settings": { "import": "Importar", diff --git a/webview-ui/src/i18n/locales/pt-BR/welcome.json b/webview-ui/src/i18n/locales/pt-BR/welcome.json index c444ff4374..29ecf56e7e 100644 --- a/webview-ui/src/i18n/locales/pt-BR/welcome.json +++ b/webview-ui/src/i18n/locales/pt-BR/welcome.json @@ -12,7 +12,9 @@ }, "telemetry": { "helpImprove": "Ajude a melhorar o Zoo Code", - "helpImproveMessage": "Zoo Code coleta dados de erro e uso para nos ajudar a corrigir bugs e melhorar a extensão. Esta telemetria não coleta código, prompts ou informações pessoais. Você pode desabilitar isso nas configurações." + "helpImproveMessage": "Zoo Code coleta dados de erro e uso, vinculados a um identificador de instalação, para nos ajudar a corrigir bugs e melhorar a extensão. Esta telemetria não coleta seu código ou seus prompts. Você pode desabilitar isso nas configurações.", + "accept": "Aceitar", + "decline": "Recusar" }, "importSettings": "Importar configurações" } diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index f2719ad06e..66fead81f7 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -1002,8 +1002,8 @@ }, "footer": { "telemetry": { - "label": "Разрешить анонимную отправку ошибок и статистики использования", - "description": "Помогите улучшить Zoo Code, отправляя анонимные данные об использовании и отчеты об ошибках. Эта телеметрия не собирает код, промпты или личную информацию. Смотрите нашу политику конфиденциальности для получения подробной информации." + "label": "Разрешить отправку ошибок и статистики использования", + "description": "Помогите улучшить Zoo Code, отправляя данные об использовании и отчеты об ошибках, связанные с идентификатором установки, а не с вашим именем или учетной записью. Эта телеметрия не собирает ваш код или запросы. Смотрите нашу политику конфиденциальности для получения подробной информации." }, "settings": { "import": "Импорт", diff --git a/webview-ui/src/i18n/locales/ru/welcome.json b/webview-ui/src/i18n/locales/ru/welcome.json index dade1e8ece..62a40077d8 100644 --- a/webview-ui/src/i18n/locales/ru/welcome.json +++ b/webview-ui/src/i18n/locales/ru/welcome.json @@ -12,7 +12,9 @@ }, "telemetry": { "helpImprove": "Помогите улучшить Zoo Code", - "helpImproveMessage": "Zoo Code собирает данные об ошибках и использовании, чтобы помочь нам исправлять ошибки и улучшать расширение. Эта телеметрия не собирает код, приглашения или личную информацию. Вы можете отключить это в настройках." + "helpImproveMessage": "Zoo Code собирает данные об ошибках и использовании, связанные с идентификатором установки, чтобы помочь нам исправлять ошибки и улучшать расширение. Эта телеметрия не собирает ваш код или запросы. Вы можете отключить это в настройках.", + "accept": "Принять", + "decline": "Отклонить" }, "importSettings": "Импортировать настройки" } diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index 08374b6d20..b9c9f08013 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -1002,8 +1002,8 @@ }, "footer": { "telemetry": { - "label": "Anonim hata ve kullanım raporlamaya izin ver", - "description": "Anonim kullanım verileri ve hata raporları göndererek Zoo Code'u geliştirmeye yardım edin. Bu telemetri kod, prompt veya kişisel bilgi toplamaz. Daha fazla ayrıntı için gizlilik politikamıza bakın. Bunu istediğiniz zaman kapatabilirsiniz." + "label": "Hata ve kullanım raporlamasına izin ver", + "description": "Adınız veya hesabınız yerine kuruluma bağlı bir tanımlayıcıyla ilişkilendirilmiş kullanım verileri ve hata raporları göndererek Zoo Code'u geliştirmeye yardım edin. Bu telemetri kodunuzu veya istemlerinizi toplamaz. Daha fazla ayrıntı için gizlilik politikamıza bakın. Bunu istediğiniz zaman kapatabilirsiniz." }, "settings": { "import": "İçe Aktar", diff --git a/webview-ui/src/i18n/locales/tr/welcome.json b/webview-ui/src/i18n/locales/tr/welcome.json index 0216342ed9..0f83de0f30 100644 --- a/webview-ui/src/i18n/locales/tr/welcome.json +++ b/webview-ui/src/i18n/locales/tr/welcome.json @@ -12,7 +12,9 @@ }, "telemetry": { "helpImprove": "Zoo Code'u iyileştirmeye yardımcı ol", - "helpImproveMessage": "Zoo Code, hataları düzeltmemize ve uzantıyı iyileştirmemize yardımcı olmak için hata ve kullanım verilerini toplar. Bu telemetri kod, komutlar veya kişisel bilgileri toplamaz. Bunu ayarlardan devre dışı bırakabilirsin." + "helpImproveMessage": "Zoo Code, hataları düzeltmemize ve uzantıyı iyileştirmemize yardımcı olmak için, kuruluma bağlı bir tanımlayıcıyla ilişkilendirilmiş hata ve kullanım verilerini toplar. Bu telemetri kodunu veya istemlerini toplamaz. Bunu ayarlardan devre dışı bırakabilirsin.", + "accept": "Kabul et", + "decline": "Reddet" }, "importSettings": "Ayarları İçe Aktar" } diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index a8611ca687..336c38e599 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -1002,8 +1002,8 @@ }, "footer": { "telemetry": { - "label": "Cho phép báo cáo lỗi và sử dụng ẩn danh", - "description": "Giúp cải thiện Zoo Code bằng cách gửi dữ liệu sử dụng ẩn danh và báo cáo lỗi. Telemetry này không thu thập mã, prompt hoặc thông tin cá nhân. Xem chính sách bảo mật của chúng tôi để biết thêm chi tiết. Bạn có thể tắt tính năng này bất cứ lúc nào." + "label": "Cho phép báo cáo lỗi và dữ liệu sử dụng", + "description": "Giúp cải thiện Zoo Code bằng cách gửi dữ liệu sử dụng và báo cáo lỗi, được liên kết với mã định danh cài đặt thay vì tên hoặc tài khoản của bạn. Telemetry này không thu thập mã nguồn hoặc lời nhắc của bạn. Xem chính sách bảo mật của chúng tôi để biết thêm chi tiết. Bạn có thể tắt tính năng này bất cứ lúc nào." }, "settings": { "import": "Nhập", diff --git a/webview-ui/src/i18n/locales/vi/welcome.json b/webview-ui/src/i18n/locales/vi/welcome.json index 93756a444e..76be9d097c 100644 --- a/webview-ui/src/i18n/locales/vi/welcome.json +++ b/webview-ui/src/i18n/locales/vi/welcome.json @@ -12,7 +12,9 @@ }, "telemetry": { "helpImprove": "Giúp cải thiện Zoo Code", - "helpImproveMessage": "Zoo Code thu thập dữ liệu lỗi và sử dụng để giúp chúng tôi sửa lỗi và cải thiện tiện ích mở rộng. Dữ liệu từ xa này không thu thập mã, lời nhắc hoặc thông tin cá nhân. Bạn có thể vô hiệu hóa nó trong cài đặt." + "helpImproveMessage": "Zoo Code thu thập dữ liệu lỗi và sử dụng, được liên kết với một mã định danh cài đặt, để giúp chúng tôi sửa lỗi và cải thiện tiện ích mở rộng. Dữ liệu từ xa này không thu thập mã nguồn hoặc lời nhắc của bạn. Bạn có thể vô hiệu hóa nó trong cài đặt.", + "accept": "Chấp nhận", + "decline": "Từ chối" }, "importSettings": "Nhập Cài đặt" } diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index 9f3913e872..b43b8c0774 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -1002,8 +1002,8 @@ }, "footer": { "telemetry": { - "label": "允许匿名数据收集", - "description": "通过发送匿名使用数据和错误报告来帮助改进 Zoo Code。此遥测不会收集代码、提示 或个人信息。详细信息请参阅我们的隐私政策。您可以随时关闭此功能。" + "label": "允许发送错误和使用情况报告", + "description": "通过发送与安装标识符(而非您的姓名或帐户)关联的使用数据和错误报告来帮助改进 Zoo Code。此遥测不会收集您的代码或提示词。详细信息请参阅我们的隐私政策。您可以随时关闭此功能。" }, "settings": { "import": "导入", diff --git a/webview-ui/src/i18n/locales/zh-CN/welcome.json b/webview-ui/src/i18n/locales/zh-CN/welcome.json index 1506c0c959..17740e8302 100644 --- a/webview-ui/src/i18n/locales/zh-CN/welcome.json +++ b/webview-ui/src/i18n/locales/zh-CN/welcome.json @@ -12,7 +12,9 @@ }, "telemetry": { "helpImprove": "帮助改进 Zoo Code", - "helpImproveMessage": "Zoo Code 收集错误和使用数据以帮助我们修复 Bug 并改进扩展。此遥测不收集代码、提示或个人信息。你可以在设置中将其关闭。" + "helpImproveMessage": "Zoo Code 收集与安装标识符关联的错误和使用数据,以帮助我们修复 Bug 并改进扩展。此遥测不会收集你的代码或提示词。你可以在设置中将其关闭。", + "accept": "接受", + "decline": "拒绝" }, "importSettings": "导入设置" } diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index 80d0d18735..e8a9216ca9 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -1029,8 +1029,8 @@ }, "footer": { "telemetry": { - "label": "允許匿名錯誤與使用情況回報", - "description": "透過發送匿名使用資料和錯誤回報來協助改善 Zoo Code。此遙測不會收集程式碼、提示詞或個人資訊。查看我們的 隱私權政策 以了解更多資訊。" + "label": "允許錯誤與使用情況回報", + "description": "透過發送與安裝識別碼(而非您的姓名或帳戶)相關聯的使用資料和錯誤回報來協助改善 Zoo Code。此遙測不會收集您的程式碼或提示詞。查看我們的 隱私權政策 以了解更多資訊。您可以隨時關閉此功能。" }, "settings": { "import": "匯入", diff --git a/webview-ui/src/i18n/locales/zh-TW/welcome.json b/webview-ui/src/i18n/locales/zh-TW/welcome.json index 4ba8548a62..eba96dc00a 100644 --- a/webview-ui/src/i18n/locales/zh-TW/welcome.json +++ b/webview-ui/src/i18n/locales/zh-TW/welcome.json @@ -12,7 +12,9 @@ }, "telemetry": { "helpImprove": "幫助改進 Zoo Code", - "helpImproveMessage": "Zoo Code 會收集錯誤和使用情況資料以幫助我們修復錯誤並改進擴充功能。此遙測不會收集程式碼、提示詞或個人資訊。您可以在 設定 中關閉。" + "helpImproveMessage": "Zoo Code 會收集與安裝識別碼相關聯的錯誤和使用情況資料,以幫助我們修復錯誤並改進擴充功能。此遙測不會收集您的程式碼或提示詞。您可以在 設定 中關閉。", + "accept": "接受", + "decline": "拒絕" }, "importSettings": "匯入設定" } diff --git a/webview-ui/src/utils/TelemetryClient.ts b/webview-ui/src/utils/TelemetryClient.ts index 3e28a4f234..f3a70da29f 100644 --- a/webview-ui/src/utils/TelemetryClient.ts +++ b/webview-ui/src/utils/TelemetryClient.ts @@ -1,15 +1,20 @@ import posthog from "posthog-js" -import type { TelemetrySetting } from "@roo-code/types" +import { type TelemetrySetting, isTelemetryOptedIn } from "@roo-code/types" class TelemetryClient { private static instance: TelemetryClient private static telemetryEnabled: boolean = false - public updateTelemetryState(telemetrySetting: TelemetrySetting, apiKey?: string, distinctId?: string) { + public updateTelemetryState( + telemetrySetting: TelemetrySetting, + apiKey?: string, + distinctId?: string, + vscodeTelemetryEnabled: boolean = true, + ) { posthog.reset() - if (telemetrySetting !== "disabled" && apiKey && distinctId) { + if (isTelemetryOptedIn(telemetrySetting) && apiKey && distinctId && vscodeTelemetryEnabled) { TelemetryClient.telemetryEnabled = true posthog.init(apiKey, { From db52d7fc721ba5c0985948d13abe99c1784c2a02 Mon Sep 17 00:00:00 2001 From: eason liang <136036952+easonLiangWorldedtech@users.noreply.github.com> Date: Sat, 22 Aug 2026 01:08:25 +0000 Subject: [PATCH 41/66] feat(models): add Gemini 3.5 Flash Lite and 3.1 Flash Lite to Gemini API provider (#1334) * feat(models): add Gemini 3.5 Flash Lite and 3.1 Flash Lite to Gemini API provider Adds the two new stable Flash Lite models so users can select them directly instead of relying on gemini-flash-lite-latest (#1251). Model ids, limits and pricing verified against the official Gemini API docs and the OpenRouter catalog. * fix(models): support minimal thinking level for Gemini 3.1 Flash Lite The official model docs list minimal, low, medium, and high thinking levels for gemini-3.1-flash-lite; add the missing minimal level (CodeRabbit review on #1334). * fix(models): default Flash Lite reasoning effort to minimal The documented API defaults are On (minimal) for gemini-3.5-flash-lite and minimal is the lowest supported level for gemini-3.1-flash-lite; defaulting to medium would raise unset users above the cheap tier. Addressed via CodeRabbit review on #1334. --------- Co-authored-by: Eason Liang --- .../types/src/__tests__/google-models.test.ts | 38 +++++++++++++++++++ packages/types/src/providers/gemini.ts | 31 +++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/packages/types/src/__tests__/google-models.test.ts b/packages/types/src/__tests__/google-models.test.ts index 674fb5d83c..80ee7c98ce 100644 --- a/packages/types/src/__tests__/google-models.test.ts +++ b/packages/types/src/__tests__/google-models.test.ts @@ -10,3 +10,41 @@ describe.each([ expect(model.cacheWritesPrice).toBe(0.5) }) }) + +describe.each([ + ["gemini-3.5-flash-lite", geminiModels["gemini-3.5-flash-lite"]], + ["gemini-3.1-flash-lite", geminiModels["gemini-3.1-flash-lite"]], +])("Gemini 3.x Flash Lite model %s", (_modelId, model) => { + it("is registered with the documented limits and multimodal support", () => { + expect(model.maxTokens).toBe(65_536) + expect(model.contextWindow).toBe(1_048_576) + expect(model.supportsImages).toBe(true) + expect(model.supportsPromptCache).toBe(true) + expect(model.supportsReasoningBudget).toBe(false) + }) +}) + +it("exposes the documented thinking levels and pricing for Gemini 3.5 Flash Lite", () => { + const model = geminiModels["gemini-3.5-flash-lite"] + expect(model.supportsReasoningEffort).toEqual(["minimal", "low", "medium", "high"]) + // The documented API default is On (minimal): + // https://ai.google.dev/gemini-api/docs/thinking + expect(model.reasoningEffort).toBe("minimal") + expect(model.inputPrice).toBe(0.3) + expect(model.outputPrice).toBe(2.5) + expect(model.cacheReadsPrice).toBe(0.03) + expect(model.cacheWritesPrice).toBe(1.0) +}) + +it("exposes the documented thinking levels and pricing for Gemini 3.1 Flash Lite", () => { + const model = geminiModels["gemini-3.1-flash-lite"] + // https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/gemini/3-1-flash-lite + // "choosing from minimal, low, medium, or high thinking levels" + expect(model.supportsReasoningEffort).toEqual(["minimal", "low", "medium", "high"]) + // Lowest supported level, matching the cheap/free Flash Lite tier. + expect(model.reasoningEffort).toBe("minimal") + expect(model.inputPrice).toBe(0.25) + expect(model.outputPrice).toBe(1.5) + expect(model.cacheReadsPrice).toBe(0.025) + expect(model.cacheWritesPrice).toBe(1.0) +}) diff --git a/packages/types/src/providers/gemini.ts b/packages/types/src/providers/gemini.ts index d3051a8229..b65f842a59 100644 --- a/packages/types/src/providers/gemini.ts +++ b/packages/types/src/providers/gemini.ts @@ -145,6 +145,37 @@ export const geminiModels = { outputPrice: 3.0, cacheReadsPrice: 0.05, }, + // 3.x Flash Lite models + "gemini-3.5-flash-lite": { + maxTokens: 65_536, + contextWindow: 1_048_576, + supportsImages: true, + supportsPromptCache: true, + supportsReasoningEffort: ["minimal", "low", "medium", "high"], + // Matches the documented API default thinking level (On (minimal)). + reasoningEffort: "minimal", + inputPrice: 0.3, + outputPrice: 2.5, + cacheReadsPrice: 0.03, + cacheWritesPrice: 1.0, + supportsReasoningBudget: false, + }, + "gemini-3.1-flash-lite": { + maxTokens: 65_536, + contextWindow: 1_048_576, + supportsImages: true, + supportsPromptCache: true, + supportsReasoningEffort: ["minimal", "low", "medium", "high"], + // Lowest level of the supported set: keeps the cheap/free tier's + // default latency and cost in line with the Flash Lite tier. + reasoningEffort: "minimal", + inputPrice: 0.25, + outputPrice: 1.5, + cacheReadsPrice: 0.025, + cacheWritesPrice: 1.0, + supportsReasoningBudget: false, + }, + // 2.5 Pro models "gemini-2.5-pro": { maxTokens: 64_000, From 3dcac600b9d13b1d6882749947b6f380e2e4b8df Mon Sep 17 00:00:00 2001 From: "zoomote[bot]" <305051434+zoomote[bot]@users.noreply.github.com> Date: Sat, 22 Aug 2026 01:57:36 +0000 Subject: [PATCH 42/66] [Chore] Enforce safe async handling in core tools (#1255) * chore(lint): enforce no-floating-promises in core tools * test: cover core tool promise branches * refactor(core/tools): drop unreachable webview-post catches, make notifications non-blocking --------- Co-authored-by: Roomote Co-authored-by: Elliott de Launay --- src/core/tools/ExecuteCommandTool.ts | 21 +++-- src/core/tools/UpdateTodoListTool.ts | 19 +++-- src/core/tools/UseMcpToolTool.ts | 3 +- .../tools/__tests__/executeCommand.spec.ts | 82 ++++++++++++++++--- .../__tests__/executeCommandTool.spec.ts | 69 +++++++++++++++- .../__tests__/updateTodoListTool.spec.ts | 39 ++++++++- src/eslint.config.mjs | 2 +- 7 files changed, 204 insertions(+), 31 deletions(-) diff --git a/src/core/tools/ExecuteCommandTool.ts b/src/core/tools/ExecuteCommandTool.ts index f2fc4889f8..8383d9a4e1 100644 --- a/src/core/tools/ExecuteCommandTool.ts +++ b/src/core/tools/ExecuteCommandTool.ts @@ -8,6 +8,7 @@ import { CommandExecutionStatus, DEFAULT_TERMINAL_OUTPUT_PREVIEW_SIZE, Persisted import { TelemetryService } from "@roo-code/telemetry" import { Task } from "../task/Task" +import type { ClineProvider } from "../webview/ClineProvider" import { ToolUse, ToolResponse } from "../../shared/tools" import { formatResponse } from "../prompts/responses" @@ -75,6 +76,12 @@ export function resolveAgentTimeoutMs(timeoutSeconds: number | null | undefined) return process.env.ROO_CLI_RUNTIME === "1" ? 0 : requestedAgentTimeout } +// Fire-and-forget: some call sites are synchronous terminal callbacks that cannot await, +// and postMessageToWebview swallows its own errors, so void is enough. +function postCommandExecutionStatus(provider: ClineProvider | undefined, status: CommandExecutionStatus): void { + void provider?.postMessageToWebview({ type: "commandExecutionStatus", text: JSON.stringify(status) }) +} + export class ExecuteCommandTool extends BaseTool<"execute_command"> { readonly name = "execute_command" as const @@ -115,7 +122,7 @@ export class ExecuteCommandTool extends BaseTool<"execute_command"> { status: "error", message: parseError.message, } - provider?.postMessageToWebview({ type: "commandExecutionStatus", text: JSON.stringify(errorStatus) }) + postCommandExecutionStatus(provider, errorStatus) task.didToolFailInCurrentTurn = true pushToolResult(formatResponse.toolError(parseError.message)) return @@ -203,7 +210,7 @@ export class ExecuteCommandTool extends BaseTool<"execute_command"> { if (canRetryShellIntegrationError(error)) { // Silent retry via execa — shell startup race, command was not submitted. const status: CommandExecutionStatus = { executionId, status: "fallback" } - provider?.postMessageToWebview({ type: "commandExecutionStatus", text: JSON.stringify(status) }) + postCommandExecutionStatus(provider, status) const [rejected, result] = await executeCommandInTerminal(task, { ...options, @@ -294,7 +301,7 @@ export async function executeCommandInTerminal( // panel immediately (same effect as the retry-fallback path). if (isCmdExeFallback) { const status: CommandExecutionStatus = { executionId, status: "fallback" } - provider?.postMessageToWebview({ type: "commandExecutionStatus", text: JSON.stringify(status) }) + postCommandExecutionStatus(provider, status) } // Get global storage path for persisted output artifacts @@ -394,7 +401,7 @@ export async function executeCommandInTerminal( const compressedOutput = Terminal.compressTerminalOutput(accumulatedOutput) latestCompressedOutput = compressedOutput const status: CommandExecutionStatus = { executionId, status: "output", output: compressedOutput } - provider?.postMessageToWebview({ type: "commandExecutionStatus", text: JSON.stringify(status) }) + postCommandExecutionStatus(provider, status) schedulePartialCommandOutputUpdate() }, onCompleted: async (output: string | undefined) => { @@ -433,11 +440,11 @@ export async function executeCommandInTerminal( }, onShellExecutionStarted: (pid: number | undefined) => { const status: CommandExecutionStatus = { executionId, status: "started", pid, command } - provider?.postMessageToWebview({ type: "commandExecutionStatus", text: JSON.stringify(status) }) + postCommandExecutionStatus(provider, status) }, onShellExecutionComplete: (details: ExitCodeDetails) => { const status: CommandExecutionStatus = { executionId, status: "exited", exitCode: details.exitCode } - provider?.postMessageToWebview({ type: "commandExecutionStatus", text: JSON.stringify(status) }) + postCommandExecutionStatus(provider, status) exitDetails = details }, } @@ -506,7 +513,7 @@ export async function executeCommandInTerminal( } catch (error) { if (isUserTimedOut) { const status: CommandExecutionStatus = { executionId, status: "timeout" } - provider?.postMessageToWebview({ type: "commandExecutionStatus", text: JSON.stringify(status) }) + postCommandExecutionStatus(provider, status) await task.say("error", t("common:errors:command_timeout", { seconds: commandExecutionTimeoutSeconds })) task.didToolFailInCurrentTurn = true task.terminalProcess = undefined diff --git a/src/core/tools/UpdateTodoListTool.ts b/src/core/tools/UpdateTodoListTool.ts index 7414b713cf..4317696da6 100644 --- a/src/core/tools/UpdateTodoListTool.ts +++ b/src/core/tools/UpdateTodoListTool.ts @@ -64,13 +64,18 @@ export class UpdateTodoListTool extends BaseTool<"update_todo_list"> { approvedTodoList !== undefined && JSON.stringify(normalizedTodos) !== JSON.stringify(approvedTodoList) if (isTodoListChanged) { normalizedTodos = approvedTodoList ?? [] - task.say( - "user_edit_todos", - JSON.stringify({ - tool: "updateTodoList", - todos: normalizedTodos, - }), - ) + // Non-blocking: a failed notification must not abort persisting the edited list. + void task + .say( + "user_edit_todos", + JSON.stringify({ + tool: "updateTodoList", + todos: normalizedTodos, + }), + ) + .catch((error) => { + console.error("[UpdateTodoListTool] Failed to post user_edit_todos:", error) + }) } await setTodoListForTask(task, normalizedTodos) diff --git a/src/core/tools/UseMcpToolTool.ts b/src/core/tools/UseMcpToolTool.ts index 9b2870060c..cd7c3d469d 100644 --- a/src/core/tools/UseMcpToolTool.ts +++ b/src/core/tools/UseMcpToolTool.ts @@ -287,7 +287,8 @@ export class UseMcpToolTool extends BaseTool<"use_mcp_tool"> { private async sendExecutionStatus(task: Task, status: McpExecutionStatus): Promise { const clineProvider = await task.providerRef.deref() - clineProvider?.postMessageToWebview({ + // Fire-and-forget: postMessageToWebview swallows its own errors, so void is enough. + void clineProvider?.postMessageToWebview({ type: "mcpExecutionStatus", text: JSON.stringify(status), }) diff --git a/src/core/tools/__tests__/executeCommand.spec.ts b/src/core/tools/__tests__/executeCommand.spec.ts index fd85beb0f4..7146fa930b 100644 --- a/src/core/tools/__tests__/executeCommand.spec.ts +++ b/src/core/tools/__tests__/executeCommand.spec.ts @@ -38,7 +38,7 @@ describe("executeCommand", () => { // Create mock provider mockProvider = { - postMessageToWebview: vitest.fn(), + postMessageToWebview: vitest.fn().mockResolvedValue(undefined), getState: vitest.fn().mockResolvedValue({ terminalShellIntegrationDisabled: false, }), @@ -73,6 +73,12 @@ describe("executeCommand", () => { // Mock TerminalRegistry.getOrCreateTerminal ;(TerminalRegistry.getOrCreateTerminal as any).mockResolvedValue(mockTerminal) + vitest.mocked(Terminal.isActiveShellCmdExe).mockReturnValue(false) + }) + + afterEach(() => { + vitest.useRealTimers() + vitest.restoreAllMocks() }) describe("Working Directory Behavior", () => { @@ -89,7 +95,7 @@ describe("executeCommand", () => { mockTerminal.runCommand.mockImplementation((command: string, callbacks: RooTerminalCallbacks) => { // Simulate command completion setTimeout(() => { - callbacks.onCompleted("Command output", mockProcess) + void callbacks.onCompleted("Command output", mockProcess) callbacks.onShellExecutionComplete({ exitCode: 0 }, mockProcess) }, 0) return mockProcess @@ -128,7 +134,7 @@ describe("executeCommand", () => { .fn() .mockImplementation((command: string, callbacks: RooTerminalCallbacks) => { setTimeout(() => { - callbacks.onCompleted("Command output", mockProcess) + void callbacks.onCompleted("Command output", mockProcess) callbacks.onShellExecutionComplete({ exitCode: 0 }, mockProcess) }, 0) return mockProcess @@ -160,7 +166,7 @@ describe("executeCommand", () => { .fn() .mockImplementation((command: string, callbacks: RooTerminalCallbacks) => { setTimeout(() => { - callbacks.onCompleted("Command output", mockProcess) + void callbacks.onCompleted("Command output", mockProcess) callbacks.onShellExecutionComplete({ exitCode: 0 }, mockProcess) }, 0) return mockProcess @@ -190,7 +196,7 @@ describe("executeCommand", () => { mockTerminal.getCurrentWorkingDirectory.mockReturnValue(customCwd) mockTerminal.runCommand.mockImplementation((command: string, callbacks: RooTerminalCallbacks) => { setTimeout(() => { - callbacks.onCompleted("Command output", mockProcess) + void callbacks.onCompleted("Command output", mockProcess) callbacks.onShellExecutionComplete({ exitCode: 0 }, mockProcess) }, 0) return mockProcess @@ -219,7 +225,7 @@ describe("executeCommand", () => { mockTerminal.getCurrentWorkingDirectory.mockReturnValue(resolvedCwd) mockTerminal.runCommand.mockImplementation((command: string, callbacks: RooTerminalCallbacks) => { setTimeout(() => { - callbacks.onCompleted("Command output", mockProcess) + void callbacks.onCompleted("Command output", mockProcess) callbacks.onShellExecutionComplete({ exitCode: 0 }, mockProcess) }, 0) return mockProcess @@ -265,10 +271,34 @@ describe("executeCommand", () => { }) describe("Terminal Provider Selection", () => { + it("posts fallback status when cmd.exe requires the Execa provider", async () => { + vitest.spyOn(Terminal, "isActiveShellCmdExe").mockReturnValue(true) + mockTerminal.runCommand.mockImplementation((command: string, callbacks: RooTerminalCallbacks) => { + setTimeout(() => { + void callbacks.onCompleted("Command output", mockProcess) + callbacks.onShellExecutionComplete({ exitCode: 0 }, mockProcess) + }, 0) + return mockProcess + }) + + await executeCommandInTerminal(mockTask, { + executionId: "test-123", + command: "echo test", + terminalShellIntegrationDisabled: false, + }) + + expect(mockProvider.postMessageToWebview).toHaveBeenCalledWith( + expect.objectContaining({ + type: "commandExecutionStatus", + text: expect.stringContaining('"status":"fallback"'), + }), + ) + }) + it("should use vscode provider when shell integration is enabled", async () => { mockTerminal.runCommand.mockImplementation((command: string, callbacks: RooTerminalCallbacks) => { setTimeout(() => { - callbacks.onCompleted("Command output", mockProcess) + void callbacks.onCompleted("Command output", mockProcess) callbacks.onShellExecutionComplete({ exitCode: 0 }, mockProcess) }, 0) return mockProcess @@ -290,7 +320,7 @@ describe("executeCommand", () => { it("should use execa provider when shell integration is disabled", async () => { mockTerminal.runCommand.mockImplementation((command: string, callbacks: RooTerminalCallbacks) => { setTimeout(() => { - callbacks.onCompleted("Command output", mockProcess) + void callbacks.onCompleted("Command output", mockProcess) callbacks.onShellExecutionComplete({ exitCode: 0 }, mockProcess) }, 0) return mockProcess @@ -311,11 +341,39 @@ describe("executeCommand", () => { }) describe("Command Execution States", () => { + it("posts timeout status when command execution exceeds the user limit", async () => { + vitest.useFakeTimers() + const pendingProcess = Object.assign(new Promise(() => {}), { + continue: vitest.fn(), + abort: vitest.fn(), + }) + mockTerminal.runCommand.mockReturnValue(pendingProcess) + + const executionPromise = executeCommandInTerminal(mockTask, { + executionId: "test-123", + command: "sleep 10", + terminalShellIntegrationDisabled: false, + commandExecutionTimeout: 1_000, + }) + await vitest.advanceTimersByTimeAsync(1_000) + const [rejected, result] = await executionPromise + + expect(rejected).toBe(false) + expect(result).toContain("terminated after exceeding") + expect(mockProvider.postMessageToWebview).toHaveBeenCalledWith( + expect.objectContaining({ + type: "commandExecutionStatus", + text: expect.stringContaining('"status":"timeout"'), + }), + ) + expect(pendingProcess.abort).toHaveBeenCalled() + }) + it("should handle completed command with exit code 0", async () => { mockTerminal.getCurrentWorkingDirectory.mockReturnValue("/test/project") mockTerminal.runCommand.mockImplementation((command: string, callbacks: RooTerminalCallbacks) => { setTimeout(() => { - callbacks.onCompleted("Command completed successfully", mockProcess) + void callbacks.onCompleted("Command completed successfully", mockProcess) callbacks.onShellExecutionComplete({ exitCode: 0 }, mockProcess) }, 0) return mockProcess @@ -340,7 +398,7 @@ describe("executeCommand", () => { mockTerminal.getCurrentWorkingDirectory.mockReturnValue("/test/project") mockTerminal.runCommand.mockImplementation((command: string, callbacks: RooTerminalCallbacks) => { setTimeout(() => { - callbacks.onCompleted("Command failed", mockProcess) + void callbacks.onCompleted("Command failed", mockProcess) callbacks.onShellExecutionComplete({ exitCode: 1 }, mockProcess) }, 0) return mockProcess @@ -366,7 +424,7 @@ describe("executeCommand", () => { mockTerminal.getCurrentWorkingDirectory.mockReturnValue("/test/project") mockTerminal.runCommand.mockImplementation((command: string, callbacks: RooTerminalCallbacks) => { setTimeout(() => { - callbacks.onCompleted("Command interrupted", mockProcess) + void callbacks.onCompleted("Command interrupted", mockProcess) callbacks.onShellExecutionComplete( { exitCode: undefined, @@ -411,7 +469,7 @@ describe("executeCommand", () => { getCurrentWorkingDirectory: vitest.fn().mockReturnValue(updatedCwd), runCommand: vitest.fn().mockImplementation((command: string, callbacks: RooTerminalCallbacks) => { setTimeout(() => { - callbacks.onCompleted("Directory changed", mockProcess) + void callbacks.onCompleted("Directory changed", mockProcess) callbacks.onShellExecutionComplete({ exitCode: 0 }, mockProcess) }, 0) return mockProcess diff --git a/src/core/tools/__tests__/executeCommandTool.spec.ts b/src/core/tools/__tests__/executeCommandTool.spec.ts index 41b22a0e5f..a856b180ca 100644 --- a/src/core/tools/__tests__/executeCommandTool.spec.ts +++ b/src/core/tools/__tests__/executeCommandTool.spec.ts @@ -8,6 +8,7 @@ import { formatResponse } from "../../prompts/responses" import { ToolUse, AskApproval, HandleError, PushToolResult } from "../../../shared/tools" import { unescapeHtmlEntities } from "../../../utils/text-normalization" import { Terminal } from "../../../integrations/terminal/Terminal" +import { TerminalRegistry } from "../../../integrations/terminal/TerminalRegistry" import type { RooTerminalCallbacks, RooTerminalProcess } from "../../../integrations/terminal/types" // Mock dependencies @@ -97,7 +98,7 @@ describe("executeCommandTool", () => { terminalOutputCharacterLimit: 100000, terminalShellIntegrationDisabled: true, }), - postMessageToWebview: vitest.fn(), + postMessageToWebview: vitest.fn().mockResolvedValue(undefined), }), }, lastMessageTs: Date.now(), @@ -212,6 +213,70 @@ describe("executeCommandTool", () => { }) describe("Error handling", () => { + it("reports command parse errors to the webview", async () => { + const provider = await mockCline.providerRef.deref() + mockToolUse.params.command = 'echo "unterminated' + mockToolUse.nativeArgs = { command: 'echo "unterminated' } + + await executeCommandTool.handle(mockCline as unknown as Task, mockToolUse, { + askApproval: mockAskApproval as unknown as AskApproval, + handleError: mockHandleError as unknown as HandleError, + pushToolResult: mockPushToolResult as unknown as PushToolResult, + }) + + expect(provider.postMessageToWebview).toHaveBeenCalledWith( + expect.objectContaining({ + type: "commandExecutionStatus", + text: expect.stringContaining('"status":"error"'), + }), + ) + expect(mockAskApproval).not.toHaveBeenCalled() + }) + + it("posts fallback status when retrying a pre-submission shell integration failure", async () => { + const provider = await mockCline.providerRef.deref() + const shellError = new executeCommandModule.ShellIntegrationError("startup failed", false) + const failedProcess = Object.assign(Promise.reject(shellError), { + continue: vitest.fn(), + abort: vitest.fn(), + }) + const successfulProcess = Object.assign(Promise.resolve(), { + continue: vitest.fn(), + abort: vitest.fn(), + }) + // The terminal mock only needs the Promise surface used by this execution path. + const successfulTerminalProcess = successfulProcess as unknown as RooTerminalProcess + + vitest + .mocked(TerminalRegistry.getOrCreateTerminal) + .mockResolvedValueOnce({ + runCommand: vitest.fn().mockReturnValue(failedProcess), + getCurrentWorkingDirectory: vitest.fn().mockReturnValue("/test/workspace"), + } as never) + .mockResolvedValueOnce({ + runCommand: vitest.fn().mockImplementation((_command: string, callbacks: RooTerminalCallbacks) => { + void callbacks.onCompleted?.("", successfulTerminalProcess) + callbacks.onShellExecutionComplete?.({ exitCode: 0 }, successfulTerminalProcess) + return successfulProcess + }), + getCurrentWorkingDirectory: vitest.fn().mockReturnValue("/test/workspace"), + } as never) + + await executeCommandTool.handle(mockCline as unknown as Task, mockToolUse, { + askApproval: mockAskApproval as unknown as AskApproval, + handleError: mockHandleError as unknown as HandleError, + pushToolResult: mockPushToolResult as unknown as PushToolResult, + }) + + expect(provider.postMessageToWebview).toHaveBeenCalledWith( + expect.objectContaining({ + type: "commandExecutionStatus", + text: expect.stringContaining('"status":"fallback"'), + }), + ) + expect(TerminalRegistry.getOrCreateTerminal).toHaveBeenCalledTimes(2) + }) + it.each([ [undefined, undefined, "executeCommand.destructiveCommandGuard.blocked"], ["matches a destructive pattern", undefined, "executeCommand.destructiveCommandGuard.blockedWithReason"], @@ -580,7 +645,7 @@ describe("executeCommandTool", () => { mockCline.providerRef.deref.mockResolvedValue({ contextProxy: { getValue: vitest.fn().mockReturnValue(false) }, getState: vitest.fn().mockResolvedValue({ terminalShellIntegrationDisabled: false }), - postMessageToWebview: vitest.fn(), + postMessageToWebview: vitest.fn().mockResolvedValue(undefined), }) vitest.spyOn(Terminal, "isActiveShellCmdExe").mockReturnValue(false) const terminal = await setupControllableTerminal() diff --git a/src/core/tools/__tests__/updateTodoListTool.spec.ts b/src/core/tools/__tests__/updateTodoListTool.spec.ts index ebe0500d66..6700764418 100644 --- a/src/core/tools/__tests__/updateTodoListTool.spec.ts +++ b/src/core/tools/__tests__/updateTodoListTool.spec.ts @@ -1,6 +1,43 @@ import { describe, it, expect, beforeEach, vi } from "vitest" -import { parseMarkdownChecklist } from "../UpdateTodoListTool" +import { parseMarkdownChecklist, setPendingTodoList, updateTodoListTool } from "../UpdateTodoListTool" import { TodoItem } from "@roo-code/types" +import type { Task } from "../../task/Task" +import type { ToolCallbacks } from "../BaseTool" + +describe("UpdateTodoListTool", () => { + it("persists the edited todo list even if the say notification fails", async () => { + const editedTodos: TodoItem[] = [{ id: "edited", content: "Edited task", status: "in_progress" }] + const consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => undefined) + const task = { + consecutiveMistakeCount: 0, + recordToolError: vi.fn(), + didToolFailInCurrentTurn: false, + todoList: [], + say: vi.fn().mockRejectedValue(new Error("say failed")), + } as unknown as Task + const callbacks = { + pushToolResult: vi.fn(), + handleError: vi.fn(), + askApproval: vi.fn().mockImplementation(async () => { + setPendingTodoList(editedTodos) + return true + }), + } as unknown as ToolCallbacks + + await updateTodoListTool.execute({ todos: "[ ] Original task" }, task, callbacks) + await new Promise((resolve) => setImmediate(resolve)) + + // Notification is fire-and-forget: persistence happens regardless, and the + // rejection is logged rather than routed to handleError (which would abort). + expect(task.todoList).toEqual(editedTodos) + expect(callbacks.handleError).not.toHaveBeenCalled() + expect(consoleErrorSpy).toHaveBeenCalledWith( + "[UpdateTodoListTool] Failed to post user_edit_todos:", + expect.any(Error), + ) + consoleErrorSpy.mockRestore() + }) +}) describe("parseMarkdownChecklist", () => { describe("standard checkbox format (without dash prefix)", () => { diff --git a/src/eslint.config.mjs b/src/eslint.config.mjs index 27341c6770..903445b7f5 100644 --- a/src/eslint.config.mjs +++ b/src/eslint.config.mjs @@ -52,7 +52,7 @@ export default [ { // Ratchet: enforce no-floating-promises directory by directory. Each // directory is added here once its floating promises are resolved. - files: ["activate/**/*.ts", "core/task/**/*.ts", "core/webview/**/*.ts"], + files: ["activate/**/*.ts", "core/task/**/*.ts", "core/tools/**/*.ts", "core/webview/**/*.ts"], languageOptions: { parserOptions: { project: true, From 6ad8a6e581d7f881f90fd434927c99066f04d27b Mon Sep 17 00:00:00 2001 From: James Mtendamema <59908268+JamesRobert20@users.noreply.github.com> Date: Sat, 22 Aug 2026 04:07:33 +0000 Subject: [PATCH 43/66] fix(zoo-gateway): stop inventing UI cost from default model prices (#1339) * fix(zoo-gateway): stop inventing UI cost from default model prices Stale in-memory model maps and defaultModelInfo $/token fallback made the panel overstate spend vs gateway billing after new catalog models (e.g. Alibaba promo). * fix(zoo-gateway): negative-cache missing models and cover unset usage.cost Avoid refetching the catalog on every request when an id is still absent after a fetch; retry after a short TTL. Add coverage for usage chunks that omit cost. * fix(zoo-gateway): negative-cache empty catalog misses too An empty getModels() result still records a missing-id attempt; the retry guard no longer requires a non-empty models map. * fix(zoo-gateway): refresh catalog before negative-caching a miss getModels can return a stale shared catalog for non-auth-scoped providers. Force refreshModels when the selected id is still missing so newly listed models are not blocked for the five-minute negative-cache window. * fix(zoo-gateway): include refreshModels in RouterProvider test mocks fetchModel now calls refreshModels on catalog misses; provider specs that mocked only getModels broke under CI. --- src/api/providers/__tests__/kenari.spec.ts | 4 + src/api/providers/__tests__/kimi-code.spec.ts | 5 +- src/api/providers/__tests__/lite-llm.spec.ts | 4 + src/api/providers/__tests__/nanogpt.spec.ts | 9 + .../providers/__tests__/opencode-go.spec.ts | 6 + .../providers/__tests__/openrouter.spec.ts | 4 + src/api/providers/__tests__/requesty.spec.ts | 4 + src/api/providers/__tests__/unbound.spec.ts | 4 + .../__tests__/vercel-ai-gateway.spec.ts | 4 + .../providers/__tests__/zoo-gateway.spec.ts | 320 ++++++++++++++++-- src/api/providers/router-provider.ts | 72 +++- 11 files changed, 391 insertions(+), 45 deletions(-) diff --git a/src/api/providers/__tests__/kenari.spec.ts b/src/api/providers/__tests__/kenari.spec.ts index f9d07873c6..ce629f0377 100644 --- a/src/api/providers/__tests__/kenari.spec.ts +++ b/src/api/providers/__tests__/kenari.spec.ts @@ -34,6 +34,10 @@ vitest.mock("../fetchers/modelCache", () => ({ }, }), ), + refreshModels: vitest.fn(async (options) => { + const { getModels } = await import("../fetchers/modelCache") + return getModels(options) + }), getModelsFromCache: vitest.fn().mockReturnValue(undefined), })) diff --git a/src/api/providers/__tests__/kimi-code.spec.ts b/src/api/providers/__tests__/kimi-code.spec.ts index c8343f7bc4..fe229910b8 100644 --- a/src/api/providers/__tests__/kimi-code.spec.ts +++ b/src/api/providers/__tests__/kimi-code.spec.ts @@ -17,7 +17,10 @@ vi.mock("../../../integrations/kimi-code/oauth", () => ({ }, })) -vi.mock("../fetchers/modelCache", () => ({ getModels: mockGetModels })) +vi.mock("../fetchers/modelCache", () => ({ + getModels: mockGetModels, + refreshModels: mockGetModels, +})) describe("KimiCodeHandler", () => { beforeEach(() => { diff --git a/src/api/providers/__tests__/lite-llm.spec.ts b/src/api/providers/__tests__/lite-llm.spec.ts index eee5cf52bb..20bd3b1be2 100644 --- a/src/api/providers/__tests__/lite-llm.spec.ts +++ b/src/api/providers/__tests__/lite-llm.spec.ts @@ -58,6 +58,10 @@ vi.mock("../fetchers/modelCache", () => ({ "vertex_ai/gemini-3-pro": { ...litellmDefaultModelInfo, maxTokens: 8192 }, }) }), + refreshModels: vi.fn(async (options) => { + const { getModels } = await import("../fetchers/modelCache") + return getModels(options) + }), getModelsFromCache: vi.fn().mockReturnValue(undefined), })) diff --git a/src/api/providers/__tests__/nanogpt.spec.ts b/src/api/providers/__tests__/nanogpt.spec.ts index 6ac9a17d61..3d13ea8693 100644 --- a/src/api/providers/__tests__/nanogpt.spec.ts +++ b/src/api/providers/__tests__/nanogpt.spec.ts @@ -23,6 +23,15 @@ vi.mock("../fetchers/modelCache", () => ({ supportsReasoningEffort: ["low", "medium", "high"], }, }), + refreshModels: vi.fn().mockResolvedValue({ + "model:thinking": { + maxTokens: 128000, + contextWindow: 1050000, + supportsImages: true, + supportsPromptCache: false, + supportsReasoningEffort: ["low", "medium", "high"], + }, + }), getModelsFromCache: vi.fn(), })) diff --git a/src/api/providers/__tests__/opencode-go.spec.ts b/src/api/providers/__tests__/opencode-go.spec.ts index 98209ae325..75ad5ff077 100644 --- a/src/api/providers/__tests__/opencode-go.spec.ts +++ b/src/api/providers/__tests__/opencode-go.spec.ts @@ -36,6 +36,12 @@ vitest.mock("../fetchers/modelCache", () => ({ "qwen3.7-max": { ...opencodeGoModels["qwen3.7-max"] }, }) }), + refreshModels: vitest.fn().mockImplementation(function () { + return Promise.resolve({ + "glm-5.1": { ...opencodeGoModels["glm-5.1"] }, + "qwen3.7-max": { ...opencodeGoModels["qwen3.7-max"] }, + }) + }), getModelsFromCache: vitest.fn().mockReturnValue(undefined), })) diff --git a/src/api/providers/__tests__/openrouter.spec.ts b/src/api/providers/__tests__/openrouter.spec.ts index 1e422e4ba8..18b6286d09 100644 --- a/src/api/providers/__tests__/openrouter.spec.ts +++ b/src/api/providers/__tests__/openrouter.spec.ts @@ -102,6 +102,10 @@ vitest.mock("../fetchers/modelCache", () => ({ }, }) }), + refreshModels: vitest.fn(async (options) => { + const { getModels } = await import("../fetchers/modelCache") + return getModels(options) + }), })) describe("OpenRouterHandler", () => { diff --git a/src/api/providers/__tests__/requesty.spec.ts b/src/api/providers/__tests__/requesty.spec.ts index c685da0ed2..57feb39636 100644 --- a/src/api/providers/__tests__/requesty.spec.ts +++ b/src/api/providers/__tests__/requesty.spec.ts @@ -96,6 +96,10 @@ vitest.mock("../fetchers/modelCache", () => ({ }, }) }), + refreshModels: vitest.fn(async (options) => { + const { getModels } = await import("../fetchers/modelCache") + return getModels(options) + }), })) describe("RequestyHandler", () => { diff --git a/src/api/providers/__tests__/unbound.spec.ts b/src/api/providers/__tests__/unbound.spec.ts index 9b45713386..99f11d7b6f 100644 --- a/src/api/providers/__tests__/unbound.spec.ts +++ b/src/api/providers/__tests__/unbound.spec.ts @@ -32,6 +32,10 @@ vi.mock("../fetchers/modelCache", () => ({ description: "GPT-4o", }, }), + refreshModels: vi.fn(async (options) => { + const { getModels } = await import("../fetchers/modelCache") + return getModels(options) + }), })) describe("UnboundHandler", () => { diff --git a/src/api/providers/__tests__/vercel-ai-gateway.spec.ts b/src/api/providers/__tests__/vercel-ai-gateway.spec.ts index ffad3fa0d1..b238d72381 100644 --- a/src/api/providers/__tests__/vercel-ai-gateway.spec.ts +++ b/src/api/providers/__tests__/vercel-ai-gateway.spec.ts @@ -99,6 +99,10 @@ vitest.mock("../fetchers/modelCache", () => ({ }, }) }), + refreshModels: vitest.fn(async (options) => { + const { getModels } = await import("../fetchers/modelCache") + return getModels(options) + }), getModelsFromCache: vitest.fn().mockReturnValue(undefined), })) diff --git a/src/api/providers/__tests__/zoo-gateway.spec.ts b/src/api/providers/__tests__/zoo-gateway.spec.ts index 66131d7cb1..c6f4c15c1e 100644 --- a/src/api/providers/__tests__/zoo-gateway.spec.ts +++ b/src/api/providers/__tests__/zoo-gateway.spec.ts @@ -43,32 +43,37 @@ vitest.mock("delay", () => ({ return Promise.resolve() }), })) +const DEFAULT_MODEL_CATALOG = vitest.hoisted(() => ({ + "anthropic/claude-sonnet-4": { + maxTokens: 64000, + contextWindow: 200000, + supportsImages: true, + supportsPromptCache: true, + inputPrice: 3, + outputPrice: 15, + cacheWritesPrice: 3.75, + cacheReadsPrice: 0.3, + description: "Claude Sonnet 4", + }, + "anthropic/claude-3.5-haiku": { + maxTokens: 32000, + contextWindow: 200000, + supportsImages: true, + supportsPromptCache: true, + inputPrice: 1, + outputPrice: 5, + cacheWritesPrice: 1.25, + cacheReadsPrice: 0.1, + description: "Claude 3.5 Haiku", + }, +})) + vitest.mock("../fetchers/modelCache", () => ({ getModels: vitest.fn().mockImplementation(function () { - return Promise.resolve({ - "anthropic/claude-sonnet-4": { - maxTokens: 64000, - contextWindow: 200000, - supportsImages: true, - supportsPromptCache: true, - inputPrice: 3, - outputPrice: 15, - cacheWritesPrice: 3.75, - cacheReadsPrice: 0.3, - description: "Claude Sonnet 4", - }, - "anthropic/claude-3.5-haiku": { - maxTokens: 32000, - contextWindow: 200000, - supportsImages: true, - supportsPromptCache: true, - inputPrice: 1, - outputPrice: 5, - cacheWritesPrice: 1.25, - cacheReadsPrice: 0.1, - description: "Claude 3.5 Haiku", - }, - }) + return Promise.resolve(DEFAULT_MODEL_CATALOG) + }), + refreshModels: vitest.fn().mockImplementation(function () { + return Promise.resolve(DEFAULT_MODEL_CATALOG) }), getModelsFromCache: vitest.fn().mockReturnValue(undefined), })) @@ -119,8 +124,22 @@ describe("ZooGatewayHandler", () => { zooGatewayModelId: "anthropic/claude-sonnet-4", } - beforeEach(() => { + beforeEach(async () => { clearAllMocks() + const { getModels, refreshModels, getModelsFromCache } = await import("../fetchers/modelCache") + vitest + .mocked(getModels) + .mockReset() + .mockImplementation(function () { + return Promise.resolve(DEFAULT_MODEL_CATALOG) + }) + vitest + .mocked(refreshModels) + .mockReset() + .mockImplementation(function () { + return Promise.resolve(DEFAULT_MODEL_CATALOG) + }) + vitest.mocked(getModelsFromCache).mockReset().mockReturnValue(undefined) mockSessionCleared.value = false mockGetCachedZooCodeToken.mockReturnValue(undefined) mockCreate.mockClear() @@ -277,6 +296,73 @@ describe("ZooGatewayHandler", () => { ]) }) + it("forwards gateway usage.cost as totalCost so the panel matches billing", async () => { + mockCreate.mockImplementation(async () => + asyncStreamFrom([ + { + choices: [{ delta: { content: "ok" }, index: 0 }], + usage: null, + }, + { + choices: [{ delta: {}, index: 0 }], + usage: { + prompt_tokens: 25694, + completion_tokens: 829, + total_tokens: 26523, + cost: 0.006262, + }, + }, + ]), + ) + + const handler = new ZooGatewayHandler(mockOptions) + const chunks = await collectStream( + handler.createMessage("You are helpful.", [{ role: "user", content: "Hello" }]), + ) + + expect(chunks).toContainEqual({ + type: "usage", + inputTokens: 25694, + outputTokens: 829, + cacheWriteTokens: undefined, + cacheReadTokens: undefined, + totalCost: 0.006262, + }) + }) + + it("defaults totalCost to 0 when usage omits cost", async () => { + mockCreate.mockImplementation(async () => + asyncStreamFrom([ + { + choices: [{ delta: { content: "ok" }, index: 0 }], + usage: null, + }, + { + choices: [{ delta: {}, index: 0 }], + usage: { + prompt_tokens: 10, + completion_tokens: 5, + total_tokens: 15, + }, + }, + ]), + ) + + const handler = new ZooGatewayHandler(mockOptions) + const chunks = await collectStream( + handler.createMessage("You are helpful.", [{ role: "user", content: "Hello" }]), + ) + + expect(chunks).toContainEqual({ + type: "usage", + inputTokens: 10, + outputTokens: 5, + cacheWriteTokens: undefined, + cacheReadTokens: undefined, + totalCost: 0, + }) + }) + it("forwards task and mode metadata as request headers", async () => { const handler = new ZooGatewayHandler(mockOptions) @@ -628,45 +714,218 @@ describe("ZooGatewayHandler", () => { describe("ensureModelFetched", () => { it("fetches models when instance models are empty", async () => { const handler = new ZooGatewayHandler(mockOptions) - const { getModels } = await import("../fetchers/modelCache") + const { getModels, refreshModels } = await import("../fetchers/modelCache") expect(handler.getModel().info.contextWindow).toBe(200000) await handler.ensureModelFetched() expect(getModels).toHaveBeenCalled() + expect(refreshModels).not.toHaveBeenCalled() }) it("skips the fetch when models are already populated", async () => { const handler = new ZooGatewayHandler(mockOptions) - const { getModels } = await import("../fetchers/modelCache") + const { getModels, refreshModels } = await import("../fetchers/modelCache") await handler.ensureModelFetched() vitest.mocked(getModels).mockClear() + vitest.mocked(refreshModels).mockClear() await handler.ensureModelFetched() expect(getModels).not.toHaveBeenCalled() + expect(refreshModels).not.toHaveBeenCalled() }) it("short-circuits a subsequent fetchModel call after models are populated", async () => { const handler = new ZooGatewayHandler(mockOptions) - const { getModels } = await import("../fetchers/modelCache") + const { getModels, refreshModels } = await import("../fetchers/modelCache") await handler.ensureModelFetched() vitest.mocked(getModels).mockClear() + vitest.mocked(refreshModels).mockClear() await handler.fetchModel() expect(getModels).not.toHaveBeenCalled() + expect(refreshModels).not.toHaveBeenCalled() + }) + + it("refetches when the configured model is missing from a populated map", async () => { + vitest.useFakeTimers() + try { + const { getModels, refreshModels } = await import("../fetchers/modelCache") + const staleCatalog = { + "anthropic/claude-sonnet-4": { + maxTokens: 64000, + contextWindow: 200000, + supportsImages: true, + supportsPromptCache: true, + inputPrice: 3, + outputPrice: 15, + }, + } + vitest.mocked(getModels).mockResolvedValueOnce(staleCatalog) + vitest.mocked(refreshModels).mockResolvedValueOnce(staleCatalog) + + const handler = new ZooGatewayHandler({ + ...mockOptions, + zooGatewayModelId: "alibaba/qwen3.8-max", + }) + + await handler.ensureModelFetched() + expect(handler.getModel().info.inputPrice).toBe(0) + + const freshCatalog = { + "alibaba/qwen3.8-max": { + maxTokens: 65536, + contextWindow: 1_000_000, + supportsImages: true, + supportsPromptCache: true, + inputPrice: 0.222, + outputPrice: 0.667, + }, + } + vitest.mocked(getModels).mockClear() + vitest.mocked(refreshModels).mockClear() + vitest.mocked(getModels).mockResolvedValueOnce(freshCatalog) + + vitest.advanceTimersByTime(5 * 60 * 1000 + 1) + await handler.ensureModelFetched() + + expect(getModels).toHaveBeenCalled() + expect(refreshModels).not.toHaveBeenCalled() + expect(handler.getModel().info.inputPrice).toBe(0.222) + expect(handler.getModel().info.outputPrice).toBe(0.667) + } finally { + vitest.useRealTimers() + } + }) + + it("does not reuse default model prices for an unknown configured model", async () => { + const { getModels, refreshModels } = await import("../fetchers/modelCache") + vitest.mocked(getModels).mockResolvedValueOnce({}) + vitest.mocked(refreshModels).mockResolvedValueOnce({}) + + const handler = new ZooGatewayHandler({ + ...mockOptions, + zooGatewayModelId: "alibaba/qwen3.8-max", + }) + + await handler.ensureModelFetched() + + const { id, info } = handler.getModel() + expect(id).toBe("alibaba/qwen3.8-max") + expect(info.inputPrice).toBe(0) + expect(info.outputPrice).toBe(0) + expect(info.cacheWritesPrice).toBe(0) + expect(info.cacheReadsPrice).toBe(0) + }) + + it("does not refetch an unresolved model on every ensureModelFetched call", async () => { + const { getModels, refreshModels } = await import("../fetchers/modelCache") + const catalog = { + "anthropic/claude-sonnet-4": { + maxTokens: 64000, + contextWindow: 200000, + supportsImages: true, + supportsPromptCache: true, + inputPrice: 3, + outputPrice: 15, + }, + } + vitest.mocked(getModels).mockResolvedValue(catalog) + vitest.mocked(refreshModels).mockResolvedValue(catalog) + + const handler = new ZooGatewayHandler({ + ...mockOptions, + zooGatewayModelId: "alibaba/qwen3.8-max", + }) + + await handler.ensureModelFetched() + vitest.mocked(getModels).mockClear() + vitest.mocked(refreshModels).mockClear() + + await handler.ensureModelFetched() + await handler.ensureModelFetched() + + expect(getModels).not.toHaveBeenCalled() + expect(refreshModels).not.toHaveBeenCalled() + expect(handler.getModel().info.inputPrice).toBe(0) + }) + + it("negative-caches an empty catalog response for a missing model", async () => { + const { getModels, refreshModels } = await import("../fetchers/modelCache") + vitest.mocked(getModels).mockResolvedValue({}) + vitest.mocked(refreshModels).mockResolvedValue({}) + + const handler = new ZooGatewayHandler({ + ...mockOptions, + zooGatewayModelId: "alibaba/qwen3.8-max", + }) + + await handler.ensureModelFetched() + vitest.mocked(getModels).mockClear() + vitest.mocked(refreshModels).mockClear() + + await handler.ensureModelFetched() + + expect(getModels).not.toHaveBeenCalled() + expect(refreshModels).not.toHaveBeenCalled() + expect(handler.getModel().info.inputPrice).toBe(0) + }) + + it("force-refreshes before negative-caching when shared catalog is stale", async () => { + const { getModels, refreshModels } = await import("../fetchers/modelCache") + vitest.mocked(getModels).mockResolvedValueOnce({ + "anthropic/claude-sonnet-4": { + maxTokens: 64000, + contextWindow: 200000, + supportsImages: true, + supportsPromptCache: true, + inputPrice: 3, + outputPrice: 15, + }, + }) + vitest.mocked(refreshModels).mockResolvedValueOnce({ + "alibaba/qwen3.8-max": { + maxTokens: 65536, + contextWindow: 1_000_000, + supportsImages: true, + supportsPromptCache: true, + inputPrice: 0.222, + outputPrice: 0.667, + }, + }) + + const handler = new ZooGatewayHandler({ + ...mockOptions, + zooGatewayModelId: "alibaba/qwen3.8-max", + }) + + await handler.ensureModelFetched() + + expect(getModels).toHaveBeenCalled() + expect(refreshModels).toHaveBeenCalled() + expect(handler.getModel().info.inputPrice).toBe(0.222) + expect(handler.getModel().info.outputPrice).toBe(0.667) + + vitest.mocked(getModels).mockClear() + vitest.mocked(refreshModels).mockClear() + await handler.ensureModelFetched() + expect(getModels).not.toHaveBeenCalled() + expect(refreshModels).not.toHaveBeenCalled() }) it("deduplicates concurrent calls into a single fetch", async () => { const handler = new ZooGatewayHandler(mockOptions) - const { getModels } = await import("../fetchers/modelCache") + const { getModels, refreshModels } = await import("../fetchers/modelCache") vitest.mocked(getModels).mockClear() + vitest.mocked(refreshModels).mockClear() await Promise.all([handler.ensureModelFetched(), handler.ensureModelFetched()]) expect(getModels).toHaveBeenCalledTimes(1) + expect(refreshModels).not.toHaveBeenCalled() }) it("recovers after a rejected fetch so later calls are not poisoned", async () => { @@ -690,7 +949,7 @@ describe("ZooGatewayHandler", () => { }) it("makes getModel return the fetched context window instead of the default", async () => { - const { getModels } = await import("../fetchers/modelCache") + const { getModels, refreshModels } = await import("../fetchers/modelCache") vitest.mocked(getModels).mockResolvedValueOnce({ "google/gemini-2.5-pro": { maxTokens: 65536, @@ -710,6 +969,7 @@ describe("ZooGatewayHandler", () => { await handler.ensureModelFetched() expect(handler.getModel().info.contextWindow).toBe(1048576) + expect(refreshModels).not.toHaveBeenCalled() }) }) }) diff --git a/src/api/providers/router-provider.ts b/src/api/providers/router-provider.ts index 65ac904b87..7292824da8 100644 --- a/src/api/providers/router-provider.ts +++ b/src/api/providers/router-provider.ts @@ -5,7 +5,7 @@ import { type ModelInfo, type ModelRecord } from "@roo-code/types" import { ApiHandlerOptions, RouterName } from "../../shared/api" import { BaseProvider } from "./base-provider" -import { getModels, getModelsFromCache } from "./fetchers/modelCache" +import { getModels, getModelsFromCache, refreshModels } from "./fetchers/modelCache" import { DEFAULT_HEADERS, NOT_PROVIDED } from "./constants" @@ -51,25 +51,58 @@ export abstract class RouterProvider extends BaseProvider { } private modelFetchPromise?: Promise<{ id: string; info: ModelInfo }> + /** Last catalog refresh attempt per missing model id (ms), for negative caching. */ + private missingModelRefreshAt = new Map() + private static readonly MISSING_MODEL_RETRY_MS = 5 * 60 * 1000 public async fetchModel() { - if (Object.keys(this.models).length > 0) { + // Refetch when the selected model is missing — a stale non-empty map + // would otherwise keep serving defaultModelInfo prices for cost estimates. + const id = this.modelId || this.defaultModelId + if (this.models[id]) { + return this.getModel() + } + + // After a catalog fetch that still lacks this id, don't hammer getModels + // on every createMessage; retry only after the negative-cache window. + const lastMissingAttempt = this.missingModelRefreshAt.get(id) + if ( + lastMissingAttempt !== undefined && + Date.now() - lastMissingAttempt < RouterProvider.MISSING_MODEL_RETRY_MS + ) { return this.getModel() } if (!this.modelFetchPromise) { - this.modelFetchPromise = getModels({ + const fetchOptions = { provider: this.name, apiKey: this.apiKey, baseUrl: this.client.baseURL, - }) - .then((models) => { + } + + this.modelFetchPromise = (async () => { + let models = await getModels(fetchOptions) + this.models = models + + // getModels may return a shared cached catalog that predates this + // model. Force a provider refresh before recording a miss so + // newly listed models are not blocked for MISSING_MODEL_RETRY_MS. + // Auth-scoped providers already bypass that cache in getModels; + // refreshModels is then a no-op extra live fetch only on true misses. + if (!models[id]) { + models = await refreshModels(fetchOptions) this.models = models - return this.getModel() - }) - .finally(() => { - this.modelFetchPromise = undefined - }) + } + + if (models[id]) { + this.missingModelRefreshAt.delete(id) + } else { + this.missingModelRefreshAt.set(id, Date.now()) + } + return this.getModel() + })().finally(() => { + this.modelFetchPromise = undefined + }) } return this.modelFetchPromise @@ -107,10 +140,21 @@ export abstract class RouterProvider extends BaseProvider { return { id, info: cachedModels[id] } } - // Last resort: preserve the configured model ID (falling back to the default - // only when none is configured) so an as-yet-unfetched model isn't silently - // swapped for the hardcoded default. info still comes from defaults since we - // have no fetched or cached metadata for the configured model at this point. + // Last resort: keep the configured id so we don't swap models, but zero + // prices so we don't bill the UI with defaultModelInfo's $/token rates. + if (id !== this.defaultModelId) { + return { + id, + info: { + ...this.defaultModelInfo, + inputPrice: 0, + outputPrice: 0, + cacheWritesPrice: 0, + cacheReadsPrice: 0, + }, + } + } + return { id, info: this.defaultModelInfo } } From fec4e135300c9d81dcb6278b424018998c89f9f0 Mon Sep 17 00:00:00 2001 From: "zoomote[bot]" <305051434+zoomote[bot]@users.noreply.github.com> Date: Sat, 22 Aug 2026 04:23:15 +0000 Subject: [PATCH 44/66] [Improve] Keep shared controls legible across IDE themes (#1333) * test(webview): add WCAG contrast audit * test(webview): add contrast snapshot baselines * test(webview): harden contrast assertions * test(webview): refresh resting contrast baselines * test(webview): refresh focus contrast baselines * fix(webview): strengthen field focus contrast * test(webview): capture accessible focus baselines * test(webview): assign visual fixtures to CT coverage * docs(webview): document CI visual baseline fallback * test(webview): snapshot production chat and UI settings * fix(webview): scope visual test type shim * fix(webview): align contrast tests with modern themes * test(webview): add pinned production baselines * test(webview): refresh modern theme baselines * test(webview): refresh light dialog baseline * test(webview): isolate settings theme surfaces * test(webview): refresh light settings baselines * test(webview): generate themes from pinned VS Code * test(webview): refresh generated theme baselines * test(webview): align generated theme expectations * test(webview): refresh interactive theme states * test(webview): refresh focused theme baselines * test(webview): refresh dark dialog baseline * ci(webview): check generated theme drift * test(webview): stabilize generated theme fonts * test(webview): normalize fixture typography * test(webview): cover theme fixture validation * refactor(theme-fixtures): move theme probe off the public API * fix(webview): restore button mock styles lost in theme migration * test(webview): cover theme probe lifecycle --------- Co-authored-by: Roomote Co-authored-by: Elliott de Launay --- .github/workflows/visual-regression.yml | 36 + apps/vscode-e2e/package.json | 4 + .../src/theme-fixtures/definitions.ts | 36 + .../src/theme-fixtures/extension.ts | 79 ++ .../src/theme-fixtures/fixtures.test.ts | 94 +++ .../vscode-e2e/src/theme-fixtures/fixtures.ts | 77 ++ .../vscode-e2e/src/theme-fixtures/generate.ts | 145 ++++ packages/types/src/api.ts | 5 + packages/types/src/vscode-extension-host.ts | 10 + src/core/webview/ClineProvider.ts | 51 +- .../webview/__tests__/ClineProvider.spec.ts | 64 ++ .../__tests__/webviewMessageHandler.spec.ts | 45 + src/core/webview/webviewMessageHandler.ts | 5 + .../__tests__/api-theme-fixture.spec.ts | 30 + src/extension/api.ts | 5 + webview-ui/AGENTS.md | 7 + webview-ui/playwright-ct.config.ts | 53 +- webview-ui/playwright/AppProviders.tsx | 57 ++ .../playwright/ExtensionStateContext.tsx | 42 + webview-ui/playwright/contrast.ts | 200 +++++ webview-ui/playwright/index.tsx | 7 +- webview-ui/playwright/roo-code-types.ts | 50 ++ webview-ui/playwright/themes.ts | 28 + .../playwright/themes/vscode-theme-dark.css | 778 +++++++++++++++++ .../vscode-theme-high-contrast-light.css | 693 ++++++++++++++++ .../themes/vscode-theme-high-contrast.css | 655 +++++++++++++++ .../playwright/themes/vscode-theme-light.css | 780 ++++++++++++++++++ webview-ui/playwright/vscode-theme-base.css | 41 + webview-ui/playwright/vscode-theme-dark.css | 113 --- webview-ui/playwright/vscode-theme-light.css | 38 - webview-ui/src/App.tsx | 3 + webview-ui/src/components/chat/ChatRow.tsx | 2 +- .../src/components/chat/ChatTextArea.tsx | 2 +- webview-ui/src/components/chat/ChatView.tsx | 2 +- .../__tests__/ChatTextArea.visual.fixture.tsx | 35 + .../chat/__tests__/ChatTextArea.visual.tsx | 29 + .../__tests__/ThemeAwareControls.visual.tsx | 18 +- .../__tests__/ThemeTokenCleanup.visual.tsx | 10 +- .../chat-composer-focus-dark.png | Bin 0 -> 9166 bytes ...hat-composer-focus-high-contrast-light.png | Bin 0 -> 9606 bytes .../chat-composer-focus-high-contrast.png | Bin 0 -> 9624 bytes .../chat-composer-focus-light.png | Bin 0 -> 9326 bytes .../chat-composer-resting-dark.png | Bin 0 -> 9162 bytes ...t-composer-resting-high-contrast-light.png | Bin 0 -> 9606 bytes .../chat-composer-resting-high-contrast.png | Bin 0 -> 9624 bytes .../chat-composer-resting-light.png | Bin 0 -> 9326 bytes .../chat-controls-delete-dialog-dark.png | Bin 4945 -> 4965 bytes .../chat-controls-delete-dialog-light.png | Bin 5113 -> 5148 bytes .../chat-controls-focus-dark.png | Bin 5327 -> 5464 bytes .../chat-controls-focus-light.png | Bin 5233 -> 5294 bytes .../chat-controls-resting-dark.png | Bin 5187 -> 5303 bytes .../chat-controls-resting-light.png | Bin 5112 -> 5150 bytes .../remaining-controls-active-dark.png | Bin 1662 -> 1727 bytes .../remaining-controls-active-light.png | Bin 1623 -> 1637 bytes .../remaining-controls-resting-dark.png | Bin 1501 -> 1528 bytes .../remaining-controls-resting-light.png | Bin 1506 -> 1508 bytes webview-ui/src/components/chat/constants.ts | 1 + .../common/__tests__/MermaidBlock.visual.tsx | 95 +-- .../__screenshots__/mermaid-gantt-dark.png | Bin 9605 -> 8318 bytes .../mermaid-gantt-high-contrast-light.png | Bin 9798 -> 8661 bytes .../mermaid-gantt-high-contrast.png | Bin 10617 -> 8792 bytes .../__screenshots__/mermaid-gantt-light.png | Bin 9954 -> 8574 bytes .../__screenshots__/telemetry-banner-dark.png | Bin 12206 -> 12140 bytes .../common/__tests__/contrast.spec.ts | 42 + .../__tests__/UISettings.visual.fixture.tsx | 53 ++ .../settings/__tests__/UISettings.visual.tsx | 23 + .../model-info-service-tier-pricing-dark.png | Bin 18087 -> 20095 bytes .../__screenshots__/ui-settings-dark.png | Bin 0 -> 46842 bytes .../ui-settings-high-contrast-light.png | Bin 0 -> 47781 bytes .../ui-settings-high-contrast.png | Bin 0 -> 47818 bytes .../__screenshots__/ui-settings-light.png | Bin 0 -> 47491 bytes .../__tests__/OpenAICodex.visual.tsx | 6 +- .../__tests__/OpenAICompatible.visual.tsx | 2 +- ...penai-codex-speed-selector-states-dark.png | Bin 8208 -> 7318 bytes ...enai-codex-speed-selector-states-light.png | Bin 7853 -> 7347 bytes .../openai-compatible-azure-guidance-dark.png | Bin 32386 -> 27787 bytes .../AccessibilityContrast.visual.fixture.tsx | 90 ++ .../AccessibilityContrast.visual.tsx | 149 ++++ .../accessibility-gallery-focus-dark.png | Bin 0 -> 30931 bytes ...lity-gallery-focus-high-contrast-light.png | Bin 0 -> 31379 bytes ...essibility-gallery-focus-high-contrast.png | Bin 0 -> 28847 bytes .../accessibility-gallery-focus-light.png | Bin 0 -> 30848 bytes .../accessibility-gallery-resting-dark.png | Bin 0 -> 30436 bytes ...ty-gallery-resting-high-contrast-light.png | Bin 0 -> 31031 bytes ...sibility-gallery-resting-high-contrast.png | Bin 0 -> 28423 bytes .../accessibility-gallery-resting-light.png | Bin 0 -> 30505 bytes webview-ui/src/components/ui/button.tsx | 5 +- webview-ui/src/components/ui/input.tsx | 2 +- webview-ui/src/components/ui/progress.tsx | 2 +- webview-ui/src/components/ui/radio-group.tsx | 4 +- webview-ui/src/components/ui/slider.tsx | 11 +- webview-ui/src/components/ui/textarea.tsx | 4 +- webview-ui/src/index.css | 8 +- .../__tests__/useThemeFixtureProbe.test.ts | 101 +++ webview-ui/src/utils/useThemeFixtureProbe.ts | 68 ++ webview-ui/vitest.config.ts | 2 + 96 files changed, 4716 insertions(+), 281 deletions(-) create mode 100644 apps/vscode-e2e/src/theme-fixtures/definitions.ts create mode 100644 apps/vscode-e2e/src/theme-fixtures/extension.ts create mode 100644 apps/vscode-e2e/src/theme-fixtures/fixtures.test.ts create mode 100644 apps/vscode-e2e/src/theme-fixtures/fixtures.ts create mode 100644 apps/vscode-e2e/src/theme-fixtures/generate.ts create mode 100644 src/extension/__tests__/api-theme-fixture.spec.ts create mode 100644 webview-ui/playwright/AppProviders.tsx create mode 100644 webview-ui/playwright/ExtensionStateContext.tsx create mode 100644 webview-ui/playwright/contrast.ts create mode 100644 webview-ui/playwright/roo-code-types.ts create mode 100644 webview-ui/playwright/themes.ts create mode 100644 webview-ui/playwright/themes/vscode-theme-dark.css create mode 100644 webview-ui/playwright/themes/vscode-theme-high-contrast-light.css create mode 100644 webview-ui/playwright/themes/vscode-theme-high-contrast.css create mode 100644 webview-ui/playwright/themes/vscode-theme-light.css create mode 100644 webview-ui/playwright/vscode-theme-base.css delete mode 100644 webview-ui/playwright/vscode-theme-dark.css delete mode 100644 webview-ui/playwright/vscode-theme-light.css create mode 100644 webview-ui/src/components/chat/__tests__/ChatTextArea.visual.fixture.tsx create mode 100644 webview-ui/src/components/chat/__tests__/ChatTextArea.visual.tsx create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/chat-composer-focus-dark.png create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/chat-composer-focus-high-contrast-light.png create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/chat-composer-focus-high-contrast.png create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/chat-composer-focus-light.png create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/chat-composer-resting-dark.png create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/chat-composer-resting-high-contrast-light.png create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/chat-composer-resting-high-contrast.png create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/chat-composer-resting-light.png create mode 100644 webview-ui/src/components/chat/constants.ts create mode 100644 webview-ui/src/components/common/__tests__/contrast.spec.ts create mode 100644 webview-ui/src/components/settings/__tests__/UISettings.visual.fixture.tsx create mode 100644 webview-ui/src/components/settings/__tests__/UISettings.visual.tsx create mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/ui-settings-dark.png create mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/ui-settings-high-contrast-light.png create mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/ui-settings-high-contrast.png create mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/ui-settings-light.png create mode 100644 webview-ui/src/components/ui/__tests__/AccessibilityContrast.visual.fixture.tsx create mode 100644 webview-ui/src/components/ui/__tests__/AccessibilityContrast.visual.tsx create mode 100644 webview-ui/src/components/ui/__tests__/__screenshots__/accessibility-gallery-focus-dark.png create mode 100644 webview-ui/src/components/ui/__tests__/__screenshots__/accessibility-gallery-focus-high-contrast-light.png create mode 100644 webview-ui/src/components/ui/__tests__/__screenshots__/accessibility-gallery-focus-high-contrast.png create mode 100644 webview-ui/src/components/ui/__tests__/__screenshots__/accessibility-gallery-focus-light.png create mode 100644 webview-ui/src/components/ui/__tests__/__screenshots__/accessibility-gallery-resting-dark.png create mode 100644 webview-ui/src/components/ui/__tests__/__screenshots__/accessibility-gallery-resting-high-contrast-light.png create mode 100644 webview-ui/src/components/ui/__tests__/__screenshots__/accessibility-gallery-resting-high-contrast.png create mode 100644 webview-ui/src/components/ui/__tests__/__screenshots__/accessibility-gallery-resting-light.png create mode 100644 webview-ui/src/utils/__tests__/useThemeFixtureProbe.test.ts create mode 100644 webview-ui/src/utils/useThemeFixtureProbe.ts diff --git a/.github/workflows/visual-regression.yml b/.github/workflows/visual-regression.yml index 6160ea6be0..ec6a8c540b 100644 --- a/.github/workflows/visual-regression.yml +++ b/.github/workflows/visual-regression.yml @@ -5,6 +5,13 @@ on: pull_request: types: [opened, reopened, ready_for_review, synchronize] paths: + - "apps/vscode-e2e/package.json" + - "apps/vscode-e2e/src/theme-fixtures/**" + - "packages/types/src/api.ts" + - "packages/types/src/vscode-extension-host.ts" + - "src/core/webview/ClineProvider.ts" + - "src/core/webview/webviewMessageHandler.ts" + - "src/extension/api.ts" - "webview-ui/**" - "src/shared/**" - "package.json" @@ -55,3 +62,32 @@ jobs: webview-ui/playwright-report webview-ui/test-results if-no-files-found: ignore + + theme-fixtures: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - name: Checkout code + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false + - name: Setup Node.js and pnpm + uses: ./.github/actions/setup-node-pnpm + with: + install-args: "--frozen-lockfile" + - name: Install xvfb + run: sudo apt-get install -y xvfb + - name: Get pinned VS Code version + id: vscode-version + run: | + VERSION=$(node -p 'require("./apps/vscode-e2e/package.json").devDependencies["@types/vscode"]') + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + - name: Cache pinned VS Code + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + with: + path: apps/vscode-e2e/.vscode-test/ + key: vscode-theme-fixtures-${{ runner.os }}-${{ steps.vscode-version.outputs.version }}-v1 + - name: Test theme fixture serialization + run: pnpm --filter @roo-code/vscode-e2e themes:test + - name: Check generated VS Code theme fixtures + run: xvfb-run -a pnpm --filter @roo-code/vscode-e2e themes:check diff --git a/apps/vscode-e2e/package.json b/apps/vscode-e2e/package.json index 3b1a3fb18f..ac1c71d6a1 100644 --- a/apps/vscode-e2e/package.json +++ b/apps/vscode-e2e/package.json @@ -9,6 +9,10 @@ "test:ci:mock": "pnpm -w bundle && pnpm --filter @roo-code/vscode-webview build && USE_MOCK=true pnpm test:run", "test:record": "AIMOCK_RECORD=true pnpm test:ci", "test:run": "rimraf out && tsc -p tsconfig.json && dotenv -e .env.local -- node ./out/runTest.js", + "themes:build": "pnpm -w bundle && pnpm --filter @roo-code/vscode-webview build && rimraf out && tsc -p tsconfig.json", + "themes:update": "pnpm themes:build && node ./out/theme-fixtures/generate.js update", + "themes:check": "pnpm themes:build && node ./out/theme-fixtures/generate.js check", + "themes:test": "pnpm --filter @roo-code/types build && rimraf out && tsc -p tsconfig.json && node --test ./out/theme-fixtures/fixtures.test.js", "clean": "rimraf out .turbo" }, "devDependencies": { diff --git a/apps/vscode-e2e/src/theme-fixtures/definitions.ts b/apps/vscode-e2e/src/theme-fixtures/definitions.ts new file mode 100644 index 0000000000..a2359ef789 --- /dev/null +++ b/apps/vscode-e2e/src/theme-fixtures/definitions.ts @@ -0,0 +1,36 @@ +export const themeFixtureDefinitions = [ + { + name: "dark", + themeId: "Default Dark Modern", + bodyClass: "vscode-dark", + colorScheme: "dark", + kind: "dark", + }, + { + name: "light", + themeId: "Default Light Modern", + bodyClass: "vscode-light", + colorScheme: "light", + kind: "light", + }, + { + name: "high-contrast", + themeId: "Default High Contrast", + bodyClass: "vscode-high-contrast", + colorScheme: "dark", + kind: "high-contrast", + }, + { + name: "high-contrast-light", + themeId: "Default High Contrast Light", + bodyClass: "vscode-high-contrast-light", + colorScheme: "light", + kind: "high-contrast-light", + }, +] as const + +export type ThemeFixtureDefinition = (typeof themeFixtureDefinitions)[number] + +export function getThemeFixtureFileName(theme: ThemeFixtureDefinition): string { + return `vscode-theme-${theme.name}.css` +} diff --git a/apps/vscode-e2e/src/theme-fixtures/extension.ts b/apps/vscode-e2e/src/theme-fixtures/extension.ts new file mode 100644 index 0000000000..a6a026ca7a --- /dev/null +++ b/apps/vscode-e2e/src/theme-fixtures/extension.ts @@ -0,0 +1,79 @@ +import fs from "fs/promises" + +import * as vscode from "vscode" + +import type { RooCodeTestAPI, WebviewThemeFixture } from "@roo-code/types" + +import { themeFixtureDefinitions, type ThemeFixtureDefinition } from "./definitions" + +const POLL_INTERVAL_MS = 100 +const THEME_TIMEOUT_MS = 20_000 + +const colorThemeKinds: Record = { + dark: vscode.ColorThemeKind.Dark, + light: vscode.ColorThemeKind.Light, + "high-contrast": vscode.ColorThemeKind.HighContrast, + "high-contrast-light": vscode.ColorThemeKind.HighContrastLight, +} + +async function poll(capture: () => Promise, matches: (value: T) => boolean, description: string): Promise { + const deadline = Date.now() + THEME_TIMEOUT_MS + let latest: T | undefined + + while (Date.now() < deadline) { + latest = await capture() + if (matches(latest)) { + return latest + } + await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS)) + } + + throw new Error(`Timed out waiting for ${description}; latest value: ${JSON.stringify(latest)}`) +} + +function matchesTheme(fixture: WebviewThemeFixture, theme: ThemeFixtureDefinition): boolean { + return fixture.themeId === theme.themeId && fixture.bodyClass.split(/\s+/).includes(theme.bodyClass) +} + +export async function run(): Promise { + if (process.env.ROO_CODE_THEME_FIXTURE_PROBE !== "1") { + throw new Error("ROO_CODE_THEME_FIXTURE_PROBE must be set to 1") + } + + const outputPath = process.env.ROO_CODE_THEME_FIXTURE_CAPTURE_PATH + const expectedVersion = process.env.ROO_CODE_THEME_FIXTURE_VSCODE_VERSION + if (!outputPath || !expectedVersion) { + throw new Error("Theme fixture output path and VS Code version are required") + } + if (vscode.version !== expectedVersion) { + throw new Error(`Expected VS Code ${expectedVersion}, launched ${vscode.version}`) + } + + const extension = vscode.extensions.getExtension("ZooCodeOrganization.zoo-code") + if (!extension) { + throw new Error("Zoo Code extension not found") + } + const api = extension.isActive ? extension.exports : await extension.activate() + + await vscode.commands.executeCommand("zoo-code.SidebarProvider.focus") + await poll(async () => api.isReady(), Boolean, "Zoo Code webview activation") + + const captures: Record = {} + for (const theme of themeFixtureDefinitions) { + await vscode.workspace + .getConfiguration("workbench") + .update("colorTheme", theme.themeId, vscode.ConfigurationTarget.Global) + await poll( + async () => vscode.window.activeColorTheme.kind, + (kind) => kind === colorThemeKinds[theme.kind], + `${theme.themeId} color theme kind`, + ) + captures[theme.name] = await poll( + () => api.captureWebviewThemeFixture(), + (fixture) => matchesTheme(fixture, theme), + `${theme.themeId} webview identity`, + ) + } + + await fs.writeFile(outputPath, `${JSON.stringify(captures, null, 2)}\n`, "utf8") +} diff --git a/apps/vscode-e2e/src/theme-fixtures/fixtures.test.ts b/apps/vscode-e2e/src/theme-fixtures/fixtures.test.ts new file mode 100644 index 0000000000..16a66153f9 --- /dev/null +++ b/apps/vscode-e2e/src/theme-fixtures/fixtures.test.ts @@ -0,0 +1,94 @@ +import assert from "node:assert/strict" +import test from "node:test" + +import type { WebviewThemeFixture } from "@roo-code/types" + +import { themeFixtureDefinitions } from "./definitions" +import { createSerializedFixtures, findDriftedFixtures, serializeThemeFixture } from "./fixtures" + +const validVariables = Object.fromEntries( + Array.from({ length: 100 }, (_, index) => [`--vscode-test-${index}`, "#000000"]), +) +const validFixture: WebviewThemeFixture = { + themeId: "Default Dark Modern", + bodyClass: "vscode-dark", + variables: { + ...validVariables, + "--vscode-foreground": "#cccccc", + "--vscode-editor-background": "#1f1f1f", + "--vscode-button-foreground": "#ffffff", + }, +} + +test("serializeThemeFixture sorts variables and emits stable metadata", () => { + const fixture: WebviewThemeFixture = { + themeId: "Default Dark Modern", + bodyClass: "vscode-dark", + variables: { + "--vscode-z-last": "rgb(2, 2, 2)", + "--vscode-a-first": "#010101", + "--vscode-font-family": "platform-dependent", + }, + } + + assert.equal( + serializeThemeFixture(themeFixtureDefinitions[0], fixture, "1.100.0"), + [ + "/* Generated from Default Dark Modern by VS Code 1.100.0. Do not edit manually. */", + ".vscode-dark {", + "\tcolor-scheme: dark;", + "\t--vscode-a-first: #010101;", + "\t--vscode-z-last: rgb(2, 2, 2);", + "}", + "", + ].join("\n"), + ) +}) + +test("findDriftedFixtures reports missing and changed files in sorted order", () => { + const expected = new Map([ + ["vscode-theme-light.css", "light"], + ["vscode-theme-dark.css", "dark"], + ]) + const actual = new Map([["vscode-theme-light.css", "stale"]]) + + assert.deepEqual(findDriftedFixtures(expected, actual), ["vscode-theme-dark.css", "vscode-theme-light.css"]) +}) + +test("createSerializedFixtures rejects incomplete captures", () => { + const fixture: WebviewThemeFixture = { + ...validFixture, + variables: { + ...validVariables, + "--vscode-foreground": "#cccccc", + "--vscode-editor-background": "#1f1f1f", + }, + } + + assert.throws( + () => createSerializedFixtures(new Map([["dark", fixture]]), "1.100.0", [themeFixtureDefinitions[0]]), + /--vscode-button-foreground/, + ) +}) + +test("createSerializedFixtures rejects an empty capture", () => { + assert.throws( + () => + createSerializedFixtures(new Map([["dark", { ...validFixture, variables: {} }]]), "1.100.0", [ + themeFixtureDefinitions[0], + ]), + /fewer than 100/, + ) +}) + +test("createSerializedFixtures rejects the wrong theme identity", () => { + assert.throws( + () => + createSerializedFixtures( + new Map([["dark", { ...validFixture, themeId: "Default Light Modern" }]]), + "1.100.0", + [themeFixtureDefinitions[0]], + ), + /Expected Default Dark Modern/, + ) +}) diff --git a/apps/vscode-e2e/src/theme-fixtures/fixtures.ts b/apps/vscode-e2e/src/theme-fixtures/fixtures.ts new file mode 100644 index 0000000000..1cbb05a17f --- /dev/null +++ b/apps/vscode-e2e/src/theme-fixtures/fixtures.ts @@ -0,0 +1,77 @@ +import type { WebviewThemeFixture } from "@roo-code/types" + +import { getThemeFixtureFileName, type ThemeFixtureDefinition } from "./definitions" + +const requiredVariables = ["--vscode-foreground", "--vscode-editor-background", "--vscode-button-foreground"] +const minimumVariableCount = 100 +const environmentVariables = new Set(["--vscode-font-family", "--vscode-editor-font-family"]) + +export function validateThemeFixture(theme: ThemeFixtureDefinition, fixture: WebviewThemeFixture): void { + if (fixture.themeId !== theme.themeId) { + throw new Error(`Expected ${theme.themeId}, captured ${fixture.themeId || "an unknown theme"}`) + } + if (!fixture.bodyClass.split(/\s+/).includes(theme.bodyClass)) { + throw new Error(`Expected ${theme.bodyClass}, captured body classes: ${fixture.bodyClass || "none"}`) + } + if (Object.keys(fixture.variables).length < minimumVariableCount) { + throw new Error(`${theme.themeId} exposed fewer than ${minimumVariableCount} VS Code theme variables`) + } + for (const property of requiredVariables) { + if (!fixture.variables[property]) { + throw new Error(`${theme.themeId} did not expose required variable ${property}`) + } + } + for (const [property, value] of Object.entries(fixture.variables)) { + if (!property.startsWith("--vscode-") || !value) { + throw new Error(`${theme.themeId} exposed an invalid theme variable: ${property}`) + } + } +} + +export function serializeThemeFixture( + theme: ThemeFixtureDefinition, + fixture: WebviewThemeFixture, + vscodeVersion: string, +): string { + const declarations = Object.entries(fixture.variables) + .filter(([property]) => !environmentVariables.has(property)) + .sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0)) + .map(([property, value]) => `\t${property}: ${value};`) + + return [ + `/* Generated from ${theme.themeId} by VS Code ${vscodeVersion}. Do not edit manually. */`, + `.${theme.bodyClass} {`, + `\tcolor-scheme: ${theme.colorScheme};`, + ...declarations, + "}", + "", + ].join("\n") +} + +export function createSerializedFixtures( + captures: ReadonlyMap, + vscodeVersion: string, + themes: readonly ThemeFixtureDefinition[], +): Map { + return new Map( + themes.map((theme) => { + const capture = captures.get(theme.name) + if (!capture) { + throw new Error(`Missing captured theme fixture: ${theme.name}`) + } + validateThemeFixture(theme, capture) + + return [getThemeFixtureFileName(theme), serializeThemeFixture(theme, capture, vscodeVersion)] + }), + ) +} + +export function findDriftedFixtures( + expected: ReadonlyMap, + actual: ReadonlyMap, +): string[] { + return [...expected.entries()] + .filter(([fileName, contents]) => actual.get(fileName) !== contents) + .map(([fileName]) => fileName) + .sort() +} diff --git a/apps/vscode-e2e/src/theme-fixtures/generate.ts b/apps/vscode-e2e/src/theme-fixtures/generate.ts new file mode 100644 index 0000000000..60c1d9e8e7 --- /dev/null +++ b/apps/vscode-e2e/src/theme-fixtures/generate.ts @@ -0,0 +1,145 @@ +import fs from "fs/promises" +import os from "os" +import path from "path" + +import { runTests } from "@vscode/test-electron" +import type { WebviewThemeFixture } from "@roo-code/types" + +import { themeFixtureDefinitions } from "./definitions" +import { createSerializedFixtures, findDriftedFixtures } from "./fixtures" + +type GeneratorMode = "update" | "check" + +async function readPinnedVSCodeVersion(packageRoot: string): Promise { + const packageJson = JSON.parse(await fs.readFile(path.join(packageRoot, "package.json"), "utf8")) as { + devDependencies?: Record + } + const version = packageJson.devDependencies?.["@types/vscode"] + if (!version) { + throw new Error("apps/vscode-e2e/package.json does not pin @types/vscode") + } + return version +} + +async function readTrackedFixtures( + directory: string, + fileNames: Iterable, +): Promise> { + return new Map( + await Promise.all( + [...fileNames].map(async (fileName) => { + try { + return [fileName, await fs.readFile(path.join(directory, fileName), "utf8")] as const + } catch (error) { + if ((error as NodeJS.ErrnoException).code === "ENOENT") { + return [fileName, undefined] as const + } + throw error + } + }), + ), + ) +} + +async function main(): Promise { + const mode = process.argv[2] as GeneratorMode | undefined + if (mode !== "update" && mode !== "check") { + throw new Error("Usage: generate ") + } + if (process.platform !== "linux") { + throw new Error("VS Code theme fixtures must be generated on the canonical Linux environment") + } + if (!process.env.DISPLAY) { + throw new Error(`Run theme fixture generation through "xvfb-run -a"`) + } + + const packageRoot = path.resolve(__dirname, "../..") + const repositoryRoot = path.resolve(packageRoot, "../..") + const extensionDevelopmentPath = path.join(repositoryRoot, "src") + const extensionTestsPath = path.resolve(__dirname, "extension") + const fixtureDirectory = path.join(repositoryRoot, "webview-ui", "playwright", "themes") + const vscodeVersion = await readPinnedVSCodeVersion(packageRoot) + const temporaryRoot = await fs.mkdtemp(path.join(os.tmpdir(), "zoo-code-theme-fixtures-")) + const workspacePath = path.join(temporaryRoot, "workspace") + const userDataPath = path.join(temporaryRoot, "user-data") + const extensionsPath = path.join(temporaryRoot, "extensions") + const capturePath = path.join(temporaryRoot, "captures.json") + const generatedFixtureDirectory = path.join(temporaryRoot, "generated") + + try { + await Promise.all([ + fs.mkdir(workspacePath), + fs.mkdir(userDataPath), + fs.mkdir(extensionsPath), + fs.mkdir(generatedFixtureDirectory), + ]) + await runTests({ + extensionDevelopmentPath, + extensionTestsPath, + version: vscodeVersion, + launchArgs: [ + workspacePath, + `--user-data-dir=${userDataPath}`, + `--extensions-dir=${extensionsPath}`, + "--disable-workspace-trust", + "--skip-welcome", + "--skip-release-notes", + ], + extensionTestsEnv: { + ...process.env, + ROO_CODE_THEME_FIXTURE_PROBE: "1", + ROO_CODE_THEME_FIXTURE_CAPTURE_PATH: capturePath, + ROO_CODE_THEME_FIXTURE_VSCODE_VERSION: vscodeVersion, + }, + }) + + const captures = JSON.parse(await fs.readFile(capturePath, "utf8")) as Record + const generated = createSerializedFixtures( + new Map(Object.entries(captures)), + vscodeVersion, + themeFixtureDefinitions, + ) + await Promise.all( + [...generated].map(([fileName, contents]) => + fs.writeFile(path.join(generatedFixtureDirectory, fileName), contents, "utf8"), + ), + ) + + if (mode === "check") { + const [temporary, tracked] = await Promise.all([ + readTrackedFixtures(generatedFixtureDirectory, generated.keys()), + readTrackedFixtures(fixtureDirectory, generated.keys()), + ]) + const expected = new Map() + for (const [fileName, contents] of temporary) { + if (contents === undefined) { + throw new Error(`Temporary fixture was not generated: ${fileName}`) + } + expected.set(fileName, contents) + } + const drifted = findDriftedFixtures(expected, tracked) + if (drifted.length > 0) { + throw new Error( + `VS Code theme fixtures are out of date:\n${drifted.map((file) => `- ${file}`).join("\n")}`, + ) + } + console.log(`VS Code ${vscodeVersion} theme fixtures are current.`) + return + } + + await fs.mkdir(fixtureDirectory, { recursive: true }) + await Promise.all( + [...generated.keys()].map((fileName) => + fs.copyFile(path.join(generatedFixtureDirectory, fileName), path.join(fixtureDirectory, fileName)), + ), + ) + console.log(`Updated ${generated.size} theme fixtures from VS Code ${vscodeVersion}.`) + } finally { + await fs.rm(temporaryRoot, { recursive: true, force: true }) + } +} + +void main().catch((error) => { + console.error(error instanceof Error ? error.message : error) + process.exitCode = 1 +}) diff --git a/packages/types/src/api.ts b/packages/types/src/api.ts index 89e9c8bc2b..80808a274a 100644 --- a/packages/types/src/api.ts +++ b/packages/types/src/api.ts @@ -6,6 +6,7 @@ import type { RooCodeSettings } from "./global-settings.js" import type { HistoryItem } from "./history.js" import type { ProviderSettingsEntry, ProviderSettings } from "./provider-settings.js" import type { IpcMessage, IpcServerEvents } from "./ipc.js" +import type { WebviewThemeFixture } from "./vscode-extension-host.js" export type RooCodeAPIEvents = RooCodeEvents @@ -169,6 +170,10 @@ export interface RooCodeAPI extends EventEmitter { setTerminalProfile(name: string | undefined): void } +export interface RooCodeTestAPI extends RooCodeAPI { + captureWebviewThemeFixture(): Promise +} + export interface RooCodeIpcServer extends EventEmitter { listen(): void broadcast(message: IpcMessage): void diff --git a/packages/types/src/vscode-extension-host.ts b/packages/types/src/vscode-extension-host.ts index 337ad22e2c..4a9aabd102 100644 --- a/packages/types/src/vscode-extension-host.ts +++ b/packages/types/src/vscode-extension-host.ts @@ -107,6 +107,7 @@ export interface ExtensionMessage { | "rules" | "fileContent" | "rooHistoryImportProgress" + | "themeFixtureProbeRequest" text?: string /** For fileContent: { path, content, error? } */ fileContent?: { path: string; content: string | null; error?: string } @@ -154,6 +155,7 @@ export interface ExtensionMessage { // eslint-disable-next-line @typescript-eslint/no-explicit-any values?: Record requestId?: string + themeFixture?: WebviewThemeFixture promptText?: string results?: | { path: string; type: "file" | "folder"; label?: string }[] @@ -641,6 +643,7 @@ export interface WebviewMessage { | "deleteRule" | "openRuleFile" | "openRulesDirectory" + | "themeFixtureProbeResponse" text?: string taskId?: string editedMessageContent?: string @@ -687,6 +690,7 @@ export interface WebviewMessage { /** Target mode slugs for updateSkillModes */ newSkillModeSlugs?: string[] // For updateSkillModes (new mode restrictions) requestId?: string + themeFixture?: WebviewThemeFixture ids?: string[] terminalOperation?: "continue" | "abort" messageTs?: number @@ -753,6 +757,12 @@ export interface WebviewMessage { worktreeIncludeContent?: string } +export interface WebviewThemeFixture { + themeId: string + bodyClass: string + variables: Record +} + export interface RequestOpenAiCodexRateLimitsMessage { type: "requestOpenAiCodexRateLimits" } diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 2d00f25107..0761e21a4f 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -37,6 +37,7 @@ import { type ToolUsage, type ExtensionMessage, type ExtensionState, + type WebviewThemeFixture, type MarketplaceInstalledMetadata, RooCodeEventName, requestyDefaultModelId, @@ -178,6 +179,15 @@ export class ClineProvider private static activeInstances: Set = new Set() private disposables: vscode.Disposable[] = [] private webviewDisposables: vscode.Disposable[] = [] + private pendingThemeFixtureProbes = new Map< + string, + { + resolve: (fixture: WebviewThemeFixture) => void + reject: (error: Error) => void + timeout: ReturnType + } + >() + private nextThemeFixtureProbeId = 0 private view?: vscode.WebviewView | vscode.WebviewPanel private taskRegistry = new TaskRegistry() private taskScheduler = new TaskScheduler() @@ -753,6 +763,7 @@ export class ClineProvider - https://github.com/microsoft/vscode-extension-samples/blob/main/webview-sample/src/extension.ts */ private clearWebviewResources() { + this.rejectPendingThemeFixtureProbes(new Error("Webview was disposed before the theme fixture probe completed")) while (this.webviewDisposables.length) { const x = this.webviewDisposables.pop() if (x) { @@ -965,7 +976,8 @@ export class ClineProvider } webviewView.webview.html = - this.contextProxy.extensionMode === vscode.ExtensionMode.Development + this.contextProxy.extensionMode === vscode.ExtensionMode.Development && + process.env.ROO_CODE_THEME_FIXTURE_PROBE !== "1" ? await this.getHMRHtmlContent(webviewView.webview) : await this.getHtmlContent(webviewView.webview) @@ -1408,6 +1420,43 @@ export class ClineProvider } } + public requestWebviewThemeFixture(timeoutMs = 5_000): Promise { + if (process.env.ROO_CODE_THEME_FIXTURE_PROBE !== "1") { + return Promise.reject(new Error("Theme fixture probing is disabled")) + } + + const requestId = `theme-fixture-${++this.nextThemeFixtureProbeId}` + + return new Promise((resolve, reject) => { + const timeout = setTimeout(() => { + this.pendingThemeFixtureProbes.delete(requestId) + reject(new Error(`Theme fixture probe timed out after ${timeoutMs}ms`)) + }, timeoutMs) + + this.pendingThemeFixtureProbes.set(requestId, { resolve, reject, timeout }) + void this.postMessageToWebview({ type: "themeFixtureProbeRequest", requestId }) + }) + } + + public resolveWebviewThemeFixtureProbe(requestId: string, fixture: WebviewThemeFixture): void { + const pending = this.pendingThemeFixtureProbes.get(requestId) + if (!pending) { + return + } + + clearTimeout(pending.timeout) + this.pendingThemeFixtureProbes.delete(requestId) + pending.resolve(fixture) + } + + private rejectPendingThemeFixtureProbes(error: Error): void { + for (const pending of this.pendingThemeFixtureProbes.values()) { + clearTimeout(pending.timeout) + pending.reject(error) + } + this.pendingThemeFixtureProbes.clear() + } + private async getHMRHtmlContent(webview: vscode.Webview): Promise { let localPort = "5173" diff --git a/src/core/webview/__tests__/ClineProvider.spec.ts b/src/core/webview/__tests__/ClineProvider.spec.ts index fec6cef265..20b14d4ef1 100644 --- a/src/core/webview/__tests__/ClineProvider.spec.ts +++ b/src/core/webview/__tests__/ClineProvider.spec.ts @@ -771,6 +771,70 @@ describe("ClineProvider", () => { await expect(provider.postMessageToWebview(message)).resolves.toBeUndefined() }) + describe("theme fixture probes", () => { + const fixture = { + themeId: "Default Dark Modern", + bodyClass: "vscode-dark", + variables: { "--vscode-foreground": "#cccccc" }, + } + const originalProbeSetting = process.env.ROO_CODE_THEME_FIXTURE_PROBE + + beforeEach(() => { + process.env.ROO_CODE_THEME_FIXTURE_PROBE = "1" + }) + + afterEach(() => { + if (originalProbeSetting === undefined) { + delete process.env.ROO_CODE_THEME_FIXTURE_PROBE + } else { + process.env.ROO_CODE_THEME_FIXTURE_PROBE = originalProbeSetting + } + vi.useRealTimers() + }) + + test("rejects requests when probing is disabled", async () => { + delete process.env.ROO_CODE_THEME_FIXTURE_PROBE + + await expect(provider.requestWebviewThemeFixture()).rejects.toThrow("Theme fixture probing is disabled") + }) + + test("posts a request and resolves the matching response", async () => { + const postMessageSpy = vi.spyOn(provider, "postMessageToWebview").mockResolvedValue(undefined) + const request = provider.requestWebviewThemeFixture() + await Promise.resolve() + const requestId = postMessageSpy.mock.calls[0]?.[0].requestId + const unknownFixture = { ...fixture, themeId: "Unexpected Theme" } + + expect(requestId).toBeTruthy() + expect(postMessageSpy).toHaveBeenCalledWith({ type: "themeFixtureProbeRequest", requestId }) + provider.resolveWebviewThemeFixtureProbe("unknown-request", unknownFixture) + provider.resolveWebviewThemeFixtureProbe(requestId!, fixture) + + await expect(request).resolves.toEqual(fixture) + }) + + test("rejects a request after its timeout", async () => { + vi.useFakeTimers() + vi.spyOn(provider, "postMessageToWebview").mockResolvedValue(undefined) + const request = provider.requestWebviewThemeFixture(100) + const rejection = expect(request).rejects.toThrow("Theme fixture probe timed out after 100ms") + + await vi.advanceTimersByTimeAsync(100) + await rejection + }) + + test("rejects pending requests when webview resources are cleared", async () => { + vi.spyOn(provider, "postMessageToWebview").mockResolvedValue(undefined) + const request = provider.requestWebviewThemeFixture() + const rejection = expect(request).rejects.toThrow( + "Webview was disposed before the theme fixture probe completed", + ) + + provider["clearWebviewResources"]() + await rejection + }) + }) + test("postStateToWebview does not force action navigation for non-compliant MDM state", async () => { const mdmService = { requiresCloudAuth: vi.fn().mockReturnValue(true), diff --git a/src/core/webview/__tests__/webviewMessageHandler.spec.ts b/src/core/webview/__tests__/webviewMessageHandler.spec.ts index 815eb08683..9d46894756 100644 --- a/src/core/webview/__tests__/webviewMessageHandler.spec.ts +++ b/src/core/webview/__tests__/webviewMessageHandler.spec.ts @@ -117,6 +117,7 @@ const mockClineProvider = { }, log: vi.fn(), postStateToWebview: vi.fn(), + resolveWebviewThemeFixtureProbe: vi.fn(), getCurrentTask: vi.fn(), getTaskWithId: vi.fn(), createTaskWithHistoryItem: vi.fn(), @@ -124,6 +125,50 @@ const mockClineProvider = { cwd: "/mock/workspace", } as unknown as ClineProvider +describe("webviewMessageHandler - theme fixture probes", () => { + const originalProbeSetting = process.env.ROO_CODE_THEME_FIXTURE_PROBE + const themeFixture = { + themeId: "Default Dark Modern", + bodyClass: "vscode-dark", + variables: { "--vscode-foreground": "#cccccc" }, + } + + beforeEach(() => { + vi.clearAllMocks() + process.env.ROO_CODE_THEME_FIXTURE_PROBE = "1" + }) + + afterEach(() => { + if (originalProbeSetting === undefined) { + delete process.env.ROO_CODE_THEME_FIXTURE_PROBE + } else { + process.env.ROO_CODE_THEME_FIXTURE_PROBE = originalProbeSetting + } + }) + + it("resolves a complete response when probing is enabled", async () => { + await webviewMessageHandler(mockClineProvider, { + type: "themeFixtureProbeResponse", + requestId: "request-1", + themeFixture, + }) + + expect(mockClineProvider.resolveWebviewThemeFixtureProbe).toHaveBeenCalledWith("request-1", themeFixture) + }) + + it("ignores incomplete or disabled responses", async () => { + await webviewMessageHandler(mockClineProvider, { type: "themeFixtureProbeResponse" }) + delete process.env.ROO_CODE_THEME_FIXTURE_PROBE + await webviewMessageHandler(mockClineProvider, { + type: "themeFixtureProbeResponse", + requestId: "request-1", + themeFixture, + }) + + expect(mockClineProvider.resolveWebviewThemeFixtureProbe).not.toHaveBeenCalled() + }) +}) + import { t } from "../../../i18n" vi.mock("vscode", () => { diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index 8bf1c64777..cd817074d6 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -574,6 +574,11 @@ export const webviewMessageHandler = async ( } switch (message.type) { + case "themeFixtureProbeResponse": + if (process.env.ROO_CODE_THEME_FIXTURE_PROBE === "1" && message.requestId && message.themeFixture) { + provider.resolveWebviewThemeFixtureProbe(message.requestId, message.themeFixture) + } + break case "webviewDidLaunch": // Load custom modes first const customModes = await provider.customModesManager.getCustomModes() diff --git a/src/extension/__tests__/api-theme-fixture.spec.ts b/src/extension/__tests__/api-theme-fixture.spec.ts new file mode 100644 index 0000000000..6f7a378882 --- /dev/null +++ b/src/extension/__tests__/api-theme-fixture.spec.ts @@ -0,0 +1,30 @@ +import { describe, expect, it, vi } from "vitest" +import type * as vscode from "vscode" + +import { API } from "../api" +import type { ClineProvider } from "../../core/webview/ClineProvider" + +vi.mock("@roo-code/ipc", () => ({ + IpcServer: class {}, +})) + +describe("API - theme fixture probe", () => { + it("delegates capture to the sidebar provider", async () => { + const fixture = { + themeId: "Default Dark Modern", + bodyClass: "vscode-dark", + variables: { "--vscode-foreground": "#cccccc" }, + } + const requestWebviewThemeFixture = vi.fn().mockResolvedValue(fixture) + const provider = { + context: {}, + on: vi.fn(), + requestWebviewThemeFixture, + } as unknown as ClineProvider + const outputChannel = { appendLine: vi.fn() } as unknown as vscode.OutputChannel + const api = new API(outputChannel, provider) + + await expect(api.captureWebviewThemeFixture()).resolves.toEqual(fixture) + expect(requestWebviewThemeFixture).toHaveBeenCalledOnce() + }) +}) diff --git a/src/extension/api.ts b/src/extension/api.ts index b57dc89b74..16f1d402bc 100644 --- a/src/extension/api.ts +++ b/src/extension/api.ts @@ -14,6 +14,7 @@ import { type ProviderSettingsEntry, type TaskEvent, type CreateTaskOptions, + type WebviewThemeFixture, RooCodeEventName, TaskCommandName, isSecretStateKey, @@ -314,6 +315,10 @@ export class API extends EventEmitter implements RooCodeAPI { return this.sidebarProvider.viewLaunched } + public captureWebviewThemeFixture(): Promise { + return this.sidebarProvider.requestWebviewThemeFixture() + } + private async waitForWebviewLaunch(timeoutMs: number): Promise { try { await pWaitFor(() => this.sidebarProvider.viewLaunched, { diff --git a/webview-ui/AGENTS.md b/webview-ui/AGENTS.md index 892c76676a..1c74d22109 100644 --- a/webview-ui/AGENTS.md +++ b/webview-ui/AGENTS.md @@ -68,6 +68,13 @@ Skip a visual test when the change is behavior-only (state transitions, handler - Update intentional baselines with `pnpm test:visual:docker:update` and commit the resulting `__screenshots__` files with the UI change. - Use the Docker commands when creating or reviewing baselines; host-rendered screenshots are not the source of truth. - If Docker is unavailable, `pnpm test:visual` can help diagnose test code, but do not create or update committed baselines from the host rendering environment. +- If Docker cannot run at all, use the repository's pinned GitHub Actions container as the authoritative baseline generator: + 1. Push the visual test without new or updated host-generated baselines. + 2. Dispatch `.github/workflows/visual-regression.yml` against that branch. The expected missing-baseline failure uploads the `webview-visual-regression` artifact. + 3. Download the artifact and copy each relevant `test-results/**/-actual.png` to the test's `__screenshots__/.png` path. + 4. Commit those container-generated PNGs, push, and rerun the workflow until the visual job passes. +- Fork contributors can use this fallback in their own fork when GitHub Actions is enabled and the workflow exists on the fork's default branch, for example with `gh workflow run visual-regression.yml --repo /Zoo-Code --ref `. The public Playwright image and artifact upload do not require upstream secrets, though the Codecov upload may be unavailable. Fork contributors usually cannot manually dispatch the upstream repository's workflow; a maintainer can run it against an upstream branch when needed. +- The files under `playwright/themes/` are generated from the resolved webview variables exposed by the VS Code version pinned in `apps/vscode-e2e/package.json`; do not edit them manually. On Linux, update them with `xvfb-run -a pnpm --filter @roo-code/vscode-e2e themes:update` and verify them with `xvfb-run -a pnpm --filter @roo-code/vscode-e2e themes:check`. CI runs the same check and fails when the checked-in fixtures drift from the pinned VS Code runtime. - Keep visual tests limited to components supported by the current Playwright harness. Add shared extension state, translation, React Query, or other provider support before snapshotting components that require it. - The current baseline naming assumes a single Chromium project. Include `{projectName}` in `snapshotPathTemplate` before adding another browser project. - Import `test` and `expect` from `webview-ui/playwright/coverage-fixture.ts` (not directly from `@playwright/experimental-ct-react`) so the auto-fixture collects V8 coverage for `monocart-reporter` — that's what produces `coverage-ct/lcov.info` for the Codecov upload. diff --git a/webview-ui/playwright-ct.config.ts b/webview-ui/playwright-ct.config.ts index 3eb0abac7b..4d43820d5a 100644 --- a/webview-ui/playwright-ct.config.ts +++ b/webview-ui/playwright-ct.config.ts @@ -7,6 +7,13 @@ import react from "@vitejs/plugin-react" import tailwindcss from "@tailwindcss/vite" const dirname = path.dirname(fileURLToPath(import.meta.url)) +const rooCodeTypesShim = path.resolve(dirname, "./playwright/roo-code-types.ts") +const rooCodeTypesShimImporters = [ + "/src/shared/modes.ts", + "/webview-ui/src/components/chat/CodeIndexPopover.tsx", + "/webview-ui/src/components/chat/ModeSelector.tsx", + "/webview-ui/src/components/settings/UISettings.tsx", +] const monocartReporter: ReporterDescription = [ "monocart-reporter", @@ -49,6 +56,19 @@ export default defineConfig({ ctTemplateDir: "./playwright", ctViteConfig: { plugins: [ + { + name: "playwright-ct-roo-code-types-shim", + enforce: "pre", + resolveId(source, importer) { + if ( + source === "@roo-code/types" && + importer && + rooCodeTypesShimImporters.some((suffix) => importer.endsWith(suffix)) + ) { + return rooCodeTypesShim + } + }, + }, react({ babel: { plugins: [["babel-plugin-react-compiler", { target: "18" }]], @@ -57,17 +77,28 @@ export default defineConfig({ tailwindcss(), ], resolve: { - alias: { - "@src/i18n/TranslationContext": path.resolve(dirname, "./playwright/TranslationContext.ts"), - "@": path.resolve(dirname, "./src"), - "@src": path.resolve(dirname, "./src"), - "@roo": path.resolve(dirname, "../src/shared"), - "@vscode/webview-ui-toolkit/react": path.resolve( - dirname, - "./src/__mocks__/@vscode/webview-ui-toolkit/react.tsx", - ), - vscode: path.resolve(dirname, "../src/__mocks__/vscode.js"), - }, + alias: [ + { + find: "@/context/ExtensionStateContext", + replacement: path.resolve(dirname, "./playwright/ExtensionStateContext.tsx"), + }, + { + find: "@src/context/ExtensionStateContext", + replacement: path.resolve(dirname, "./playwright/ExtensionStateContext.tsx"), + }, + { + find: "@src/i18n/TranslationContext", + replacement: path.resolve(dirname, "./playwright/TranslationContext.ts"), + }, + { find: "@", replacement: path.resolve(dirname, "./src") }, + { find: "@src", replacement: path.resolve(dirname, "./src") }, + { find: "@roo", replacement: path.resolve(dirname, "../src/shared") }, + { + find: "@vscode/webview-ui-toolkit/react", + replacement: path.resolve(dirname, "./src/__mocks__/@vscode/webview-ui-toolkit/react.tsx"), + }, + { find: "vscode", replacement: path.resolve(dirname, "../src/__mocks__/vscode.js") }, + ], }, define: { "process.platform": JSON.stringify(process.platform), diff --git a/webview-ui/playwright/AppProviders.tsx b/webview-ui/playwright/AppProviders.tsx new file mode 100644 index 0000000000..40f33896dd --- /dev/null +++ b/webview-ui/playwright/AppProviders.tsx @@ -0,0 +1,57 @@ +import React, { useState } from "react" +import { QueryClient, QueryClientProvider } from "@tanstack/react-query" + +import { ExtensionStateContextProvider } from "@/context/ExtensionStateContext" +import { TranslationProvider } from "@/i18n/TranslationContext" +import i18next, { loadTranslations } from "@/i18n/setup" +import { TooltipProvider } from "@/components/ui/tooltip" +import { TranslationContext as PlaywrightTranslationContext } from "@src/i18n/TranslationContext" + +loadTranslations() + +type InitialState = NonNullable["initialState"]> + +interface AppProvidersProps { + children: React.ReactNode + initialState?: InitialState +} + +const defaultInitialState: InitialState = { + language: "en", + clineMessages: [], + taskHistory: [], + shouldShowAnnouncement: false, + telemetrySetting: "enabled", + apiConfiguration: { apiProvider: "anthropic" }, + currentApiConfigName: "Default", + listApiConfigMeta: [{ id: "default", name: "Default", modelId: "claude-sonnet" }], + pinnedApiConfigs: {}, + hasOpenedModeSelector: true, +} + +export function AppProviders({ children, initialState }: AppProvidersProps) { + const [queryClient] = useState( + () => + new QueryClient({ + defaultOptions: { queries: { retry: false } }, + }), + ) + + return ( + + + i18next.t(key, options), i18n: i18next }}> + + +
+
+ {children} +
+ + + + + + ) +} diff --git a/webview-ui/playwright/ExtensionStateContext.tsx b/webview-ui/playwright/ExtensionStateContext.tsx new file mode 100644 index 0000000000..3aadd4bd8d --- /dev/null +++ b/webview-ui/playwright/ExtensionStateContext.tsx @@ -0,0 +1,42 @@ +import React, { createContext, useContext } from "react" + +const noop = () => undefined + +const defaultState = { + language: "en", + clineMessages: [], + taskHistory: [], + filePaths: [], + openedTabs: [], + commands: [], + customModes: [], + customModePrompts: {}, + currentApiConfigName: "Default", + listApiConfigMeta: [{ id: "default", name: "Default", modelId: "claude-sonnet" }], + pinnedApiConfigs: {}, + apiConfiguration: { apiProvider: "anthropic" }, + enterBehavior: "send", + lockApiConfigAcrossModes: false, + telemetrySetting: "enabled", + togglePinnedApiConfig: noop, + setHasOpenedModeSelector: noop, + setApiConfiguration: noop, +} + +export const ExtensionStateContext = createContext>(defaultState) + +export function ExtensionStateContextProvider({ + children, + initialState, +}: { + children: React.ReactNode + initialState?: Record +}) { + return ( + + {children} + + ) +} + +export const useExtensionState = () => useContext(ExtensionStateContext) diff --git a/webview-ui/playwright/contrast.ts b/webview-ui/playwright/contrast.ts new file mode 100644 index 0000000000..faef445c9e --- /dev/null +++ b/webview-ui/playwright/contrast.ts @@ -0,0 +1,200 @@ +import type { Locator } from "@playwright/test" +import { expect } from "@playwright/test" + +export interface RgbaColor { + r: number + g: number + b: number + a: number +} + +export type ContrastProperty = "color" | "background-color" | "border-color" | "outline-color" | "fill" | "stroke" + +interface ContrastOptions { + background?: Locator + foregroundProperty?: ContrastProperty + backgroundProperty?: ContrastProperty + minimum?: number | "text" + label: string +} + +interface ContrastStyles { + foreground: string + foregroundOpacity: number + backgroundLayers: Array<{ color: string; opacity: number }> + fontSize: number + fontWeight: number +} + +export function parseCssColor(value: string): RgbaColor { + const match = value.match(/^rgba?\(\s*([\d.]+)[,\s]+([\d.]+)[,\s]+([\d.]+)(?:\s*[,/]\s*([\d.]+%?))?\s*\)$/i) + if (match) { + const alpha = match[4]?.endsWith("%") ? Number.parseFloat(match[4]) / 100 : Number.parseFloat(match[4] ?? "1") + return { r: Number(match[1]), g: Number(match[2]), b: Number(match[3]), a: alpha } + } + + const srgb = value.match(/^color\(\s*srgb\s+([\d.-]+)\s+([\d.-]+)\s+([\d.-]+)(?:\s*\/\s*([\d.]+%?))?\s*\)$/i) + if (srgb) { + const alpha = srgb[4]?.endsWith("%") ? Number.parseFloat(srgb[4]) / 100 : Number.parseFloat(srgb[4] ?? "1") + return { r: Number(srgb[1]) * 255, g: Number(srgb[2]) * 255, b: Number(srgb[3]) * 255, a: alpha } + } + + const oklab = value.match(/^oklab\(\s*([\d.-]+)\s+([\d.-]+)\s+([\d.-]+)(?:\s*\/\s*([\d.]+%?))?\s*\)$/i) + if (!oklab) throw new Error(`Unsupported CSS color: ${value}`) + const [lightness, axisA, axisB] = oklab.slice(1, 4).map(Number) + const l = (lightness + 0.3963377774 * axisA + 0.2158037573 * axisB) ** 3 + const m = (lightness - 0.1055613458 * axisA - 0.0638541728 * axisB) ** 3 + const s = (lightness - 0.0894841775 * axisA - 1.291485548 * axisB) ** 3 + const linear = [ + 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s, + -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s, + -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s, + ] + const [r, g, b] = linear.map((channel) => { + const value = channel <= 0.0031308 ? 12.92 * channel : 1.055 * channel ** (1 / 2.4) - 0.055 + return Math.min(255, Math.max(0, value * 255)) + }) + const alpha = oklab[4]?.endsWith("%") ? Number.parseFloat(oklab[4]) / 100 : Number.parseFloat(oklab[4] ?? "1") + return { r, g, b, a: alpha } +} + +export function composite(foreground: RgbaColor, background: RgbaColor): RgbaColor { + const alpha = foreground.a + background.a * (1 - foreground.a) + if (alpha === 0) return { r: 0, g: 0, b: 0, a: 0 } + return { + r: (foreground.r * foreground.a + background.r * background.a * (1 - foreground.a)) / alpha, + g: (foreground.g * foreground.a + background.g * background.a * (1 - foreground.a)) / alpha, + b: (foreground.b * foreground.a + background.b * background.a * (1 - foreground.a)) / alpha, + a: alpha, + } +} + +export function contrastRatio(first: RgbaColor, second: RgbaColor): number { + const luminance = ({ r, g, b }: RgbaColor) => { + const channels = [r, g, b].map((channel) => { + const value = channel / 255 + return value <= 0.04045 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4 + }) + return 0.2126 * channels[0] + 0.7152 * channels[1] + 0.0722 * channels[2] + } + const lighter = Math.max(luminance(first), luminance(second)) + const darker = Math.min(luminance(first), luminance(second)) + return (lighter + 0.05) / (darker + 0.05) +} + +export function requiredTextContrast(fontSize: number, fontWeight: number): number { + return fontSize >= 24 || (fontSize >= 56 / 3 && fontWeight >= 700) ? 3 : 4.5 +} + +export async function expectContrast(foreground: Locator, options: ContrastOptions) { + const backgroundToken = options.background ? `contrast-${Date.now()}-${Math.random()}` : null + if (options.background && backgroundToken) { + await options.background.evaluate( + (element, token) => element.setAttribute("data-contrast-background", token), + backgroundToken, + ) + } + let styles: ContrastStyles + try { + styles = await foreground.evaluate( + (element, { backgroundToken, foregroundProperty, backgroundProperty }): ContrastStyles => { + const assertSupported = (current: Element, styles: CSSStyleDeclaration, allowLeafOpacity: boolean) => { + if (styles.backgroundImage !== "none") + throw new Error(`Unsupported background image on ${current.tagName.toLowerCase()}`) + if (styles.filter !== "none") + throw new Error(`Unsupported filter on ${current.tagName.toLowerCase()}`) + if (styles.backdropFilter !== "none") + throw new Error(`Unsupported backdrop filter on ${current.tagName.toLowerCase()}`) + if (styles.mixBlendMode !== "normal" || styles.backgroundBlendMode !== "normal") { + throw new Error(`Unsupported blend mode on ${current.tagName.toLowerCase()}`) + } + if (styles.maskImage !== "none") + throw new Error(`Unsupported mask on ${current.tagName.toLowerCase()}`) + if (!allowLeafOpacity && Number(styles.opacity) !== 1) { + throw new Error(`Unsupported group opacity on ${current.tagName.toLowerCase()}`) + } + } + const styleValue = (styles: CSSStyleDeclaration, property: ContrastProperty) => { + if (property === "fill" || property === "stroke") return styles[property] + return styles.getPropertyValue(property) + } + const foregroundStyles = getComputedStyle(element) + assertSupported( + element, + foregroundStyles, + foregroundStyles.backgroundColor.endsWith(", 0)") || + foregroundStyles.backgroundColor.endsWith("/ 0)"), + ) + let foregroundAncestor = element.parentElement + while (foregroundAncestor) { + assertSupported(foregroundAncestor, getComputedStyle(foregroundAncestor), false) + foregroundAncestor = foregroundAncestor.parentElement + } + const backgroundLayers: Array<{ color: string; opacity: number }> = [] + let current: Element | null = backgroundToken + ? document.querySelector(`[data-contrast-background="${CSS.escape(backgroundToken)}"]`) + : element + let first = true + while (current) { + const styles = getComputedStyle(current) + assertSupported(current, styles, first && current.childElementCount === 0) + const color = first ? styleValue(styles, backgroundProperty) : styles.backgroundColor + const propertyOpacity = + first && backgroundProperty === "fill" + ? Number(styles.fillOpacity) + : first && backgroundProperty === "stroke" + ? Number(styles.strokeOpacity) + : 1 + backgroundLayers.push({ color, opacity: Number(styles.opacity) * propertyOpacity }) + current = current.parentElement + first = false + } + return { + foreground: styleValue(foregroundStyles, foregroundProperty), + foregroundOpacity: + Number(foregroundStyles.opacity) * + (foregroundProperty === "fill" + ? Number(foregroundStyles.fillOpacity) + : foregroundProperty === "stroke" + ? Number(foregroundStyles.strokeOpacity) + : 1), + backgroundLayers, + fontSize: Number.parseFloat(foregroundStyles.fontSize), + fontWeight: Number.parseInt(foregroundStyles.fontWeight, 10) || 400, + } + }, + { + backgroundToken, + foregroundProperty: options.foregroundProperty ?? "color", + backgroundProperty: options.backgroundProperty ?? "background-color", + }, + ) + } finally { + if (options.background && backgroundToken) { + await options.background.evaluate((element) => element.removeAttribute("data-contrast-background")) + } + } + + let effectiveBackground: RgbaColor = { r: 0, g: 0, b: 0, a: 0 } + for (const layer of styles.backgroundLayers.reverse()) { + const color = parseCssColor(layer.color) + effectiveBackground = composite({ ...color, a: color.a * layer.opacity }, effectiveBackground) + } + if (effectiveBackground.a < 0.999) { + throw new Error(`${options.label}: effective background is not opaque`) + } + + const foregroundColor = parseCssColor(styles.foreground) + const effectiveForeground = composite( + { ...foregroundColor, a: foregroundColor.a * styles.foregroundOpacity }, + effectiveBackground, + ) + const ratio = contrastRatio(effectiveForeground, effectiveBackground) + const minimum = + options.minimum === "text" || options.minimum === undefined + ? requiredTextContrast(styles.fontSize, styles.fontWeight) + : options.minimum + const diagnostic = `${options.label}: ${ratio.toFixed(2)}:1 (required ${minimum}:1; foreground ${styles.foreground}; background rgba(${effectiveBackground.r.toFixed(0)}, ${effectiveBackground.g.toFixed(0)}, ${effectiveBackground.b.toFixed(0)}, ${effectiveBackground.a.toFixed(2)}))` + expect(ratio, diagnostic).toBeGreaterThanOrEqual(minimum) + return { ratio, minimum, foreground: effectiveForeground, background: effectiveBackground } +} diff --git a/webview-ui/playwright/index.tsx b/webview-ui/playwright/index.tsx index 3710fe1502..d54a3bc98e 100644 --- a/webview-ui/playwright/index.tsx +++ b/webview-ui/playwright/index.tsx @@ -1,7 +1,10 @@ -import "./vscode-theme-dark.css" import "@vscode/codicons/dist/codicon.css" +import "./themes/vscode-theme-dark.css" +import "./themes/vscode-theme-light.css" +import "./themes/vscode-theme-high-contrast.css" +import "./themes/vscode-theme-high-contrast-light.css" +import "./vscode-theme-base.css" import "../src/index.css" -import "./vscode-theme-light.css" // Components read `window.IMAGES_BASE_URI` at mount time to resolve extension // image assets. Under Playwright CT the extension host isn't present, so seed diff --git a/webview-ui/playwright/roo-code-types.ts b/webview-ui/playwright/roo-code-types.ts new file mode 100644 index 0000000000..d07b4aaddc --- /dev/null +++ b/webview-ui/playwright/roo-code-types.ts @@ -0,0 +1,50 @@ +export { DEFAULT_MODES } from "../../packages/types/src/mode" + +export const DEFAULT_AUTO_CLOSE_ZOO_OPENED_FILES = false +export const DEFAULT_AUTO_CLOSE_ZOO_OPENED_FILES_AFTER_USER_EDITED = false +export const DEFAULT_AUTO_CLOSE_ZOO_OPENED_NEW_FILES = false + +export const CODEBASE_INDEX_DEFAULTS = { + MIN_SEARCH_RESULTS: 10, + MAX_SEARCH_RESULTS: 200, + DEFAULT_SEARCH_RESULTS: 50, + SEARCH_RESULTS_STEP: 10, + MIN_SEARCH_SCORE: 0, + MAX_SEARCH_SCORE: 1, + DEFAULT_SEARCH_MIN_SCORE: 0.4, + SEARCH_SCORE_STEP: 0.05, +} as const + +export const TelemetryEventName = { + MODE_SWITCH: "Mode Switched", + MODE_SELECTOR_OPENED: "Mode Selector Opened", +} as const + +export const OpenAiServiceTier = { + Default: "default", + Flex: "flex", + Priority: "priority", +} as const + +const languages = [ + "ca", + "de", + "en", + "es", + "fr", + "hi", + "id", + "it", + "ja", + "ko", + "nl", + "pl", + "pt-BR", + "ru", + "tr", + "vi", + "zh-CN", + "zh-TW", +] + +export const isLanguage = (value: string) => languages.includes(value) diff --git a/webview-ui/playwright/themes.ts b/webview-ui/playwright/themes.ts new file mode 100644 index 0000000000..65ec5ee384 --- /dev/null +++ b/webview-ui/playwright/themes.ts @@ -0,0 +1,28 @@ +import type { Page } from "@playwright/test" + +export interface VisualTheme { + name: "dark" | "light" | "high-contrast" | "high-contrast-light" + bodyClass: string + themeId: string +} + +export const visualThemes: VisualTheme[] = [ + { name: "dark", bodyClass: "vscode-dark", themeId: "Default Dark Modern" }, + { name: "light", bodyClass: "vscode-light", themeId: "Default Light Modern" }, + { name: "high-contrast", bodyClass: "vscode-high-contrast", themeId: "Default High Contrast" }, + { + name: "high-contrast-light", + bodyClass: "vscode-high-contrast-light", + themeId: "Default High Contrast Light", + }, +] + +export async function applyVisualTheme(page: Page, theme: VisualTheme) { + await page.evaluate(({ bodyClass, themeId }) => { + document.documentElement.className = bodyClass + document.documentElement.removeAttribute("style") + document.body.className = bodyClass + document.body.removeAttribute("style") + document.body.dataset.vscodeThemeId = themeId + }, theme) +} diff --git a/webview-ui/playwright/themes/vscode-theme-dark.css b/webview-ui/playwright/themes/vscode-theme-dark.css new file mode 100644 index 0000000000..285cb2179c --- /dev/null +++ b/webview-ui/playwright/themes/vscode-theme-dark.css @@ -0,0 +1,778 @@ +/* Generated from Default Dark Modern by VS Code 1.100.0. Do not edit manually. */ +.vscode-dark { + color-scheme: dark; + --vscode-actionBar-toggledBackground: #383a49; + --vscode-activityBar-activeBorder: #0078d4; + --vscode-activityBar-background: #181818; + --vscode-activityBar-border: #2b2b2b; + --vscode-activityBar-dropBorder: #d7d7d7; + --vscode-activityBar-foreground: #d7d7d7; + --vscode-activityBar-inactiveForeground: #868686; + --vscode-activityBarBadge-background: #0078d4; + --vscode-activityBarBadge-foreground: #ffffff; + --vscode-activityBarTop-activeBorder: #e7e7e7; + --vscode-activityBarTop-dropBorder: #e7e7e7; + --vscode-activityBarTop-foreground: #e7e7e7; + --vscode-activityBarTop-inactiveForeground: rgba(231, 231, 231, 0.6); + --vscode-activityErrorBadge-background: #f14c4c; + --vscode-activityErrorBadge-foreground: #000000; + --vscode-activityWarningBadge-background: #cca700; + --vscode-activityWarningBadge-foreground: #000000; + --vscode-badge-background: #616161; + --vscode-badge-foreground: #f8f8f8; + --vscode-banner-background: #04395e; + --vscode-banner-foreground: #ffffff; + --vscode-banner-iconForeground: #3794ff; + --vscode-breadcrumb-activeSelectionForeground: #e0e0e0; + --vscode-breadcrumb-background: #1f1f1f; + --vscode-breadcrumb-focusForeground: #e0e0e0; + --vscode-breadcrumb-foreground: rgba(204, 204, 204, 0.8); + --vscode-breadcrumbPicker-background: #202020; + --vscode-button-background: #0078d4; + --vscode-button-border: rgba(255, 255, 255, 0.07); + --vscode-button-foreground: #ffffff; + --vscode-button-hoverBackground: #026ec1; + --vscode-button-secondaryBackground: #313131; + --vscode-button-secondaryForeground: #cccccc; + --vscode-button-secondaryHoverBackground: #3c3c3c; + --vscode-button-separator: rgba(255, 255, 255, 0.4); + --vscode-chart-axis: rgba(191, 191, 191, 0.4); + --vscode-chart-guide: rgba(191, 191, 191, 0.2); + --vscode-chart-line: #236b8e; + --vscode-charts-blue: #3794ff; + --vscode-charts-foreground: #cccccc; + --vscode-charts-green: #89d185; + --vscode-charts-lines: rgba(204, 204, 204, 0.5); + --vscode-charts-orange: #d18616; + --vscode-charts-purple: #b180d7; + --vscode-charts-red: #f14c4c; + --vscode-charts-yellow: #cca700; + --vscode-chat-avatarBackground: #1f1f1f; + --vscode-chat-avatarForeground: #cccccc; + --vscode-chat-editedFileForeground: #e2c08d; + --vscode-chat-requestBackground: rgba(31, 31, 31, 0.62); + --vscode-chat-requestBorder: rgba(255, 255, 255, 0.1); + --vscode-chat-slashCommandBackground: #34414b; + --vscode-chat-slashCommandForeground: #40a6ff; + --vscode-checkbox-background: #313131; + --vscode-checkbox-border: #3c3c3c; + --vscode-checkbox-disabled.background: #646464; + --vscode-checkbox-disabled.foreground: #989898; + --vscode-checkbox-foreground: #cccccc; + --vscode-checkbox-selectBackground: #202020; + --vscode-checkbox-selectBorder: #cccccc; + --vscode-commandCenter-activeBackground: rgba(255, 255, 255, 0.08); + --vscode-commandCenter-activeBorder: rgba(204, 204, 204, 0.3); + --vscode-commandCenter-activeForeground: #cccccc; + --vscode-commandCenter-background: rgba(255, 255, 255, 0.05); + --vscode-commandCenter-border: rgba(204, 204, 204, 0.2); + --vscode-commandCenter-debuggingBackground: rgba(0, 120, 212, 0.26); + --vscode-commandCenter-foreground: #cccccc; + --vscode-commandCenter-inactiveBorder: rgba(157, 157, 157, 0.25); + --vscode-commandCenter-inactiveForeground: #9d9d9d; + --vscode-commentsView-resolvedIcon: rgba(204, 204, 204, 0.5); + --vscode-commentsView-unresolvedIcon: #0078d4; + --vscode-debugConsole-errorForeground: #f85149; + --vscode-debugConsole-infoForeground: #3794ff; + --vscode-debugConsole-sourceForeground: #cccccc; + --vscode-debugConsole-warningForeground: #cca700; + --vscode-debugConsoleInputIcon-foreground: #cccccc; + --vscode-debugExceptionWidget-background: #420b0d; + --vscode-debugExceptionWidget-border: #a31515; + --vscode-debugIcon-breakpointCurrentStackframeForeground: #ffcc00; + --vscode-debugIcon-breakpointDisabledForeground: #848484; + --vscode-debugIcon-breakpointForeground: #e51400; + --vscode-debugIcon-breakpointStackframeForeground: #89d185; + --vscode-debugIcon-breakpointUnverifiedForeground: #848484; + --vscode-debugIcon-continueForeground: #75beff; + --vscode-debugIcon-disconnectForeground: #f48771; + --vscode-debugIcon-pauseForeground: #75beff; + --vscode-debugIcon-restartForeground: #89d185; + --vscode-debugIcon-startForeground: #89d185; + --vscode-debugIcon-stepBackForeground: #75beff; + --vscode-debugIcon-stepIntoForeground: #75beff; + --vscode-debugIcon-stepOutForeground: #75beff; + --vscode-debugIcon-stepOverForeground: #75beff; + --vscode-debugIcon-stopForeground: #f48771; + --vscode-debugTokenExpression-boolean: #4e94ce; + --vscode-debugTokenExpression-error: #f48771; + --vscode-debugTokenExpression-name: #c586c0; + --vscode-debugTokenExpression-number: #b5cea8; + --vscode-debugTokenExpression-string: #ce9178; + --vscode-debugTokenExpression-type: #4a90e2; + --vscode-debugTokenExpression-value: rgba(204, 204, 204, 0.6); + --vscode-debugToolBar-background: #181818; + --vscode-debugView-exceptionLabelBackground: #6c2022; + --vscode-debugView-exceptionLabelForeground: #cccccc; + --vscode-debugView-stateLabelBackground: rgba(136, 136, 136, 0.27); + --vscode-debugView-stateLabelForeground: #cccccc; + --vscode-debugView-valueChangedHighlight: #569cd6; + --vscode-descriptionForeground: #9d9d9d; + --vscode-diffEditor-diagonalFill: rgba(204, 204, 204, 0.2); + --vscode-diffEditor-insertedLineBackground: rgba(155, 185, 85, 0.2); + --vscode-diffEditor-insertedTextBackground: rgba(156, 204, 44, 0.2); + --vscode-diffEditor-move.border: rgba(139, 139, 139, 0.61); + --vscode-diffEditor-moveActive.border: #ffa500; + --vscode-diffEditor-removedLineBackground: rgba(255, 0, 0, 0.2); + --vscode-diffEditor-removedTextBackground: rgba(255, 0, 0, 0.2); + --vscode-diffEditor-unchangedCodeBackground: rgba(116, 116, 116, 0.16); + --vscode-diffEditor-unchangedRegionBackground: #181818; + --vscode-diffEditor-unchangedRegionForeground: #cccccc; + --vscode-diffEditor-unchangedRegionShadow: #000000; + --vscode-disabledForeground: rgba(204, 204, 204, 0.5); + --vscode-dropdown-background: #313131; + --vscode-dropdown-border: #3c3c3c; + --vscode-dropdown-foreground: #cccccc; + --vscode-dropdown-listBackground: #1f1f1f; + --vscode-editor-background: #1f1f1f; + --vscode-editor-compositionBorder: #ffffff; + --vscode-editor-findMatchBackground: #9e6a03; + --vscode-editor-findMatchHighlightBackground: rgba(234, 92, 0, 0.33); + --vscode-editor-findRangeHighlightBackground: rgba(58, 61, 65, 0.4); + --vscode-editor-focusedStackFrameHighlightBackground: rgba(122, 189, 122, 0.3); + --vscode-editor-foldBackground: rgba(38, 79, 120, 0.3); + --vscode-editor-foldPlaceholderForeground: #808080; + --vscode-editor-font-size: 14px; + --vscode-editor-font-weight: normal; + --vscode-editor-foreground: #cccccc; + --vscode-editor-hoverHighlightBackground: rgba(38, 79, 120, 0.25); + --vscode-editor-inactiveSelectionBackground: #3a3d41; + --vscode-editor-inlineValuesBackground: rgba(255, 200, 0, 0.2); + --vscode-editor-inlineValuesForeground: rgba(255, 255, 255, 0.5); + --vscode-editor-lineHighlightBorder: #282828; + --vscode-editor-linkedEditingBackground: rgba(255, 0, 0, 0.3); + --vscode-editor-placeholder.foreground: rgba(255, 255, 255, 0.34); + --vscode-editor-rangeHighlightBackground: rgba(255, 255, 255, 0.04); + --vscode-editor-selectionBackground: #264f78; + --vscode-editor-selectionHighlightBackground: rgba(173, 214, 255, 0.15); + --vscode-editor-snippetFinalTabstopHighlightBorder: #525252; + --vscode-editor-snippetTabstopHighlightBackground: rgba(124, 124, 124, 0.3); + --vscode-editor-stackFrameHighlightBackground: rgba(255, 255, 0, 0.2); + --vscode-editor-symbolHighlightBackground: rgba(234, 92, 0, 0.33); + --vscode-editor-wordHighlightBackground: rgba(87, 87, 87, 0.72); + --vscode-editor-wordHighlightStrongBackground: rgba(0, 73, 114, 0.72); + --vscode-editor-wordHighlightTextBackground: rgba(87, 87, 87, 0.72); + --vscode-editorActionList-background: #202020; + --vscode-editorActionList-focusBackground: #04395e; + --vscode-editorActionList-focusForeground: #ffffff; + --vscode-editorActionList-foreground: #cccccc; + --vscode-editorActiveLineNumber-foreground: #c6c6c6; + --vscode-editorBracketHighlight-foreground1: #ffd700; + --vscode-editorBracketHighlight-foreground2: #da70d6; + --vscode-editorBracketHighlight-foreground3: #179fff; + --vscode-editorBracketHighlight-foreground4: rgba(0, 0, 0, 0); + --vscode-editorBracketHighlight-foreground5: rgba(0, 0, 0, 0); + --vscode-editorBracketHighlight-foreground6: rgba(0, 0, 0, 0); + --vscode-editorBracketHighlight-unexpectedBracket.foreground: rgba(255, 18, 18, 0.8); + --vscode-editorBracketMatch-background: rgba(0, 100, 0, 0.1); + --vscode-editorBracketMatch-border: #888888; + --vscode-editorBracketPairGuide-activeBackground1: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-activeBackground2: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-activeBackground3: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-activeBackground4: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-activeBackground5: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-activeBackground6: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background1: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background2: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background3: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background4: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background5: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background6: rgba(0, 0, 0, 0); + --vscode-editorCodeLens-foreground: #999999; + --vscode-editorCommentsWidget-rangeActiveBackground: rgba(0, 120, 212, 0.1); + --vscode-editorCommentsWidget-rangeBackground: rgba(0, 120, 212, 0.1); + --vscode-editorCommentsWidget-replyInputBackground: #252526; + --vscode-editorCommentsWidget-resolvedBorder: rgba(204, 204, 204, 0.5); + --vscode-editorCommentsWidget-unresolvedBorder: #0078d4; + --vscode-editorCursor-foreground: #aeafad; + --vscode-editorError-foreground: #f14c4c; + --vscode-editorGhostText-foreground: rgba(255, 255, 255, 0.34); + --vscode-editorGroup-border: rgba(255, 255, 255, 0.09); + --vscode-editorGroup-dropBackground: rgba(83, 89, 93, 0.5); + --vscode-editorGroup-dropIntoPromptBackground: #202020; + --vscode-editorGroup-dropIntoPromptForeground: #cccccc; + --vscode-editorGroupHeader-noTabsBackground: #1f1f1f; + --vscode-editorGroupHeader-tabsBackground: #181818; + --vscode-editorGroupHeader-tabsBorder: #2b2b2b; + --vscode-editorGutter-addedBackground: #2ea043; + --vscode-editorGutter-addedSecondaryBackground: #175021; + --vscode-editorGutter-background: #1f1f1f; + --vscode-editorGutter-commentGlyphForeground: #cccccc; + --vscode-editorGutter-commentRangeForeground: #37373d; + --vscode-editorGutter-commentUnresolvedGlyphForeground: #cccccc; + --vscode-editorGutter-deletedBackground: #f85149; + --vscode-editorGutter-deletedSecondaryBackground: #b91007; + --vscode-editorGutter-foldingControlForeground: #cccccc; + --vscode-editorGutter-itemBackground: #37373d; + --vscode-editorGutter-itemGlyphForeground: #cccccc; + --vscode-editorGutter-modifiedBackground: #0078d4; + --vscode-editorGutter-modifiedSecondaryBackground: #003c6a; + --vscode-editorHint-foreground: rgba(238, 238, 238, 0.7); + --vscode-editorHoverWidget-background: #202020; + --vscode-editorHoverWidget-border: #454545; + --vscode-editorHoverWidget-foreground: #cccccc; + --vscode-editorHoverWidget-highlightForeground: #2aaaff; + --vscode-editorHoverWidget-statusBarBackground: #262626; + --vscode-editorIndentGuide-activeBackground: rgba(227, 228, 226, 0.16); + --vscode-editorIndentGuide-activeBackground1: #707070; + --vscode-editorIndentGuide-activeBackground2: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-activeBackground3: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-activeBackground4: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-activeBackground5: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-activeBackground6: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-background: rgba(227, 228, 226, 0.16); + --vscode-editorIndentGuide-background1: #404040; + --vscode-editorIndentGuide-background2: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-background3: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-background4: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-background5: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-background6: rgba(0, 0, 0, 0); + --vscode-editorInfo-foreground: #3794ff; + --vscode-editorInlayHint-background: rgba(97, 97, 97, 0.1); + --vscode-editorInlayHint-foreground: #969696; + --vscode-editorInlayHint-parameterBackground: rgba(97, 97, 97, 0.1); + --vscode-editorInlayHint-parameterForeground: #969696; + --vscode-editorInlayHint-typeBackground: rgba(97, 97, 97, 0.1); + --vscode-editorInlayHint-typeForeground: #969696; + --vscode-editorLightBulb-foreground: #ffcc00; + --vscode-editorLightBulbAi-foreground: #ffcc00; + --vscode-editorLightBulbAutoFix-foreground: #75beff; + --vscode-editorLineNumber-activeForeground: #cccccc; + --vscode-editorLineNumber-foreground: #6e7681; + --vscode-editorLink-activeForeground: #4e94ce; + --vscode-editorMarkerNavigation-background: #1f1f1f; + --vscode-editorMarkerNavigationError-background: #f14c4c; + --vscode-editorMarkerNavigationError-headerBackground: rgba(241, 76, 76, 0.1); + --vscode-editorMarkerNavigationInfo-background: #3794ff; + --vscode-editorMarkerNavigationInfo-headerBackground: rgba(55, 148, 255, 0.1); + --vscode-editorMarkerNavigationWarning-background: #cca700; + --vscode-editorMarkerNavigationWarning-headerBackground: rgba(204, 167, 0, 0.1); + --vscode-editorMinimap-inlineChatInserted: rgba(156, 204, 44, 0.12); + --vscode-editorMultiCursor-primary.foreground: #aeafad; + --vscode-editorMultiCursor-secondary.foreground: #aeafad; + --vscode-editorOverviewRuler-addedForeground: rgba(46, 160, 67, 0.6); + --vscode-editorOverviewRuler-border: #010409; + --vscode-editorOverviewRuler-bracketMatchForeground: #a0a0a0; + --vscode-editorOverviewRuler-commentForeground: #37373d; + --vscode-editorOverviewRuler-commentUnresolvedForeground: #37373d; + --vscode-editorOverviewRuler-commonContentForeground: rgba(96, 96, 96, 0.4); + --vscode-editorOverviewRuler-currentContentForeground: rgba(64, 200, 174, 0.5); + --vscode-editorOverviewRuler-deletedForeground: rgba(248, 81, 73, 0.6); + --vscode-editorOverviewRuler-errorForeground: rgba(255, 18, 18, 0.7); + --vscode-editorOverviewRuler-findMatchForeground: rgba(209, 134, 22, 0.49); + --vscode-editorOverviewRuler-incomingContentForeground: rgba(64, 166, 255, 0.5); + --vscode-editorOverviewRuler-infoForeground: #3794ff; + --vscode-editorOverviewRuler-inlineChatInserted: rgba(156, 204, 44, 0.12); + --vscode-editorOverviewRuler-inlineChatRemoved: rgba(255, 0, 0, 0.12); + --vscode-editorOverviewRuler-modifiedForeground: rgba(0, 120, 212, 0.6); + --vscode-editorOverviewRuler-rangeHighlightForeground: rgba(0, 122, 204, 0.6); + --vscode-editorOverviewRuler-selectionHighlightForeground: rgba(160, 160, 160, 0.8); + --vscode-editorOverviewRuler-warningForeground: #cca700; + --vscode-editorOverviewRuler-wordHighlightForeground: rgba(160, 160, 160, 0.8); + --vscode-editorOverviewRuler-wordHighlightStrongForeground: rgba(192, 160, 192, 0.8); + --vscode-editorOverviewRuler-wordHighlightTextForeground: rgba(160, 160, 160, 0.8); + --vscode-editorPane-background: #1f1f1f; + --vscode-editorRuler-foreground: #5a5a5a; + --vscode-editorStickyScroll-background: #1f1f1f; + --vscode-editorStickyScroll-shadow: #000000; + --vscode-editorStickyScrollHover-background: #2a2d2e; + --vscode-editorSuggestWidget-background: #202020; + --vscode-editorSuggestWidget-border: #454545; + --vscode-editorSuggestWidget-focusHighlightForeground: #2aaaff; + --vscode-editorSuggestWidget-foreground: #cccccc; + --vscode-editorSuggestWidget-highlightForeground: #2aaaff; + --vscode-editorSuggestWidget-selectedBackground: #04395e; + --vscode-editorSuggestWidget-selectedForeground: #ffffff; + --vscode-editorSuggestWidget-selectedIconForeground: #ffffff; + --vscode-editorSuggestWidgetStatus-foreground: rgba(204, 204, 204, 0.5); + --vscode-editorUnicodeHighlight-border: #cca700; + --vscode-editorUnnecessaryCode-opacity: rgba(0, 0, 0, 0.67); + --vscode-editorWarning-foreground: #cca700; + --vscode-editorWatermark-foreground: rgba(204, 204, 204, 0.6); + --vscode-editorWhitespace-foreground: rgba(227, 228, 226, 0.16); + --vscode-editorWidget-background: #202020; + --vscode-editorWidget-border: #454545; + --vscode-editorWidget-foreground: #cccccc; + --vscode-errorForeground: #f85149; + --vscode-extensionBadge-remoteBackground: #0078d4; + --vscode-extensionBadge-remoteForeground: #ffffff; + --vscode-extensionButton-background: #0078d4; + --vscode-extensionButton-foreground: #ffffff; + --vscode-extensionButton-hoverBackground: #026ec1; + --vscode-extensionButton-prominentBackground: #0078d4; + --vscode-extensionButton-prominentForeground: #ffffff; + --vscode-extensionButton-prominentHoverBackground: #026ec1; + --vscode-extensionButton-separator: rgba(255, 255, 255, 0.4); + --vscode-extensionIcon-preReleaseForeground: #1d9271; + --vscode-extensionIcon-privateForeground: rgba(255, 255, 255, 0.38); + --vscode-extensionIcon-sponsorForeground: #d758b3; + --vscode-extensionIcon-starForeground: #ff8e00; + --vscode-extensionIcon-verifiedForeground: #4daafc; + --vscode-focusBorder: #0078d4; + --vscode-font-size: 13px; + --vscode-font-weight: normal; + --vscode-foreground: #cccccc; + --vscode-gauge-background: #007acc; + --vscode-gauge-errorBackground: #be1100; + --vscode-gauge-errorForeground: rgba(190, 17, 0, 0.3); + --vscode-gauge-foreground: rgba(0, 122, 204, 0.3); + --vscode-gauge-warningBackground: #b89500; + --vscode-gauge-warningForeground: rgba(184, 149, 0, 0.3); + --vscode-git-blame.editorDecorationForeground: #969696; + --vscode-gitDecoration-addedResourceForeground: #81b88b; + --vscode-gitDecoration-conflictingResourceForeground: #e4676b; + --vscode-gitDecoration-deletedResourceForeground: #c74e39; + --vscode-gitDecoration-ignoredResourceForeground: #8c8c8c; + --vscode-gitDecoration-modifiedResourceForeground: #e2c08d; + --vscode-gitDecoration-renamedResourceForeground: #73c991; + --vscode-gitDecoration-stageDeletedResourceForeground: #c74e39; + --vscode-gitDecoration-stageModifiedResourceForeground: #e2c08d; + --vscode-gitDecoration-submoduleResourceForeground: #8db9e2; + --vscode-gitDecoration-untrackedResourceForeground: #73c991; + --vscode-icon-foreground: #cccccc; + --vscode-inlineChat-background: #202020; + --vscode-inlineChat-border: #454545; + --vscode-inlineChat-foreground: #cccccc; + --vscode-inlineChat-shadow: rgba(0, 0, 0, 0.36); + --vscode-inlineChatDiff-inserted: rgba(156, 204, 44, 0.1); + --vscode-inlineChatDiff-removed: rgba(255, 0, 0, 0.1); + --vscode-inlineChatInput-background: #313131; + --vscode-inlineChatInput-border: #454545; + --vscode-inlineChatInput-focusBorder: #0078d4; + --vscode-inlineChatInput-placeholderForeground: #989898; + --vscode-inlineEdit-gutterIndicator.background: rgba(24, 24, 24, 0.5); + --vscode-inlineEdit-gutterIndicator.primaryBackground: rgba(0, 120, 212, 0.4); + --vscode-inlineEdit-gutterIndicator.primaryBorder: #0078d4; + --vscode-inlineEdit-gutterIndicator.primaryForeground: #ffffff; + --vscode-inlineEdit-gutterIndicator.secondaryBackground: #313131; + --vscode-inlineEdit-gutterIndicator.secondaryBorder: #313131; + --vscode-inlineEdit-gutterIndicator.secondaryForeground: #cccccc; + --vscode-inlineEdit-gutterIndicator.successfulBackground: #0078d4; + --vscode-inlineEdit-gutterIndicator.successfulBorder: #0078d4; + --vscode-inlineEdit-gutterIndicator.successfulForeground: #ffffff; + --vscode-inlineEdit-modifiedBackground: rgba(156, 204, 44, 0.06); + --vscode-inlineEdit-modifiedBorder: rgba(156, 204, 44, 0.2); + --vscode-inlineEdit-modifiedChangedLineBackground: rgba(155, 185, 85, 0.14); + --vscode-inlineEdit-modifiedChangedTextBackground: rgba(156, 204, 44, 0.14); + --vscode-inlineEdit-originalBackground: rgba(255, 0, 0, 0.04); + --vscode-inlineEdit-originalBorder: rgba(255, 0, 0, 0.2); + --vscode-inlineEdit-originalChangedLineBackground: rgba(255, 0, 0, 0.16); + --vscode-inlineEdit-originalChangedTextBackground: rgba(255, 0, 0, 0.16); + --vscode-inlineEdit-tabWillAcceptModifiedBorder: rgba(156, 204, 44, 0.2); + --vscode-inlineEdit-tabWillAcceptOriginalBorder: rgba(255, 0, 0, 0.2); + --vscode-input-background: #313131; + --vscode-input-border: #3c3c3c; + --vscode-input-foreground: #cccccc; + --vscode-input-placeholderForeground: #989898; + --vscode-inputOption-activeBackground: rgba(36, 137, 219, 0.51); + --vscode-inputOption-activeBorder: #2488db; + --vscode-inputOption-activeForeground: #ffffff; + --vscode-inputOption-hoverBackground: rgba(90, 93, 94, 0.5); + --vscode-inputValidation-errorBackground: #5a1d1d; + --vscode-inputValidation-errorBorder: #be1100; + --vscode-inputValidation-infoBackground: #063b49; + --vscode-inputValidation-infoBorder: #007acc; + --vscode-inputValidation-warningBackground: #352a05; + --vscode-inputValidation-warningBorder: #b89500; + --vscode-interactive-activeCodeBorder: #007acc; + --vscode-interactive-inactiveCodeBorder: #37373d; + --vscode-keybindingLabel-background: rgba(128, 128, 128, 0.17); + --vscode-keybindingLabel-border: rgba(51, 51, 51, 0.6); + --vscode-keybindingLabel-bottomBorder: rgba(68, 68, 68, 0.6); + --vscode-keybindingLabel-foreground: #cccccc; + --vscode-keybindingTable-headerBackground: rgba(204, 204, 204, 0.04); + --vscode-keybindingTable-rowsBackground: rgba(204, 204, 204, 0.04); + --vscode-list-activeSelectionBackground: #04395e; + --vscode-list-activeSelectionForeground: #ffffff; + --vscode-list-activeSelectionIconForeground: #ffffff; + --vscode-list-deemphasizedForeground: #8c8c8c; + --vscode-list-dropBackground: #383b3d; + --vscode-list-dropBetweenBackground: #cccccc; + --vscode-list-errorForeground: #f88070; + --vscode-list-filterMatchBackground: rgba(234, 92, 0, 0.33); + --vscode-list-focusHighlightForeground: #2aaaff; + --vscode-list-focusOutline: #0078d4; + --vscode-list-highlightForeground: #2aaaff; + --vscode-list-hoverBackground: #2a2d2e; + --vscode-list-inactiveSelectionBackground: #37373d; + --vscode-list-invalidItemForeground: #b89500; + --vscode-list-warningForeground: #cca700; + --vscode-listFilterWidget-background: #202020; + --vscode-listFilterWidget-noMatchesOutline: #be1100; + --vscode-listFilterWidget-outline: rgba(0, 0, 0, 0); + --vscode-listFilterWidget-shadow: rgba(0, 0, 0, 0.36); + --vscode-menu-background: #1f1f1f; + --vscode-menu-border: #454545; + --vscode-menu-foreground: #cccccc; + --vscode-menu-selectionBackground: #0078d4; + --vscode-menu-selectionForeground: #ffffff; + --vscode-menu-separatorBackground: #454545; + --vscode-menubar-selectionBackground: rgba(90, 93, 94, 0.31); + --vscode-menubar-selectionForeground: #cccccc; + --vscode-merge-commonContentBackground: rgba(96, 96, 96, 0.16); + --vscode-merge-commonHeaderBackground: rgba(96, 96, 96, 0.4); + --vscode-merge-currentContentBackground: rgba(64, 200, 174, 0.2); + --vscode-merge-currentHeaderBackground: rgba(64, 200, 174, 0.5); + --vscode-merge-incomingContentBackground: rgba(64, 166, 255, 0.2); + --vscode-merge-incomingHeaderBackground: rgba(64, 166, 255, 0.5); + --vscode-mergeEditor-change.background: rgba(155, 185, 85, 0.2); + --vscode-mergeEditor-change.word.background: rgba(156, 204, 44, 0.2); + --vscode-mergeEditor-changeBase.background: #4b1818; + --vscode-mergeEditor-changeBase.word.background: #6f1313; + --vscode-mergeEditor-conflict.handled.minimapOverViewRuler: rgba(173, 172, 168, 0.93); + --vscode-mergeEditor-conflict.handledFocused.border: rgba(193, 193, 193, 0.8); + --vscode-mergeEditor-conflict.handledUnfocused.border: rgba(134, 134, 134, 0.29); + --vscode-mergeEditor-conflict.input1.background: rgba(64, 200, 174, 0.2); + --vscode-mergeEditor-conflict.input2.background: rgba(64, 166, 255, 0.2); + --vscode-mergeEditor-conflict.unhandled.minimapOverViewRuler: #fcba03; + --vscode-mergeEditor-conflict.unhandledFocused.border: #ffa600; + --vscode-mergeEditor-conflict.unhandledUnfocused.border: rgba(255, 166, 0, 0.48); + --vscode-mergeEditor-conflictingLines.background: rgba(255, 234, 0, 0.28); + --vscode-minimap-chatEditHighlight: rgba(31, 31, 31, 0.6); + --vscode-minimap-errorHighlight: rgba(255, 18, 18, 0.7); + --vscode-minimap-findMatchHighlight: #d18616; + --vscode-minimap-foregroundOpacity: #000000; + --vscode-minimap-infoHighlight: #3794ff; + --vscode-minimap-selectionHighlight: #264f78; + --vscode-minimap-selectionOccurrenceHighlight: #676767; + --vscode-minimap-warningHighlight: #cca700; + --vscode-minimapGutter-addedBackground: #2ea043; + --vscode-minimapGutter-deletedBackground: #f85149; + --vscode-minimapGutter-modifiedBackground: #0078d4; + --vscode-minimapSlider-activeBackground: rgba(191, 191, 191, 0.2); + --vscode-minimapSlider-background: rgba(121, 121, 121, 0.2); + --vscode-minimapSlider-hoverBackground: rgba(100, 100, 100, 0.35); + --vscode-multiDiffEditor-background: #1f1f1f; + --vscode-multiDiffEditor-border: #2b2b2b; + --vscode-multiDiffEditor-headerBackground: #262626; + --vscode-notebook-cellBorderColor: #37373d; + --vscode-notebook-cellEditorBackground: #181818; + --vscode-notebook-cellInsertionIndicator: #0078d4; + --vscode-notebook-cellStatusBarItemHoverBackground: rgba(255, 255, 255, 0.15); + --vscode-notebook-cellToolbarSeparator: rgba(128, 128, 128, 0.35); + --vscode-notebook-editorBackground: #1f1f1f; + --vscode-notebook-focusedCellBorder: #0078d4; + --vscode-notebook-focusedEditorBorder: #0078d4; + --vscode-notebook-inactiveFocusedCellBorder: #37373d; + --vscode-notebook-selectedCellBackground: #37373d; + --vscode-notebook-selectedCellBorder: #37373d; + --vscode-notebook-symbolHighlightBackground: rgba(255, 255, 255, 0.04); + --vscode-notebookEditorOverviewRuler-runningCellForeground: #89d185; + --vscode-notebookScrollbarSlider-activeBackground: rgba(191, 191, 191, 0.4); + --vscode-notebookScrollbarSlider-background: rgba(121, 121, 121, 0.4); + --vscode-notebookScrollbarSlider-hoverBackground: rgba(100, 100, 100, 0.7); + --vscode-notebookStatusErrorIcon-foreground: #f85149; + --vscode-notebookStatusRunningIcon-foreground: #cccccc; + --vscode-notebookStatusSuccessIcon-foreground: #89d185; + --vscode-notificationCenter-border: #313131; + --vscode-notificationCenterHeader-background: #1f1f1f; + --vscode-notificationCenterHeader-foreground: #cccccc; + --vscode-notificationLink-foreground: #4daafc; + --vscode-notificationToast-border: #313131; + --vscode-notifications-background: #1f1f1f; + --vscode-notifications-border: #2b2b2b; + --vscode-notifications-foreground: #cccccc; + --vscode-notificationsErrorIcon-foreground: #f14c4c; + --vscode-notificationsInfoIcon-foreground: #3794ff; + --vscode-notificationsWarningIcon-foreground: #cca700; + --vscode-panel-background: #181818; + --vscode-panel-border: #2b2b2b; + --vscode-panel-dropBorder: #cccccc; + --vscode-panelInput-border: #2b2b2b; + --vscode-panelSection-border: #2b2b2b; + --vscode-panelSection-dropBackground: rgba(83, 89, 93, 0.5); + --vscode-panelSectionHeader-background: rgba(128, 128, 128, 0.2); + --vscode-panelStickyScroll-background: #181818; + --vscode-panelStickyScroll-shadow: #000000; + --vscode-panelTitle-activeBorder: #0078d4; + --vscode-panelTitle-activeForeground: #cccccc; + --vscode-panelTitle-inactiveForeground: #9d9d9d; + --vscode-panelTitleBadge-background: #0078d4; + --vscode-panelTitleBadge-foreground: #ffffff; + --vscode-peekView-border: #3794ff; + --vscode-peekViewEditor-background: #1f1f1f; + --vscode-peekViewEditor-matchHighlightBackground: rgba(187, 128, 9, 0.4); + --vscode-peekViewEditorGutter-background: #1f1f1f; + --vscode-peekViewEditorStickyScroll-background: #1f1f1f; + --vscode-peekViewResult-background: #1f1f1f; + --vscode-peekViewResult-fileForeground: #ffffff; + --vscode-peekViewResult-lineForeground: #bbbbbb; + --vscode-peekViewResult-matchHighlightBackground: rgba(187, 128, 9, 0.4); + --vscode-peekViewResult-selectionBackground: rgba(51, 153, 255, 0.2); + --vscode-peekViewResult-selectionForeground: #ffffff; + --vscode-peekViewTitle-background: #252526; + --vscode-peekViewTitleDescription-foreground: rgba(204, 204, 204, 0.7); + --vscode-peekViewTitleLabel-foreground: #ffffff; + --vscode-pickerGroup-border: #3c3c3c; + --vscode-pickerGroup-foreground: #3794ff; + --vscode-ports-iconRunningProcessForeground: #369432; + --vscode-problemsErrorIcon-foreground: #f14c4c; + --vscode-problemsInfoIcon-foreground: #3794ff; + --vscode-problemsWarningIcon-foreground: #cca700; + --vscode-profileBadge-background: #4d4d4d; + --vscode-profileBadge-foreground: #ffffff; + --vscode-profiles-sashBorder: #2b2b2b; + --vscode-progressBar-background: #0078d4; + --vscode-prompt-frontMatter.background: #191919; + --vscode-prompt-frontMatter.inactiveBackground: #1c1c1c; + --vscode-quickInput-background: #222222; + --vscode-quickInput-foreground: #cccccc; + --vscode-quickInputList-focusBackground: #04395e; + --vscode-quickInputList-focusForeground: #ffffff; + --vscode-quickInputList-focusIconForeground: #ffffff; + --vscode-quickInputTitle-background: rgba(255, 255, 255, 0.1); + --vscode-radio-activeBackground: rgba(36, 137, 219, 0.51); + --vscode-radio-activeBorder: #2488db; + --vscode-radio-activeForeground: #ffffff; + --vscode-radio-inactiveBorder: rgba(255, 255, 255, 0.2); + --vscode-radio-inactiveHoverBackground: rgba(90, 93, 94, 0.5); + --vscode-sash-hoverBorder: #0078d4; + --vscode-scmGraph-foreground1: #ffb000; + --vscode-scmGraph-foreground2: #dc267f; + --vscode-scmGraph-foreground3: #994f00; + --vscode-scmGraph-foreground4: #40b0a6; + --vscode-scmGraph-foreground5: #b66dff; + --vscode-scmGraph-historyItemBaseRefColor: #ea5c00; + --vscode-scmGraph-historyItemHoverAdditionsForeground: #81b88b; + --vscode-scmGraph-historyItemHoverDefaultLabelBackground: #616161; + --vscode-scmGraph-historyItemHoverDefaultLabelForeground: #cccccc; + --vscode-scmGraph-historyItemHoverDeletionsForeground: #c74e39; + --vscode-scmGraph-historyItemHoverLabelForeground: #ffffff; + --vscode-scmGraph-historyItemRefColor: #3794ff; + --vscode-scmGraph-historyItemRemoteRefColor: #b180d7; + --vscode-scrollbar-shadow: #000000; + --vscode-scrollbarSlider-activeBackground: rgba(191, 191, 191, 0.4); + --vscode-scrollbarSlider-background: rgba(121, 121, 121, 0.4); + --vscode-scrollbarSlider-hoverBackground: rgba(100, 100, 100, 0.7); + --vscode-search-resultsInfoForeground: rgba(204, 204, 204, 0.65); + --vscode-searchEditor-findMatchBackground: rgba(234, 92, 0, 0.22); + --vscode-searchEditor-textInputBorder: #3c3c3c; + --vscode-settings-checkboxBackground: #313131; + --vscode-settings-checkboxBorder: #3c3c3c; + --vscode-settings-checkboxForeground: #cccccc; + --vscode-settings-dropdownBackground: #313131; + --vscode-settings-dropdownBorder: #3c3c3c; + --vscode-settings-dropdownForeground: #cccccc; + --vscode-settings-dropdownListBorder: #454545; + --vscode-settings-focusedRowBackground: rgba(42, 45, 46, 0.6); + --vscode-settings-focusedRowBorder: #0078d4; + --vscode-settings-headerBorder: #2b2b2b; + --vscode-settings-headerForeground: #ffffff; + --vscode-settings-modifiedItemIndicator: rgba(187, 128, 9, 0.4); + --vscode-settings-numberInputBackground: #313131; + --vscode-settings-numberInputBorder: #3c3c3c; + --vscode-settings-numberInputForeground: #cccccc; + --vscode-settings-rowHoverBackground: rgba(42, 45, 46, 0.3); + --vscode-settings-sashBorder: #2b2b2b; + --vscode-settings-settingsHeaderHoverForeground: rgba(255, 255, 255, 0.7); + --vscode-settings-textInputBackground: #313131; + --vscode-settings-textInputBorder: #3c3c3c; + --vscode-settings-textInputForeground: #cccccc; + --vscode-sideBar-background: #181818; + --vscode-sideBar-border: #2b2b2b; + --vscode-sideBar-dropBackground: rgba(83, 89, 93, 0.5); + --vscode-sideBar-foreground: #cccccc; + --vscode-sideBarActivityBarTop-border: #2b2b2b; + --vscode-sideBarSectionHeader-background: #181818; + --vscode-sideBarSectionHeader-border: #2b2b2b; + --vscode-sideBarSectionHeader-foreground: #cccccc; + --vscode-sideBarStickyScroll-background: #181818; + --vscode-sideBarStickyScroll-shadow: #000000; + --vscode-sideBarTitle-background: #181818; + --vscode-sideBarTitle-foreground: #cccccc; + --vscode-sideBySideEditor-horizontalBorder: rgba(255, 255, 255, 0.09); + --vscode-sideBySideEditor-verticalBorder: rgba(255, 255, 255, 0.09); + --vscode-simpleFindWidget-sashBorder: #454545; + --vscode-statusBar-background: #181818; + --vscode-statusBar-border: #2b2b2b; + --vscode-statusBar-debuggingBackground: #0078d4; + --vscode-statusBar-debuggingBorder: #2b2b2b; + --vscode-statusBar-debuggingForeground: #ffffff; + --vscode-statusBar-focusBorder: #0078d4; + --vscode-statusBar-foreground: #cccccc; + --vscode-statusBar-noFolderBackground: #1f1f1f; + --vscode-statusBar-noFolderBorder: #2b2b2b; + --vscode-statusBar-noFolderForeground: #cccccc; + --vscode-statusBarItem-activeBackground: rgba(255, 255, 255, 0.18); + --vscode-statusBarItem-compactHoverBackground: rgba(255, 255, 255, 0.2); + --vscode-statusBarItem-errorBackground: #b91007; + --vscode-statusBarItem-errorForeground: #ffffff; + --vscode-statusBarItem-errorHoverBackground: rgba(255, 255, 255, 0.12); + --vscode-statusBarItem-errorHoverForeground: #cccccc; + --vscode-statusBarItem-focusBorder: #0078d4; + --vscode-statusBarItem-hoverBackground: rgba(255, 255, 255, 0.12); + --vscode-statusBarItem-hoverForeground: #cccccc; + --vscode-statusBarItem-offlineBackground: #6c1717; + --vscode-statusBarItem-offlineForeground: #ffffff; + --vscode-statusBarItem-offlineHoverBackground: rgba(255, 255, 255, 0.12); + --vscode-statusBarItem-offlineHoverForeground: #cccccc; + --vscode-statusBarItem-prominentBackground: rgba(110, 118, 129, 0.4); + --vscode-statusBarItem-prominentForeground: #cccccc; + --vscode-statusBarItem-prominentHoverBackground: rgba(255, 255, 255, 0.12); + --vscode-statusBarItem-prominentHoverForeground: #cccccc; + --vscode-statusBarItem-remoteBackground: #0078d4; + --vscode-statusBarItem-remoteForeground: #ffffff; + --vscode-statusBarItem-remoteHoverBackground: rgba(255, 255, 255, 0.12); + --vscode-statusBarItem-remoteHoverForeground: #cccccc; + --vscode-statusBarItem-warningBackground: #7a6400; + --vscode-statusBarItem-warningForeground: #ffffff; + --vscode-statusBarItem-warningHoverBackground: rgba(255, 255, 255, 0.12); + --vscode-statusBarItem-warningHoverForeground: #cccccc; + --vscode-symbolIcon-arrayForeground: #cccccc; + --vscode-symbolIcon-booleanForeground: #cccccc; + --vscode-symbolIcon-classForeground: #ee9d28; + --vscode-symbolIcon-colorForeground: #cccccc; + --vscode-symbolIcon-constantForeground: #cccccc; + --vscode-symbolIcon-constructorForeground: #b180d7; + --vscode-symbolIcon-enumeratorForeground: #ee9d28; + --vscode-symbolIcon-enumeratorMemberForeground: #75beff; + --vscode-symbolIcon-eventForeground: #ee9d28; + --vscode-symbolIcon-fieldForeground: #75beff; + --vscode-symbolIcon-fileForeground: #cccccc; + --vscode-symbolIcon-folderForeground: #cccccc; + --vscode-symbolIcon-functionForeground: #b180d7; + --vscode-symbolIcon-interfaceForeground: #75beff; + --vscode-symbolIcon-keyForeground: #cccccc; + --vscode-symbolIcon-keywordForeground: #cccccc; + --vscode-symbolIcon-methodForeground: #b180d7; + --vscode-symbolIcon-moduleForeground: #cccccc; + --vscode-symbolIcon-namespaceForeground: #cccccc; + --vscode-symbolIcon-nullForeground: #cccccc; + --vscode-symbolIcon-numberForeground: #cccccc; + --vscode-symbolIcon-objectForeground: #cccccc; + --vscode-symbolIcon-operatorForeground: #cccccc; + --vscode-symbolIcon-packageForeground: #cccccc; + --vscode-symbolIcon-propertyForeground: #cccccc; + --vscode-symbolIcon-referenceForeground: #cccccc; + --vscode-symbolIcon-snippetForeground: #cccccc; + --vscode-symbolIcon-stringForeground: #cccccc; + --vscode-symbolIcon-structForeground: #cccccc; + --vscode-symbolIcon-textForeground: #cccccc; + --vscode-symbolIcon-typeParameterForeground: #cccccc; + --vscode-symbolIcon-unitForeground: #cccccc; + --vscode-symbolIcon-variableForeground: #75beff; + --vscode-tab-activeBackground: #1f1f1f; + --vscode-tab-activeBorder: #1f1f1f; + --vscode-tab-activeBorderTop: #0078d4; + --vscode-tab-activeForeground: #ffffff; + --vscode-tab-activeModifiedBorder: #3399cc; + --vscode-tab-border: #2b2b2b; + --vscode-tab-dragAndDropBorder: #ffffff; + --vscode-tab-hoverBackground: #1f1f1f; + --vscode-tab-inactiveBackground: #181818; + --vscode-tab-inactiveForeground: #9d9d9d; + --vscode-tab-inactiveModifiedBorder: rgba(51, 153, 204, 0.5); + --vscode-tab-lastPinnedBorder: rgba(204, 204, 204, 0.2); + --vscode-tab-selectedBackground: #222222; + --vscode-tab-selectedBorderTop: #6caddf; + --vscode-tab-selectedForeground: rgba(255, 255, 255, 0.63); + --vscode-tab-unfocusedActiveBackground: #1f1f1f; + --vscode-tab-unfocusedActiveBorder: #1f1f1f; + --vscode-tab-unfocusedActiveBorderTop: #2b2b2b; + --vscode-tab-unfocusedActiveForeground: rgba(255, 255, 255, 0.5); + --vscode-tab-unfocusedActiveModifiedBorder: rgba(51, 153, 204, 0.5); + --vscode-tab-unfocusedHoverBackground: #1f1f1f; + --vscode-tab-unfocusedInactiveBackground: #181818; + --vscode-tab-unfocusedInactiveForeground: rgba(157, 157, 157, 0.5); + --vscode-tab-unfocusedInactiveModifiedBorder: rgba(51, 153, 204, 0.25); + --vscode-terminal-ansiBlack: #000000; + --vscode-terminal-ansiBlue: #2472c8; + --vscode-terminal-ansiBrightBlack: #666666; + --vscode-terminal-ansiBrightBlue: #3b8eea; + --vscode-terminal-ansiBrightCyan: #29b8db; + --vscode-terminal-ansiBrightGreen: #23d18b; + --vscode-terminal-ansiBrightMagenta: #d670d6; + --vscode-terminal-ansiBrightRed: #f14c4c; + --vscode-terminal-ansiBrightWhite: #e5e5e5; + --vscode-terminal-ansiBrightYellow: #f5f543; + --vscode-terminal-ansiCyan: #11a8cd; + --vscode-terminal-ansiGreen: #0dbc79; + --vscode-terminal-ansiMagenta: #bc3fbc; + --vscode-terminal-ansiRed: #cd3131; + --vscode-terminal-ansiWhite: #e5e5e5; + --vscode-terminal-ansiYellow: #e5e510; + --vscode-terminal-border: #2b2b2b; + --vscode-terminal-dropBackground: rgba(83, 89, 93, 0.5); + --vscode-terminal-findMatchBackground: #9e6a03; + --vscode-terminal-findMatchHighlightBackground: rgba(234, 92, 0, 0.33); + --vscode-terminal-foreground: #cccccc; + --vscode-terminal-hoverHighlightBackground: rgba(38, 79, 120, 0.13); + --vscode-terminal-inactiveSelectionBackground: #3a3d41; + --vscode-terminal-initialHintForeground: rgba(255, 255, 255, 0.34); + --vscode-terminal-selectionBackground: #264f78; + --vscode-terminal-tab.activeBorder: #0078d4; + --vscode-terminalCommandDecoration-defaultBackground: rgba(255, 255, 255, 0.25); + --vscode-terminalCommandDecoration-errorBackground: #f14c4c; + --vscode-terminalCommandDecoration-successBackground: #1b81a8; + --vscode-terminalCommandGuide-foreground: #37373d; + --vscode-terminalOverviewRuler-border: #010409; + --vscode-terminalOverviewRuler-cursorForeground: rgba(160, 160, 160, 0.8); + --vscode-terminalOverviewRuler-findMatchForeground: rgba(209, 134, 22, 0.49); + --vscode-terminalStickyScrollHover-background: #2a2d2e; + --vscode-terminalSymbolIcon-aliasForeground: #b180d7; + --vscode-terminalSymbolIcon-argumentForeground: #75beff; + --vscode-terminalSymbolIcon-fileForeground: #cccccc; + --vscode-terminalSymbolIcon-flagForeground: #ee9d28; + --vscode-terminalSymbolIcon-folderForeground: #cccccc; + --vscode-terminalSymbolIcon-methodForeground: #b180d7; + --vscode-terminalSymbolIcon-optionForeground: #ee9d28; + --vscode-terminalSymbolIcon-optionValueForeground: #75beff; + --vscode-testing-coverCountBadgeBackground: #616161; + --vscode-testing-coverCountBadgeForeground: #f8f8f8; + --vscode-testing-coveredBackground: rgba(156, 204, 44, 0.2); + --vscode-testing-coveredBorder: rgba(156, 204, 44, 0.15); + --vscode-testing-coveredGutterBackground: rgba(156, 204, 44, 0.12); + --vscode-testing-iconErrored: #f14c4c; + --vscode-testing-iconErrored.retired: rgba(241, 76, 76, 0.7); + --vscode-testing-iconFailed: #f14c4c; + --vscode-testing-iconFailed.retired: rgba(241, 76, 76, 0.7); + --vscode-testing-iconPassed: #73c991; + --vscode-testing-iconPassed.retired: rgba(115, 201, 145, 0.7); + --vscode-testing-iconQueued: #cca700; + --vscode-testing-iconQueued.retired: rgba(204, 167, 0, 0.7); + --vscode-testing-iconSkipped: #848484; + --vscode-testing-iconSkipped.retired: rgba(132, 132, 132, 0.7); + --vscode-testing-iconUnset: #848484; + --vscode-testing-iconUnset.retired: rgba(132, 132, 132, 0.7); + --vscode-testing-message.error.badgeBackground: #f14c4c; + --vscode-testing-message.error.badgeBorder: #f14c4c; + --vscode-testing-message.error.badgeForeground: #000000; + --vscode-testing-message.info.decorationForeground: rgba(204, 204, 204, 0.5); + --vscode-testing-messagePeekBorder: #3794ff; + --vscode-testing-messagePeekHeaderBackground: rgba(55, 148, 255, 0.1); + --vscode-testing-peekBorder: #f14c4c; + --vscode-testing-peekHeaderBackground: rgba(241, 76, 76, 0.1); + --vscode-testing-runAction: #73c991; + --vscode-testing-uncoveredBackground: rgba(255, 0, 0, 0.2); + --vscode-testing-uncoveredBorder: rgba(255, 0, 0, 0.15); + --vscode-testing-uncoveredBranchBackground: #781212; + --vscode-testing-uncoveredGutterBackground: rgba(255, 0, 0, 0.3); + --vscode-textBlockQuote-background: #2b2b2b; + --vscode-textBlockQuote-border: #616161; + --vscode-textCodeBlock-background: #2b2b2b; + --vscode-textLink-activeForeground: #4daafc; + --vscode-textLink-foreground: #4daafc; + --vscode-textPreformat-background: #3c3c3c; + --vscode-textPreformat-foreground: #d0d0d0; + --vscode-textSeparator-foreground: #21262d; + --vscode-titleBar-activeBackground: #181818; + --vscode-titleBar-activeForeground: #cccccc; + --vscode-titleBar-border: #2b2b2b; + --vscode-titleBar-inactiveBackground: #1f1f1f; + --vscode-titleBar-inactiveForeground: #9d9d9d; + --vscode-toolbar-activeBackground: rgba(99, 102, 103, 0.31); + --vscode-toolbar-hoverBackground: rgba(90, 93, 94, 0.31); + --vscode-tree-inactiveIndentGuidesStroke: rgba(88, 88, 88, 0.4); + --vscode-tree-indentGuidesStroke: #585858; + --vscode-tree-tableColumnsBorder: rgba(204, 204, 204, 0.13); + --vscode-tree-tableOddRowsBackground: rgba(204, 204, 204, 0.04); + --vscode-walkThrough-embeddedEditorBackground: rgba(0, 0, 0, 0.4); + --vscode-walkthrough-stepTitle.foreground: #ffffff; + --vscode-welcomePage-progress.background: #313131; + --vscode-welcomePage-progress.foreground: #0078d4; + --vscode-welcomePage-tileBackground: #2b2b2b; + --vscode-welcomePage-tileBorder: rgba(255, 255, 255, 0.1); + --vscode-welcomePage-tileHoverBackground: #262626; + --vscode-widget-border: #313131; + --vscode-widget-shadow: rgba(0, 0, 0, 0.36); +} diff --git a/webview-ui/playwright/themes/vscode-theme-high-contrast-light.css b/webview-ui/playwright/themes/vscode-theme-high-contrast-light.css new file mode 100644 index 0000000000..ff3ba14d2c --- /dev/null +++ b/webview-ui/playwright/themes/vscode-theme-high-contrast-light.css @@ -0,0 +1,693 @@ +/* Generated from Default High Contrast Light by VS Code 1.100.0. Do not edit manually. */ +.vscode-high-contrast-light { + color-scheme: light; + --vscode-actionBar-toggledBackground: #dddddd; + --vscode-activityBar-activeBorder: #0f4a85; + --vscode-activityBar-activeFocusBorder: #b5200d; + --vscode-activityBar-background: #ffffff; + --vscode-activityBar-border: #0f4a85; + --vscode-activityBar-foreground: #292929; + --vscode-activityBar-inactiveForeground: #292929; + --vscode-activityBarBadge-background: #0f4a85; + --vscode-activityBarBadge-foreground: #ffffff; + --vscode-activityBarTop-activeBorder: #b5200d; + --vscode-activityBarTop-dropBorder: #292929; + --vscode-activityBarTop-foreground: #292929; + --vscode-activityBarTop-inactiveForeground: #292929; + --vscode-activityErrorBadge-background: #f14c4c; + --vscode-activityErrorBadge-foreground: #000000; + --vscode-activityWarningBadge-background: #cca700; + --vscode-activityWarningBadge-foreground: #000000; + --vscode-badge-background: #0f4a85; + --vscode-badge-foreground: #ffffff; + --vscode-banner-background: rgba(15, 74, 133, 0.1); + --vscode-banner-iconForeground: #1a85ff; + --vscode-breadcrumb-activeSelectionForeground: #2d2d2d; + --vscode-breadcrumb-background: #ffffff; + --vscode-breadcrumb-focusForeground: #2d2d2d; + --vscode-breadcrumb-foreground: rgba(41, 41, 41, 0.8); + --vscode-breadcrumbPicker-background: #ffffff; + --vscode-button-background: #0f4a85; + --vscode-button-border: #0f4a85; + --vscode-button-foreground: #ffffff; + --vscode-button-hoverBackground: #0f4a85; + --vscode-button-secondaryBackground: #ffffff; + --vscode-button-secondaryForeground: #292929; + --vscode-button-separator: rgba(255, 255, 255, 0.4); + --vscode-chart-axis: #0f4a85; + --vscode-chart-guide: #0f4a85; + --vscode-chart-line: #236b8e; + --vscode-charts-blue: #1a85ff; + --vscode-charts-foreground: #292929; + --vscode-charts-green: #374e06; + --vscode-charts-lines: rgba(41, 41, 41, 0.5); + --vscode-charts-orange: #0f4a85; + --vscode-charts-purple: #652d90; + --vscode-charts-red: #b5200d; + --vscode-charts-yellow: #895503; + --vscode-chat-avatarBackground: #ffffff; + --vscode-chat-avatarForeground: #292929; + --vscode-chat-editedFileForeground: #895503; + --vscode-chat-requestBorder: #0f4a85; + --vscode-chat-slashCommandBackground: #0f4a85; + --vscode-chat-slashCommandForeground: #ffffff; + --vscode-checkbox-background: #ffffff; + --vscode-checkbox-border: #0f4a85; + --vscode-checkbox-disabled.background: #b8b8b8; + --vscode-checkbox-disabled.foreground: #6f6f6f; + --vscode-checkbox-foreground: #292929; + --vscode-checkbox-selectBackground: #ffffff; + --vscode-checkbox-selectBorder: #292929; + --vscode-commandCenter-activeBorder: #292929; + --vscode-commandCenter-activeForeground: #292929; + --vscode-commandCenter-border: #0f4a85; + --vscode-commandCenter-debuggingBackground: rgba(181, 32, 13, 0.26); + --vscode-commandCenter-foreground: #292929; + --vscode-commandCenter-inactiveBorder: rgba(41, 41, 41, 0.25); + --vscode-commandCenter-inactiveForeground: #292929; + --vscode-commentsView-resolvedIcon: #0f4a85; + --vscode-commentsView-unresolvedIcon: #0f4a85; + --vscode-contrastActiveBorder: #006bbd; + --vscode-contrastBorder: #0f4a85; + --vscode-debugConsole-errorForeground: #b5200d; + --vscode-debugConsole-infoForeground: #292929; + --vscode-debugConsole-sourceForeground: #292929; + --vscode-debugConsole-warningForeground: #895503; + --vscode-debugConsoleInputIcon-foreground: #292929; + --vscode-debugExceptionWidget-background: #f1dfde; + --vscode-debugExceptionWidget-border: #a31515; + --vscode-debugIcon-breakpointCurrentStackframeForeground: #be8700; + --vscode-debugIcon-breakpointDisabledForeground: #848484; + --vscode-debugIcon-breakpointForeground: #e51400; + --vscode-debugIcon-breakpointStackframeForeground: #89d185; + --vscode-debugIcon-breakpointUnverifiedForeground: #848484; + --vscode-debugIcon-continueForeground: #007acc; + --vscode-debugIcon-disconnectForeground: #a1260d; + --vscode-debugIcon-pauseForeground: #007acc; + --vscode-debugIcon-restartForeground: #388a34; + --vscode-debugIcon-startForeground: #388a34; + --vscode-debugIcon-stepBackForeground: #007acc; + --vscode-debugIcon-stepIntoForeground: #007acc; + --vscode-debugIcon-stepOutForeground: #007acc; + --vscode-debugIcon-stepOverForeground: #007acc; + --vscode-debugIcon-stopForeground: #a1260d; + --vscode-debugTokenExpression-boolean: #0000ff; + --vscode-debugTokenExpression-error: #e51400; + --vscode-debugTokenExpression-name: #292929; + --vscode-debugTokenExpression-number: #098658; + --vscode-debugTokenExpression-string: #a31515; + --vscode-debugTokenExpression-type: #292929; + --vscode-debugTokenExpression-value: #292929; + --vscode-debugToolBar-background: #ffffff; + --vscode-debugView-exceptionLabelBackground: #a31515; + --vscode-debugView-exceptionLabelForeground: #292929; + --vscode-debugView-stateLabelBackground: rgba(136, 136, 136, 0.27); + --vscode-debugView-stateLabelForeground: #292929; + --vscode-debugView-valueChangedHighlight: #569cd6; + --vscode-descriptionForeground: rgba(41, 41, 41, 0.7); + --vscode-diffEditor-border: #0f4a85; + --vscode-diffEditor-insertedTextBorder: #374e06; + --vscode-diffEditor-move.border: rgba(139, 139, 139, 0.61); + --vscode-diffEditor-moveActive.border: #ffa500; + --vscode-diffEditor-removedTextBorder: #ad0707; + --vscode-diffEditor-unchangedRegionBackground: #ffffff; + --vscode-diffEditor-unchangedRegionForeground: #292929; + --vscode-diffEditor-unchangedRegionShadow: rgba(115, 115, 115, 0.75); + --vscode-disabledForeground: #7f7f7f; + --vscode-dropdown-background: #ffffff; + --vscode-dropdown-border: #0f4a85; + --vscode-dropdown-foreground: #292929; + --vscode-dropdown-listBackground: #ffffff; + --vscode-editor-background: #ffffff; + --vscode-editor-compositionBorder: #000000; + --vscode-editor-findMatchBorder: #006bbd; + --vscode-editor-findMatchHighlightBorder: #006bbd; + --vscode-editor-findRangeHighlightBorder: rgba(0, 107, 189, 0.4); + --vscode-editor-focusedStackFrameHighlightBackground: rgba(206, 231, 206, 0.45); + --vscode-editor-font-size: 14px; + --vscode-editor-font-weight: normal; + --vscode-editor-foreground: #292929; + --vscode-editor-inactiveSelectionBackground: rgba(15, 74, 133, 0.5); + --vscode-editor-inlineValuesBackground: rgba(255, 200, 0, 0.2); + --vscode-editor-inlineValuesForeground: rgba(0, 0, 0, 0.5); + --vscode-editor-lineHighlightBorder: #0f4a85; + --vscode-editor-linkedEditingBackground: #ffffff; + --vscode-editor-rangeHighlightBorder: #006bbd; + --vscode-editor-selectionBackground: #0f4a85; + --vscode-editor-selectionForeground: #ffffff; + --vscode-editor-selectionHighlightBorder: #006bbd; + --vscode-editor-snippetFinalTabstopHighlightBorder: #292929; + --vscode-editor-snippetTabstopHighlightBackground: rgba(10, 50, 100, 0.2); + --vscode-editor-stackFrameHighlightBackground: rgba(255, 255, 102, 0.45); + --vscode-editor-symbolHighlightBorder: #006bbd; + --vscode-editor-wordHighlightBorder: #006bbd; + --vscode-editor-wordHighlightStrongBorder: #006bbd; + --vscode-editor-wordHighlightTextBorder: #006bbd; + --vscode-editorActionList-background: #ffffff; + --vscode-editorActionList-focusBackground: rgba(15, 74, 133, 0.1); + --vscode-editorActionList-foreground: #292929; + --vscode-editorActiveLineNumber-foreground: #006bbd; + --vscode-editorBracketHighlight-foreground1: #0431fa; + --vscode-editorBracketHighlight-foreground2: #319331; + --vscode-editorBracketHighlight-foreground3: #7b3814; + --vscode-editorBracketHighlight-foreground4: rgba(0, 0, 0, 0); + --vscode-editorBracketHighlight-foreground5: rgba(0, 0, 0, 0); + --vscode-editorBracketHighlight-foreground6: rgba(0, 0, 0, 0); + --vscode-editorBracketHighlight-unexpectedBracket.foreground: #b5200d; + --vscode-editorBracketMatch-background: rgba(0, 0, 0, 0); + --vscode-editorBracketMatch-border: #0f4a85; + --vscode-editorBracketPairGuide-activeBackground1: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-activeBackground2: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-activeBackground3: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-activeBackground4: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-activeBackground5: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-activeBackground6: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background1: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background2: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background3: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background4: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background5: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background6: rgba(0, 0, 0, 0); + --vscode-editorCodeLens-foreground: #292929; + --vscode-editorCommentsWidget-rangeActiveBackground: rgba(15, 74, 133, 0.1); + --vscode-editorCommentsWidget-rangeBackground: rgba(15, 74, 133, 0.1); + --vscode-editorCommentsWidget-replyInputBackground: #ffffff; + --vscode-editorCommentsWidget-resolvedBorder: #0f4a85; + --vscode-editorCommentsWidget-unresolvedBorder: #0f4a85; + --vscode-editorCursor-foreground: #0f4a85; + --vscode-editorError-border: #b5200d; + --vscode-editorError-foreground: #b5200d; + --vscode-editorGhostText-border: rgba(41, 41, 41, 0.8); + --vscode-editorGroup-border: #0f4a85; + --vscode-editorGroup-dropBackground: rgba(15, 74, 133, 0.5); + --vscode-editorGroup-dropIntoPromptBackground: #ffffff; + --vscode-editorGroup-dropIntoPromptBorder: #0f4a85; + --vscode-editorGroup-dropIntoPromptForeground: #292929; + --vscode-editorGroup-focusedEmptyBorder: #006bbd; + --vscode-editorGroupHeader-border: #0f4a85; + --vscode-editorGroupHeader-noTabsBackground: #ffffff; + --vscode-editorGutter-addedBackground: #48985d; + --vscode-editorGutter-addedSecondaryBackground: #48985d; + --vscode-editorGutter-background: #ffffff; + --vscode-editorGutter-commentGlyphForeground: #ffffff; + --vscode-editorGutter-commentRangeForeground: #000000; + --vscode-editorGutter-commentUnresolvedGlyphForeground: #ffffff; + --vscode-editorGutter-deletedBackground: #b5200d; + --vscode-editorGutter-deletedSecondaryBackground: #b5200d; + --vscode-editorGutter-foldingControlForeground: #292929; + --vscode-editorGutter-itemBackground: #000000; + --vscode-editorGutter-itemGlyphForeground: #ffffff; + --vscode-editorGutter-modifiedBackground: #2090d3; + --vscode-editorGutter-modifiedSecondaryBackground: #2090d3; + --vscode-editorHint-border: #292929; + --vscode-editorHoverWidget-background: #ffffff; + --vscode-editorHoverWidget-border: #0f4a85; + --vscode-editorHoverWidget-foreground: #292929; + --vscode-editorHoverWidget-highlightForeground: #006bbd; + --vscode-editorHoverWidget-statusBarBackground: #ffffff; + --vscode-editorIndentGuide-activeBackground: #cccccc; + --vscode-editorIndentGuide-activeBackground1: #cccccc; + --vscode-editorIndentGuide-activeBackground2: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-activeBackground3: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-activeBackground4: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-activeBackground5: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-activeBackground6: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-background: #cccccc; + --vscode-editorIndentGuide-background1: #cccccc; + --vscode-editorIndentGuide-background2: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-background3: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-background4: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-background5: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-background6: rgba(0, 0, 0, 0); + --vscode-editorInfo-border: #292929; + --vscode-editorInfo-foreground: #1a85ff; + --vscode-editorInlayHint-background: rgba(15, 74, 133, 0.1); + --vscode-editorInlayHint-foreground: #000000; + --vscode-editorInlayHint-parameterBackground: rgba(15, 74, 133, 0.1); + --vscode-editorInlayHint-parameterForeground: #000000; + --vscode-editorInlayHint-typeBackground: rgba(15, 74, 133, 0.1); + --vscode-editorInlayHint-typeForeground: #000000; + --vscode-editorLightBulb-foreground: #007acc; + --vscode-editorLightBulbAi-foreground: #007acc; + --vscode-editorLightBulbAutoFix-foreground: #007acc; + --vscode-editorLineNumber-activeForeground: #006bbd; + --vscode-editorLineNumber-foreground: #292929; + --vscode-editorLink-activeForeground: #292929; + --vscode-editorMarkerNavigation-background: #ffffff; + --vscode-editorMarkerNavigationError-background: #0f4a85; + --vscode-editorMarkerNavigationInfo-background: #0f4a85; + --vscode-editorMarkerNavigationWarning-background: #0f4a85; + --vscode-editorMarkerNavigationWarning-headerBackground: rgba(15, 74, 133, 0.2); + --vscode-editorMultiCursor-primary.foreground: #0f4a85; + --vscode-editorMultiCursor-secondary.foreground: #0f4a85; + --vscode-editorOverviewRuler-addedForeground: rgba(72, 152, 93, 0.6); + --vscode-editorOverviewRuler-border: #666666; + --vscode-editorOverviewRuler-bracketMatchForeground: #a0a0a0; + --vscode-editorOverviewRuler-commentForeground: #000000; + --vscode-editorOverviewRuler-commentUnresolvedForeground: #000000; + --vscode-editorOverviewRuler-commonContentForeground: #007acc; + --vscode-editorOverviewRuler-currentContentForeground: #007acc; + --vscode-editorOverviewRuler-deletedForeground: rgba(181, 32, 13, 0.6); + --vscode-editorOverviewRuler-errorForeground: #b5200d; + --vscode-editorOverviewRuler-findMatchForeground: #ab5a00; + --vscode-editorOverviewRuler-incomingContentForeground: #007acc; + --vscode-editorOverviewRuler-infoForeground: #292929; + --vscode-editorOverviewRuler-modifiedForeground: rgba(32, 144, 211, 0.6); + --vscode-editorOverviewRuler-rangeHighlightForeground: rgba(0, 122, 204, 0.6); + --vscode-editorOverviewRuler-selectionHighlightForeground: rgba(160, 160, 160, 0.8); + --vscode-editorOverviewRuler-warningForeground: rgba(255, 204, 0, 0.8); + --vscode-editorOverviewRuler-wordHighlightForeground: rgba(160, 160, 160, 0.8); + --vscode-editorOverviewRuler-wordHighlightStrongForeground: rgba(192, 160, 192, 0.8); + --vscode-editorOverviewRuler-wordHighlightTextForeground: rgba(160, 160, 160, 0.8); + --vscode-editorPane-background: #ffffff; + --vscode-editorRuler-foreground: #292929; + --vscode-editorStickyScroll-background: #ffffff; + --vscode-editorStickyScroll-border: #0f4a85; + --vscode-editorStickyScrollHover-background: rgba(15, 74, 133, 0.1); + --vscode-editorSuggestWidget-background: #ffffff; + --vscode-editorSuggestWidget-border: #0f4a85; + --vscode-editorSuggestWidget-focusHighlightForeground: #006bbd; + --vscode-editorSuggestWidget-foreground: #292929; + --vscode-editorSuggestWidget-highlightForeground: #006bbd; + --vscode-editorSuggestWidgetStatus-foreground: rgba(41, 41, 41, 0.5); + --vscode-editorUnicodeHighlight-border: #895503; + --vscode-editorUnnecessaryCode-border: #0f4a85; + --vscode-editorWarning-border: rgba(255, 204, 0, 0.8); + --vscode-editorWarning-foreground: #895503; + --vscode-editorWatermark-foreground: #292929; + --vscode-editorWhitespace-foreground: #cccccc; + --vscode-editorWidget-background: #ffffff; + --vscode-editorWidget-border: #0f4a85; + --vscode-editorWidget-foreground: #292929; + --vscode-errorForeground: #b5200d; + --vscode-extensionBadge-remoteBackground: #0f4a85; + --vscode-extensionBadge-remoteForeground: #ffffff; + --vscode-extensionButton-separator: rgba(255, 255, 255, 0.4); + --vscode-extensionIcon-preReleaseForeground: #0f4a85; + --vscode-extensionIcon-privateForeground: rgba(0, 0, 0, 0.38); + --vscode-extensionIcon-sponsorForeground: #b51e78; + --vscode-extensionIcon-starForeground: #0f4a85; + --vscode-extensionIcon-verifiedForeground: #0f4a85; + --vscode-focusBorder: #006bbd; + --vscode-font-size: 13px; + --vscode-font-weight: normal; + --vscode-foreground: #292929; + --vscode-gauge-background: #0f4a85; + --vscode-gauge-border: #0f4a85; + --vscode-gauge-errorBackground: #0f4a85; + --vscode-gauge-errorForeground: #ffffff; + --vscode-gauge-foreground: #ffffff; + --vscode-gauge-warningBackground: #0f4a85; + --vscode-gauge-warningForeground: #ffffff; + --vscode-git-blame.editorDecorationForeground: #000000; + --vscode-gitDecoration-addedResourceForeground: #374e06; + --vscode-gitDecoration-conflictingResourceForeground: #ad0707; + --vscode-gitDecoration-deletedResourceForeground: #ad0707; + --vscode-gitDecoration-ignoredResourceForeground: #8e8e90; + --vscode-gitDecoration-modifiedResourceForeground: #895503; + --vscode-gitDecoration-renamedResourceForeground: #007100; + --vscode-gitDecoration-stageDeletedResourceForeground: #ad0707; + --vscode-gitDecoration-stageModifiedResourceForeground: #895503; + --vscode-gitDecoration-submoduleResourceForeground: #1258a7; + --vscode-gitDecoration-untrackedResourceForeground: #007100; + --vscode-icon-foreground: #292929; + --vscode-inlineChat-background: #ffffff; + --vscode-inlineChat-border: #0f4a85; + --vscode-inlineChat-foreground: #292929; + --vscode-inlineChatInput-background: #ffffff; + --vscode-inlineChatInput-border: #0f4a85; + --vscode-inlineChatInput-focusBorder: #006bbd; + --vscode-inlineChatInput-placeholderForeground: rgba(41, 41, 41, 0.7); + --vscode-inlineEdit-gutterIndicator.primaryBackground: rgba(15, 74, 133, 0.5); + --vscode-inlineEdit-gutterIndicator.primaryBorder: #0f4a85; + --vscode-inlineEdit-gutterIndicator.primaryForeground: #ffffff; + --vscode-inlineEdit-gutterIndicator.secondaryBackground: #ffffff; + --vscode-inlineEdit-gutterIndicator.secondaryBorder: #ffffff; + --vscode-inlineEdit-gutterIndicator.secondaryForeground: #292929; + --vscode-inlineEdit-gutterIndicator.successfulBackground: #0f4a85; + --vscode-inlineEdit-gutterIndicator.successfulBorder: #0f4a85; + --vscode-inlineEdit-gutterIndicator.successfulForeground: #ffffff; + --vscode-input-background: #ffffff; + --vscode-input-border: #0f4a85; + --vscode-input-foreground: #292929; + --vscode-input-placeholderForeground: rgba(41, 41, 41, 0.7); + --vscode-inputOption-activeBackground: rgba(0, 0, 0, 0); + --vscode-inputOption-activeBorder: #0f4a85; + --vscode-inputOption-activeForeground: #292929; + --vscode-inputValidation-errorBackground: #ffffff; + --vscode-inputValidation-errorBorder: #0f4a85; + --vscode-inputValidation-errorForeground: #292929; + --vscode-inputValidation-infoBackground: #ffffff; + --vscode-inputValidation-infoBorder: #0f4a85; + --vscode-inputValidation-infoForeground: #292929; + --vscode-inputValidation-warningBackground: #ffffff; + --vscode-inputValidation-warningBorder: #0f4a85; + --vscode-inputValidation-warningForeground: #292929; + --vscode-interactive-activeCodeBorder: #0f4a85; + --vscode-interactive-inactiveCodeBorder: #0f4a85; + --vscode-keybindingLabel-background: rgba(0, 0, 0, 0); + --vscode-keybindingLabel-border: #0f4a85; + --vscode-keybindingLabel-bottomBorder: #292929; + --vscode-keybindingLabel-foreground: #292929; + --vscode-list-activeSelectionBackground: rgba(15, 74, 133, 0.1); + --vscode-list-deemphasizedForeground: #666666; + --vscode-list-filterMatchBorder: #006bbd; + --vscode-list-focusHighlightForeground: #006bbd; + --vscode-list-focusOutline: #006bbd; + --vscode-list-highlightForeground: #006bbd; + --vscode-list-hoverBackground: rgba(15, 74, 133, 0.1); + --vscode-list-inactiveSelectionBackground: rgba(15, 74, 133, 0.1); + --vscode-list-invalidItemForeground: #b5200d; + --vscode-listFilterWidget-background: #ffffff; + --vscode-listFilterWidget-noMatchesOutline: #0f4a85; + --vscode-listFilterWidget-outline: #007acc; + --vscode-menu-background: #ffffff; + --vscode-menu-border: #0f4a85; + --vscode-menu-foreground: #292929; + --vscode-menu-selectionBackground: rgba(15, 74, 133, 0.1); + --vscode-menu-selectionBorder: #006bbd; + --vscode-menu-separatorBackground: #0f4a85; + --vscode-menubar-selectionBorder: #006bbd; + --vscode-menubar-selectionForeground: #292929; + --vscode-merge-border: #007acc; + --vscode-mergeEditor-change.background: rgba(155, 185, 85, 0.2); + --vscode-mergeEditor-change.word.background: rgba(156, 204, 44, 0.4); + --vscode-mergeEditor-changeBase.background: #ffcccc; + --vscode-mergeEditor-changeBase.word.background: #ffa3a3; + --vscode-mergeEditor-conflict.handled.minimapOverViewRuler: rgba(173, 172, 168, 0.93); + --vscode-mergeEditor-conflict.handledFocused.border: rgba(193, 193, 193, 0.8); + --vscode-mergeEditor-conflict.handledUnfocused.border: rgba(134, 134, 134, 0.29); + --vscode-mergeEditor-conflict.unhandled.minimapOverViewRuler: #fcba03; + --vscode-mergeEditor-conflict.unhandledFocused.border: #ffa600; + --vscode-mergeEditor-conflict.unhandledUnfocused.border: rgba(255, 166, 0, 0.48); + --vscode-mergeEditor-conflictingLines.background: rgba(255, 234, 0, 0.28); + --vscode-minimap-chatEditHighlight: rgba(255, 255, 255, 0.6); + --vscode-minimap-errorHighlight: #b5200d; + --vscode-minimap-findMatchHighlight: #0f4a85; + --vscode-minimap-foregroundOpacity: #000000; + --vscode-minimap-infoHighlight: #292929; + --vscode-minimap-selectionHighlight: #0f4a85; + --vscode-minimap-selectionOccurrenceHighlight: #0f4a85; + --vscode-minimap-warningHighlight: rgba(255, 204, 0, 0.8); + --vscode-minimapGutter-addedBackground: #48985d; + --vscode-minimapGutter-deletedBackground: #b5200d; + --vscode-minimapGutter-modifiedBackground: #2090d3; + --vscode-minimapSlider-activeBackground: rgba(15, 74, 133, 0.5); + --vscode-minimapSlider-background: rgba(15, 74, 133, 0.2); + --vscode-minimapSlider-hoverBackground: rgba(15, 74, 133, 0.4); + --vscode-multiDiffEditor-background: #ffffff; + --vscode-multiDiffEditor-border: #cccccc; + --vscode-notebook-cellBorderColor: #0f4a85; + --vscode-notebook-cellInsertionIndicator: #006bbd; + --vscode-notebook-cellStatusBarItemHoverBackground: rgba(0, 0, 0, 0.08); + --vscode-notebook-cellToolbarSeparator: #0f4a85; + --vscode-notebook-focusedCellBorder: #006bbd; + --vscode-notebook-focusedEditorBorder: #006bbd; + --vscode-notebook-inactiveFocusedCellBorder: #0f4a85; + --vscode-notebook-inactiveSelectedCellBorder: #006bbd; + --vscode-notebook-selectedCellBorder: #0f4a85; + --vscode-notebookEditorOverviewRuler-runningCellForeground: #388a34; + --vscode-notebookScrollbarSlider-activeBackground: #0f4a85; + --vscode-notebookScrollbarSlider-background: rgba(15, 74, 133, 0.4); + --vscode-notebookScrollbarSlider-hoverBackground: rgba(15, 74, 133, 0.8); + --vscode-notebookStatusErrorIcon-foreground: #b5200d; + --vscode-notebookStatusRunningIcon-foreground: #292929; + --vscode-notebookStatusSuccessIcon-foreground: #388a34; + --vscode-notificationCenter-border: #0f4a85; + --vscode-notificationCenterHeader-background: #ffffff; + --vscode-notificationLink-foreground: #0f4a85; + --vscode-notificationToast-border: #0f4a85; + --vscode-notifications-background: #ffffff; + --vscode-notifications-border: #ffffff; + --vscode-notifications-foreground: #292929; + --vscode-notificationsErrorIcon-foreground: #b5200d; + --vscode-notificationsInfoIcon-foreground: #1a85ff; + --vscode-notificationsWarningIcon-foreground: #895503; + --vscode-panel-background: #ffffff; + --vscode-panel-border: #0f4a85; + --vscode-panel-dropBorder: #292929; + --vscode-panelInput-border: #0f4a85; + --vscode-panelSection-border: #0f4a85; + --vscode-panelSection-dropBackground: rgba(15, 74, 133, 0.5); + --vscode-panelSectionHeader-border: #0f4a85; + --vscode-panelStickyScroll-background: #ffffff; + --vscode-panelTitle-activeBorder: #b5200d; + --vscode-panelTitle-activeForeground: #292929; + --vscode-panelTitle-border: #0f4a85; + --vscode-panelTitle-inactiveForeground: #292929; + --vscode-panelTitleBadge-background: #0f4a85; + --vscode-panelTitleBadge-foreground: #ffffff; + --vscode-peekView-border: #0f4a85; + --vscode-peekViewEditor-background: #ffffff; + --vscode-peekViewEditor-matchHighlightBorder: #006bbd; + --vscode-peekViewEditorGutter-background: #ffffff; + --vscode-peekViewEditorStickyScroll-background: #ffffff; + --vscode-peekViewResult-background: #ffffff; + --vscode-peekViewResult-fileForeground: #292929; + --vscode-peekViewResult-lineForeground: #292929; + --vscode-peekViewResult-selectionForeground: #292929; + --vscode-peekViewTitle-background: #ffffff; + --vscode-peekViewTitleDescription-foreground: #292929; + --vscode-peekViewTitleLabel-foreground: #292929; + --vscode-pickerGroup-border: #0f4a85; + --vscode-pickerGroup-foreground: #0f4a85; + --vscode-ports-iconRunningProcessForeground: #ffffff; + --vscode-problemsErrorIcon-foreground: #b5200d; + --vscode-problemsInfoIcon-foreground: #1a85ff; + --vscode-problemsWarningIcon-foreground: #895503; + --vscode-profileBadge-background: #000000; + --vscode-profileBadge-foreground: #ffffff; + --vscode-profiles-sashBorder: #0f4a85; + --vscode-progressBar-background: #0f4a85; + --vscode-prompt-frontMatter.background: #0f4a85; + --vscode-prompt-frontMatter.inactiveBackground: #0f4a85; + --vscode-quickInput-background: #ffffff; + --vscode-quickInput-foreground: #292929; + --vscode-quickInputTitle-background: #ffffff; + --vscode-radio-activeBackground: rgba(0, 0, 0, 0); + --vscode-radio-activeBorder: #0f4a85; + --vscode-radio-activeForeground: #292929; + --vscode-radio-inactiveBorder: rgba(41, 41, 41, 0.2); + --vscode-sash-hoverBorder: #006bbd; + --vscode-scmGraph-foreground1: #ffb000; + --vscode-scmGraph-foreground2: #dc267f; + --vscode-scmGraph-foreground3: #994f00; + --vscode-scmGraph-foreground4: #40b0a6; + --vscode-scmGraph-foreground5: #b66dff; + --vscode-scmGraph-historyItemBaseRefColor: #ea5c00; + --vscode-scmGraph-historyItemHoverAdditionsForeground: #374e06; + --vscode-scmGraph-historyItemHoverDefaultLabelBackground: #0f4a85; + --vscode-scmGraph-historyItemHoverDefaultLabelForeground: #292929; + --vscode-scmGraph-historyItemHoverDeletionsForeground: #ad0707; + --vscode-scmGraph-historyItemHoverLabelForeground: #ffffff; + --vscode-scmGraph-historyItemRefColor: #1a85ff; + --vscode-scmGraph-historyItemRemoteRefColor: #652d90; + --vscode-scrollbarSlider-activeBackground: #0f4a85; + --vscode-scrollbarSlider-background: rgba(15, 74, 133, 0.4); + --vscode-scrollbarSlider-hoverBackground: rgba(15, 74, 133, 0.8); + --vscode-search-resultsInfoForeground: #292929; + --vscode-searchEditor-findMatchBorder: #006bbd; + --vscode-searchEditor-textInputBorder: #0f4a85; + --vscode-settings-checkboxBackground: #ffffff; + --vscode-settings-checkboxBorder: #0f4a85; + --vscode-settings-checkboxForeground: #292929; + --vscode-settings-dropdownBackground: #ffffff; + --vscode-settings-dropdownBorder: #0f4a85; + --vscode-settings-dropdownForeground: #292929; + --vscode-settings-dropdownListBorder: #0f4a85; + --vscode-settings-focusedRowBorder: #006bbd; + --vscode-settings-headerBorder: #0f4a85; + --vscode-settings-headerForeground: #292929; + --vscode-settings-modifiedItemIndicator: #66afe0; + --vscode-settings-numberInputBackground: #ffffff; + --vscode-settings-numberInputBorder: #0f4a85; + --vscode-settings-numberInputForeground: #292929; + --vscode-settings-sashBorder: #0f4a85; + --vscode-settings-settingsHeaderHoverForeground: rgba(41, 41, 41, 0.7); + --vscode-settings-textInputBackground: #ffffff; + --vscode-settings-textInputBorder: #0f4a85; + --vscode-settings-textInputForeground: #292929; + --vscode-sideBar-background: #ffffff; + --vscode-sideBar-border: #0f4a85; + --vscode-sideBar-dropBackground: rgba(15, 74, 133, 0.5); + --vscode-sideBarActivityBarTop-border: #0f4a85; + --vscode-sideBarSectionHeader-border: #0f4a85; + --vscode-sideBarStickyScroll-background: #ffffff; + --vscode-sideBarTitle-background: #ffffff; + --vscode-sideBarTitle-border: #0f4a85; + --vscode-sideBySideEditor-horizontalBorder: #0f4a85; + --vscode-sideBySideEditor-verticalBorder: #0f4a85; + --vscode-simpleFindWidget-sashBorder: #0f4a85; + --vscode-statusBar-border: #0f4a85; + --vscode-statusBar-debuggingBackground: #b5200d; + --vscode-statusBar-debuggingBorder: #0f4a85; + --vscode-statusBar-debuggingForeground: #ffffff; + --vscode-statusBar-focusBorder: #292929; + --vscode-statusBar-foreground: #292929; + --vscode-statusBar-noFolderBorder: #0f4a85; + --vscode-statusBar-noFolderForeground: #292929; + --vscode-statusBarItem-activeBackground: rgba(0, 0, 0, 0.18); + --vscode-statusBarItem-compactHoverBackground: rgba(0, 0, 0, 0.2); + --vscode-statusBarItem-errorBackground: #b5200d; + --vscode-statusBarItem-errorForeground: #ffffff; + --vscode-statusBarItem-errorHoverBackground: rgba(0, 0, 0, 0.12); + --vscode-statusBarItem-errorHoverForeground: #292929; + --vscode-statusBarItem-focusBorder: #006bbd; + --vscode-statusBarItem-hoverBackground: rgba(0, 0, 0, 0.12); + --vscode-statusBarItem-hoverForeground: #292929; + --vscode-statusBarItem-offlineBackground: #6c1717; + --vscode-statusBarItem-offlineForeground: #000000; + --vscode-statusBarItem-offlineHoverForeground: #292929; + --vscode-statusBarItem-prominentBackground: rgba(0, 0, 0, 0.5); + --vscode-statusBarItem-prominentForeground: #292929; + --vscode-statusBarItem-prominentHoverBackground: rgba(0, 0, 0, 0.12); + --vscode-statusBarItem-prominentHoverForeground: #292929; + --vscode-statusBarItem-remoteBackground: #ffffff; + --vscode-statusBarItem-remoteForeground: #000000; + --vscode-statusBarItem-remoteHoverForeground: #292929; + --vscode-statusBarItem-warningBackground: #895503; + --vscode-statusBarItem-warningForeground: #ffffff; + --vscode-statusBarItem-warningHoverBackground: rgba(0, 0, 0, 0.12); + --vscode-statusBarItem-warningHoverForeground: #292929; + --vscode-symbolIcon-arrayForeground: #292929; + --vscode-symbolIcon-booleanForeground: #292929; + --vscode-symbolIcon-classForeground: #d67e00; + --vscode-symbolIcon-colorForeground: #292929; + --vscode-symbolIcon-constantForeground: #292929; + --vscode-symbolIcon-constructorForeground: #652d90; + --vscode-symbolIcon-enumeratorForeground: #d67e00; + --vscode-symbolIcon-enumeratorMemberForeground: #007acc; + --vscode-symbolIcon-eventForeground: #d67e00; + --vscode-symbolIcon-fieldForeground: #007acc; + --vscode-symbolIcon-fileForeground: #292929; + --vscode-symbolIcon-folderForeground: #292929; + --vscode-symbolIcon-functionForeground: #652d90; + --vscode-symbolIcon-interfaceForeground: #007acc; + --vscode-symbolIcon-keyForeground: #292929; + --vscode-symbolIcon-keywordForeground: #292929; + --vscode-symbolIcon-methodForeground: #652d90; + --vscode-symbolIcon-moduleForeground: #292929; + --vscode-symbolIcon-namespaceForeground: #292929; + --vscode-symbolIcon-nullForeground: #292929; + --vscode-symbolIcon-numberForeground: #292929; + --vscode-symbolIcon-objectForeground: #292929; + --vscode-symbolIcon-operatorForeground: #292929; + --vscode-symbolIcon-packageForeground: #292929; + --vscode-symbolIcon-propertyForeground: #292929; + --vscode-symbolIcon-referenceForeground: #292929; + --vscode-symbolIcon-snippetForeground: #292929; + --vscode-symbolIcon-stringForeground: #292929; + --vscode-symbolIcon-structForeground: #292929; + --vscode-symbolIcon-textForeground: #292929; + --vscode-symbolIcon-typeParameterForeground: #292929; + --vscode-symbolIcon-unitForeground: #292929; + --vscode-symbolIcon-variableForeground: #007acc; + --vscode-tab-activeBackground: #ffffff; + --vscode-tab-activeBorderTop: #b5200d; + --vscode-tab-activeForeground: #292929; + --vscode-tab-activeModifiedBorder: #0f4a85; + --vscode-tab-border: #0f4a85; + --vscode-tab-dragAndDropBorder: #006bbd; + --vscode-tab-inactiveForeground: #292929; + --vscode-tab-inactiveModifiedBorder: #0f4a85; + --vscode-tab-lastPinnedBorder: #0f4a85; + --vscode-tab-selectedBackground: #ffffff; + --vscode-tab-selectedBorderTop: #b5200d; + --vscode-tab-selectedForeground: #292929; + --vscode-tab-unfocusedActiveBackground: #ffffff; + --vscode-tab-unfocusedActiveBorderTop: #b5200d; + --vscode-tab-unfocusedActiveForeground: #292929; + --vscode-tab-unfocusedActiveModifiedBorder: #0f4a85; + --vscode-tab-unfocusedHoverBorder: #0f4a85; + --vscode-tab-unfocusedInactiveForeground: #292929; + --vscode-tab-unfocusedInactiveModifiedBorder: #0f4a85; + --vscode-terminal-ansiBlack: #292929; + --vscode-terminal-ansiBlue: #0451a5; + --vscode-terminal-ansiBrightBlack: #666666; + --vscode-terminal-ansiBrightBlue: #0451a5; + --vscode-terminal-ansiBrightCyan: #0598bc; + --vscode-terminal-ansiBrightGreen: #00bc00; + --vscode-terminal-ansiBrightMagenta: #bc05bc; + --vscode-terminal-ansiBrightRed: #cd3131; + --vscode-terminal-ansiBrightWhite: #a5a5a5; + --vscode-terminal-ansiBrightYellow: #b5ba00; + --vscode-terminal-ansiCyan: #0598bc; + --vscode-terminal-ansiGreen: #136c13; + --vscode-terminal-ansiMagenta: #bc05bc; + --vscode-terminal-ansiRed: #cd3131; + --vscode-terminal-ansiWhite: #555555; + --vscode-terminal-ansiYellow: #949800; + --vscode-terminal-border: #0f4a85; + --vscode-terminal-dropBackground: rgba(15, 74, 133, 0.5); + --vscode-terminal-findMatchBackground: #0f4a85; + --vscode-terminal-findMatchBorder: #0f4a85; + --vscode-terminal-findMatchHighlightBorder: #0f4a85; + --vscode-terminal-foreground: #292929; + --vscode-terminal-inactiveSelectionBackground: rgba(15, 74, 133, 0.5); + --vscode-terminal-selectionBackground: #0f4a85; + --vscode-terminal-selectionForeground: #ffffff; + --vscode-terminalCommandDecoration-defaultBackground: rgba(0, 0, 0, 0.25); + --vscode-terminalCommandDecoration-errorBackground: #b5200d; + --vscode-terminalCommandDecoration-successBackground: #007100; + --vscode-terminalCommandGuide-foreground: #0f4a85; + --vscode-terminalOverviewRuler-border: #666666; + --vscode-terminalOverviewRuler-cursorForeground: rgba(160, 160, 160, 0.8); + --vscode-terminalOverviewRuler-findMatchForeground: #0f4a85; + --vscode-terminalStickyScroll-border: #0f4a85; + --vscode-terminalStickyScrollHover-background: #0f4a85; + --vscode-terminalSymbolIcon-aliasForeground: #652d90; + --vscode-terminalSymbolIcon-argumentForeground: #007acc; + --vscode-terminalSymbolIcon-fileForeground: #292929; + --vscode-terminalSymbolIcon-flagForeground: #d67e00; + --vscode-terminalSymbolIcon-folderForeground: #292929; + --vscode-terminalSymbolIcon-methodForeground: #652d90; + --vscode-terminalSymbolIcon-optionForeground: #d67e00; + --vscode-terminalSymbolIcon-optionValueForeground: #007acc; + --vscode-testing-coverCountBadgeBackground: #0f4a85; + --vscode-testing-coverCountBadgeForeground: #ffffff; + --vscode-testing-coveredBorder: #0f4a85; + --vscode-testing-coveredGutterBackground: #374e06; + --vscode-testing-iconErrored: #b5200d; + --vscode-testing-iconErrored.retired: rgba(181, 32, 13, 0.7); + --vscode-testing-iconFailed: #b5200d; + --vscode-testing-iconFailed.retired: rgba(181, 32, 13, 0.7); + --vscode-testing-iconPassed: #007100; + --vscode-testing-iconPassed.retired: rgba(0, 113, 0, 0.7); + --vscode-testing-iconQueued: #cca700; + --vscode-testing-iconQueued.retired: rgba(204, 167, 0, 0.7); + --vscode-testing-iconSkipped: #848484; + --vscode-testing-iconSkipped.retired: rgba(132, 132, 132, 0.7); + --vscode-testing-iconUnset: #848484; + --vscode-testing-iconUnset.retired: rgba(132, 132, 132, 0.7); + --vscode-testing-message.error.badgeBackground: #f14c4c; + --vscode-testing-message.error.badgeBorder: #f14c4c; + --vscode-testing-message.error.badgeForeground: #000000; + --vscode-testing-message.info.decorationForeground: rgba(41, 41, 41, 0.5); + --vscode-testing-messagePeekBorder: #0f4a85; + --vscode-testing-peekBorder: #0f4a85; + --vscode-testing-runAction: #007100; + --vscode-testing-uncoveredBorder: #0f4a85; + --vscode-testing-uncoveredGutterBackground: #b5200d; + --vscode-textBlockQuote-background: #f2f2f2; + --vscode-textBlockQuote-border: #292929; + --vscode-textCodeBlock-background: #f2f2f2; + --vscode-textLink-activeForeground: #0f4a85; + --vscode-textLink-foreground: #0f4a85; + --vscode-textPreformat-background: #09345f; + --vscode-textPreformat-foreground: #ffffff; + --vscode-textSeparator-foreground: #292929; + --vscode-titleBar-activeBackground: #ffffff; + --vscode-titleBar-activeForeground: #292929; + --vscode-titleBar-border: #0f4a85; + --vscode-titleBar-inactiveForeground: #292929; + --vscode-toolbar-hoverOutline: #006bbd; + --vscode-tree-inactiveIndentGuidesStroke: rgba(165, 165, 165, 0.4); + --vscode-tree-indentGuidesStroke: #a5a5a5; + --vscode-welcomePage-progress.background: #ffffff; + --vscode-welcomePage-progress.foreground: #0f4a85; + --vscode-welcomePage-tileBackground: #ffffff; + --vscode-welcomePage-tileBorder: #0f4a85; + --vscode-widget-border: #0f4a85; + --vscode-window-activeBorder: #0f4a85; + --vscode-window-inactiveBorder: #0f4a85; +} diff --git a/webview-ui/playwright/themes/vscode-theme-high-contrast.css b/webview-ui/playwright/themes/vscode-theme-high-contrast.css new file mode 100644 index 0000000000..8984353528 --- /dev/null +++ b/webview-ui/playwright/themes/vscode-theme-high-contrast.css @@ -0,0 +1,655 @@ +/* Generated from Default High Contrast by VS Code 1.100.0. Do not edit manually. */ +.vscode-high-contrast { + color-scheme: dark; + --vscode-actionBar-toggledBackground: #383a49; + --vscode-activityBar-activeBorder: #6fc3df; + --vscode-activityBar-background: #000000; + --vscode-activityBar-border: #6fc3df; + --vscode-activityBar-foreground: #ffffff; + --vscode-activityBar-inactiveForeground: #ffffff; + --vscode-activityBarBadge-background: #000000; + --vscode-activityBarBadge-foreground: #ffffff; + --vscode-activityBarTop-activeBorder: #6fc3df; + --vscode-activityBarTop-dropBorder: #ffffff; + --vscode-activityBarTop-foreground: #ffffff; + --vscode-activityBarTop-inactiveForeground: #ffffff; + --vscode-badge-background: #000000; + --vscode-badge-foreground: #ffffff; + --vscode-banner-iconForeground: #3794ff; + --vscode-breadcrumb-activeSelectionForeground: #ffffff; + --vscode-breadcrumb-background: #000000; + --vscode-breadcrumb-focusForeground: #ffffff; + --vscode-breadcrumb-foreground: rgba(255, 255, 255, 0.8); + --vscode-breadcrumbPicker-background: #0c141f; + --vscode-button-border: #6fc3df; + --vscode-button-foreground: #ffffff; + --vscode-button-secondaryForeground: #ffffff; + --vscode-button-separator: rgba(255, 255, 255, 0.4); + --vscode-chart-axis: #6fc3df; + --vscode-chart-guide: #6fc3df; + --vscode-chart-line: #236b8e; + --vscode-charts-blue: #3794ff; + --vscode-charts-foreground: #ffffff; + --vscode-charts-green: #89d185; + --vscode-charts-lines: rgba(255, 255, 255, 0.5); + --vscode-charts-orange: #ab5a00; + --vscode-charts-purple: #b180d7; + --vscode-charts-red: #f48771; + --vscode-charts-yellow: #ffd370; + --vscode-chat-avatarBackground: #000000; + --vscode-chat-avatarForeground: #ffffff; + --vscode-chat-editedFileForeground: #e2c08d; + --vscode-chat-requestBackground: #0c141f; + --vscode-chat-requestBorder: #6fc3df; + --vscode-chat-slashCommandBackground: #ffffff; + --vscode-chat-slashCommandForeground: #000000; + --vscode-checkbox-background: #000000; + --vscode-checkbox-border: #6fc3df; + --vscode-checkbox-disabled.background: #545454; + --vscode-checkbox-disabled.foreground: #aaaaaa; + --vscode-checkbox-foreground: #ffffff; + --vscode-checkbox-selectBackground: #0c141f; + --vscode-checkbox-selectBorder: #ffffff; + --vscode-commandCenter-activeBorder: #ffffff; + --vscode-commandCenter-activeForeground: #ffffff; + --vscode-commandCenter-border: #6fc3df; + --vscode-commandCenter-debuggingBackground: rgba(186, 89, 44, 0.26); + --vscode-commandCenter-foreground: #ffffff; + --vscode-commentsView-resolvedIcon: #6fc3df; + --vscode-commentsView-unresolvedIcon: #6fc3df; + --vscode-contrastActiveBorder: #f38518; + --vscode-contrastBorder: #6fc3df; + --vscode-debugConsole-errorForeground: #f48771; + --vscode-debugConsole-infoForeground: #ffffff; + --vscode-debugConsole-sourceForeground: #ffffff; + --vscode-debugConsole-warningForeground: #008000; + --vscode-debugConsoleInputIcon-foreground: #ffffff; + --vscode-debugExceptionWidget-background: #420b0d; + --vscode-debugExceptionWidget-border: #a31515; + --vscode-debugIcon-breakpointCurrentStackframeForeground: #ffcc00; + --vscode-debugIcon-breakpointDisabledForeground: #848484; + --vscode-debugIcon-breakpointForeground: #e51400; + --vscode-debugIcon-breakpointStackframeForeground: #89d185; + --vscode-debugIcon-breakpointUnverifiedForeground: #848484; + --vscode-debugIcon-continueForeground: #75beff; + --vscode-debugIcon-disconnectForeground: #f48771; + --vscode-debugIcon-pauseForeground: #75beff; + --vscode-debugIcon-restartForeground: #89d185; + --vscode-debugIcon-startForeground: #89d185; + --vscode-debugIcon-stepBackForeground: #75beff; + --vscode-debugIcon-stepIntoForeground: #75beff; + --vscode-debugIcon-stepOutForeground: #75beff; + --vscode-debugIcon-stepOverForeground: #75beff; + --vscode-debugIcon-stopForeground: #f48771; + --vscode-debugTokenExpression-boolean: #75bdfe; + --vscode-debugTokenExpression-error: #f48771; + --vscode-debugTokenExpression-name: #ffffff; + --vscode-debugTokenExpression-number: #89d185; + --vscode-debugTokenExpression-string: #f48771; + --vscode-debugTokenExpression-type: #ffffff; + --vscode-debugTokenExpression-value: #ffffff; + --vscode-debugToolBar-background: #000000; + --vscode-debugView-exceptionLabelBackground: #6c2022; + --vscode-debugView-exceptionLabelForeground: #ffffff; + --vscode-debugView-stateLabelBackground: rgba(136, 136, 136, 0.27); + --vscode-debugView-stateLabelForeground: #ffffff; + --vscode-debugView-valueChangedHighlight: #569cd6; + --vscode-descriptionForeground: rgba(255, 255, 255, 0.7); + --vscode-diffEditor-border: #6fc3df; + --vscode-diffEditor-insertedTextBorder: #33ff2e; + --vscode-diffEditor-move.border: rgba(139, 139, 139, 0.61); + --vscode-diffEditor-moveActive.border: #ffa500; + --vscode-diffEditor-removedTextBorder: #ff008f; + --vscode-diffEditor-unchangedRegionBackground: #000000; + --vscode-diffEditor-unchangedRegionForeground: #ffffff; + --vscode-diffEditor-unchangedRegionShadow: #000000; + --vscode-disabledForeground: #a5a5a5; + --vscode-dropdown-background: #000000; + --vscode-dropdown-border: #6fc3df; + --vscode-dropdown-foreground: #ffffff; + --vscode-dropdown-listBackground: #000000; + --vscode-editor-background: #000000; + --vscode-editor-compositionBorder: #ffffff; + --vscode-editor-findMatchBorder: #f38518; + --vscode-editor-findMatchHighlightBorder: #f38518; + --vscode-editor-findRangeHighlightBorder: rgba(243, 133, 24, 0.4); + --vscode-editor-focusedStackFrameHighlightBackground: rgba(122, 189, 122, 0.3); + --vscode-editor-font-size: 14px; + --vscode-editor-font-weight: normal; + --vscode-editor-foreground: #ffffff; + --vscode-editor-hoverHighlightBackground: rgba(173, 214, 255, 0.15); + --vscode-editor-inactiveSelectionBackground: rgba(255, 255, 255, 0.7); + --vscode-editor-inlineValuesBackground: rgba(255, 200, 0, 0.2); + --vscode-editor-inlineValuesForeground: rgba(255, 255, 255, 0.5); + --vscode-editor-lineHighlightBorder: #f38518; + --vscode-editor-linkedEditingBackground: rgba(255, 0, 0, 0.3); + --vscode-editor-rangeHighlightBorder: #f38518; + --vscode-editor-selectionBackground: #ffffff; + --vscode-editor-selectionForeground: #000000; + --vscode-editor-selectionHighlightBorder: #f38518; + --vscode-editor-snippetFinalTabstopHighlightBorder: #525252; + --vscode-editor-snippetTabstopHighlightBackground: rgba(124, 124, 124, 0.3); + --vscode-editor-stackFrameHighlightBackground: rgba(255, 255, 0, 0.2); + --vscode-editor-symbolHighlightBorder: #f38518; + --vscode-editor-wordHighlightBorder: #f38518; + --vscode-editor-wordHighlightStrongBorder: #f38518; + --vscode-editor-wordHighlightTextBorder: #f38518; + --vscode-editorActionList-background: #0c141f; + --vscode-editorActionList-foreground: #ffffff; + --vscode-editorActiveLineNumber-foreground: #f38518; + --vscode-editorBracketHighlight-foreground1: #ffd700; + --vscode-editorBracketHighlight-foreground2: #da70d6; + --vscode-editorBracketHighlight-foreground3: #87cefa; + --vscode-editorBracketHighlight-foreground4: rgba(0, 0, 0, 0); + --vscode-editorBracketHighlight-foreground5: rgba(0, 0, 0, 0); + --vscode-editorBracketHighlight-foreground6: rgba(0, 0, 0, 0); + --vscode-editorBracketHighlight-unexpectedBracket.foreground: #ff3232; + --vscode-editorBracketMatch-background: rgba(0, 100, 0, 0.1); + --vscode-editorBracketMatch-border: #6fc3df; + --vscode-editorBracketPairGuide-activeBackground1: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-activeBackground2: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-activeBackground3: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-activeBackground4: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-activeBackground5: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-activeBackground6: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background1: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background2: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background3: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background4: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background5: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background6: rgba(0, 0, 0, 0); + --vscode-editorCodeLens-foreground: #999999; + --vscode-editorCommentsWidget-rangeActiveBackground: rgba(111, 195, 223, 0.1); + --vscode-editorCommentsWidget-rangeBackground: rgba(111, 195, 223, 0.1); + --vscode-editorCommentsWidget-replyInputBackground: #000000; + --vscode-editorCommentsWidget-resolvedBorder: #6fc3df; + --vscode-editorCommentsWidget-unresolvedBorder: #6fc3df; + --vscode-editorCursor-foreground: #ffffff; + --vscode-editorError-border: rgba(228, 119, 119, 0.8); + --vscode-editorError-foreground: #f48771; + --vscode-editorGhostText-border: rgba(255, 255, 255, 0.8); + --vscode-editorGroup-border: #6fc3df; + --vscode-editorGroup-dropIntoPromptBackground: #0c141f; + --vscode-editorGroup-dropIntoPromptBorder: #6fc3df; + --vscode-editorGroup-dropIntoPromptForeground: #ffffff; + --vscode-editorGroup-focusedEmptyBorder: #f38518; + --vscode-editorGroupHeader-border: #6fc3df; + --vscode-editorGroupHeader-noTabsBackground: #000000; + --vscode-editorGutter-addedBackground: #487e02; + --vscode-editorGutter-addedSecondaryBackground: #487e02; + --vscode-editorGutter-background: #000000; + --vscode-editorGutter-commentGlyphForeground: #000000; + --vscode-editorGutter-commentRangeForeground: #ffffff; + --vscode-editorGutter-commentUnresolvedGlyphForeground: #000000; + --vscode-editorGutter-deletedBackground: #f48771; + --vscode-editorGutter-deletedSecondaryBackground: #f48771; + --vscode-editorGutter-foldingControlForeground: #ffffff; + --vscode-editorGutter-itemBackground: #ffffff; + --vscode-editorGutter-itemGlyphForeground: #000000; + --vscode-editorGutter-modifiedBackground: #1b81a8; + --vscode-editorGutter-modifiedSecondaryBackground: #1b81a8; + --vscode-editorHint-border: rgba(238, 238, 238, 0.8); + --vscode-editorHoverWidget-background: #0c141f; + --vscode-editorHoverWidget-border: #6fc3df; + --vscode-editorHoverWidget-foreground: #ffffff; + --vscode-editorHoverWidget-highlightForeground: #f38518; + --vscode-editorHoverWidget-statusBarBackground: #0c141f; + --vscode-editorIndentGuide-activeBackground: #7c7c7c; + --vscode-editorIndentGuide-activeBackground1: #ffffff; + --vscode-editorIndentGuide-activeBackground2: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-activeBackground3: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-activeBackground4: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-activeBackground5: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-activeBackground6: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-background: #7c7c7c; + --vscode-editorIndentGuide-background1: #ffffff; + --vscode-editorIndentGuide-background2: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-background3: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-background4: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-background5: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-background6: rgba(0, 0, 0, 0); + --vscode-editorInfo-border: rgba(55, 148, 255, 0.8); + --vscode-editorInfo-foreground: #3794ff; + --vscode-editorInlayHint-background: rgba(255, 255, 255, 0.1); + --vscode-editorInlayHint-foreground: #ffffff; + --vscode-editorInlayHint-parameterBackground: rgba(255, 255, 255, 0.1); + --vscode-editorInlayHint-parameterForeground: #ffffff; + --vscode-editorInlayHint-typeBackground: rgba(255, 255, 255, 0.1); + --vscode-editorInlayHint-typeForeground: #ffffff; + --vscode-editorLightBulb-foreground: #ffcc00; + --vscode-editorLightBulbAi-foreground: #ffcc00; + --vscode-editorLightBulbAutoFix-foreground: #75beff; + --vscode-editorLineNumber-activeForeground: #f38518; + --vscode-editorLineNumber-foreground: #ffffff; + --vscode-editorLink-activeForeground: #00ffff; + --vscode-editorMarkerNavigation-background: #000000; + --vscode-editorMarkerNavigationError-background: #6fc3df; + --vscode-editorMarkerNavigationInfo-background: #6fc3df; + --vscode-editorMarkerNavigationWarning-background: #6fc3df; + --vscode-editorMarkerNavigationWarning-headerBackground: #0c141f; + --vscode-editorMultiCursor-primary.foreground: #ffffff; + --vscode-editorMultiCursor-secondary.foreground: #ffffff; + --vscode-editorOverviewRuler-addedForeground: rgba(72, 126, 2, 0.6); + --vscode-editorOverviewRuler-border: rgba(127, 127, 127, 0.3); + --vscode-editorOverviewRuler-bracketMatchForeground: #a0a0a0; + --vscode-editorOverviewRuler-commentForeground: #ffffff; + --vscode-editorOverviewRuler-commentUnresolvedForeground: #ffffff; + --vscode-editorOverviewRuler-commonContentForeground: #c3df6f; + --vscode-editorOverviewRuler-currentContentForeground: #c3df6f; + --vscode-editorOverviewRuler-deletedForeground: rgba(244, 135, 113, 0.6); + --vscode-editorOverviewRuler-errorForeground: #ff3232; + --vscode-editorOverviewRuler-findMatchForeground: #ab5a00; + --vscode-editorOverviewRuler-incomingContentForeground: #c3df6f; + --vscode-editorOverviewRuler-infoForeground: rgba(55, 148, 255, 0.8); + --vscode-editorOverviewRuler-modifiedForeground: rgba(27, 129, 168, 0.6); + --vscode-editorOverviewRuler-rangeHighlightForeground: rgba(0, 122, 204, 0.6); + --vscode-editorOverviewRuler-selectionHighlightForeground: rgba(160, 160, 160, 0.8); + --vscode-editorOverviewRuler-warningForeground: rgba(255, 204, 0, 0.8); + --vscode-editorOverviewRuler-wordHighlightForeground: rgba(160, 160, 160, 0.8); + --vscode-editorOverviewRuler-wordHighlightStrongForeground: rgba(192, 160, 192, 0.8); + --vscode-editorOverviewRuler-wordHighlightTextForeground: rgba(160, 160, 160, 0.8); + --vscode-editorPane-background: #000000; + --vscode-editorRuler-foreground: #ffffff; + --vscode-editorStickyScroll-background: #000000; + --vscode-editorStickyScroll-border: #6fc3df; + --vscode-editorSuggestWidget-background: #0c141f; + --vscode-editorSuggestWidget-border: #6fc3df; + --vscode-editorSuggestWidget-focusHighlightForeground: #f38518; + --vscode-editorSuggestWidget-foreground: #ffffff; + --vscode-editorSuggestWidget-highlightForeground: #f38518; + --vscode-editorSuggestWidgetStatus-foreground: rgba(255, 255, 255, 0.5); + --vscode-editorUnicodeHighlight-border: #ffd370; + --vscode-editorUnnecessaryCode-border: rgba(255, 255, 255, 0.8); + --vscode-editorWarning-border: rgba(255, 204, 0, 0.8); + --vscode-editorWarning-foreground: #ffd370; + --vscode-editorWatermark-foreground: #ffffff; + --vscode-editorWhitespace-foreground: #7c7c7c; + --vscode-editorWidget-background: #0c141f; + --vscode-editorWidget-border: #6fc3df; + --vscode-editorWidget-foreground: #ffffff; + --vscode-errorForeground: #f48771; + --vscode-extensionBadge-remoteBackground: #000000; + --vscode-extensionBadge-remoteForeground: #ffffff; + --vscode-extensionButton-separator: rgba(255, 255, 255, 0.4); + --vscode-extensionIcon-preReleaseForeground: #1d9271; + --vscode-extensionIcon-privateForeground: rgba(255, 255, 255, 0.38); + --vscode-extensionIcon-starForeground: #ff8e00; + --vscode-extensionIcon-verifiedForeground: #21a6ff; + --vscode-focusBorder: #f38518; + --vscode-font-size: 13px; + --vscode-font-weight: normal; + --vscode-foreground: #ffffff; + --vscode-gauge-background: #6fc3df; + --vscode-gauge-border: #6fc3df; + --vscode-gauge-errorBackground: #6fc3df; + --vscode-gauge-errorForeground: #ffffff; + --vscode-gauge-foreground: #ffffff; + --vscode-gauge-warningBackground: #6fc3df; + --vscode-gauge-warningForeground: #ffffff; + --vscode-git-blame.editorDecorationForeground: #ffffff; + --vscode-gitDecoration-addedResourceForeground: #a1e3ad; + --vscode-gitDecoration-conflictingResourceForeground: #c74e39; + --vscode-gitDecoration-deletedResourceForeground: #c74e39; + --vscode-gitDecoration-ignoredResourceForeground: #a7a8a9; + --vscode-gitDecoration-modifiedResourceForeground: #e2c08d; + --vscode-gitDecoration-renamedResourceForeground: #73c991; + --vscode-gitDecoration-stageDeletedResourceForeground: #c74e39; + --vscode-gitDecoration-stageModifiedResourceForeground: #e2c08d; + --vscode-gitDecoration-submoduleResourceForeground: #8db9e2; + --vscode-gitDecoration-untrackedResourceForeground: #73c991; + --vscode-icon-foreground: #ffffff; + --vscode-inlineChat-background: #0c141f; + --vscode-inlineChat-border: #6fc3df; + --vscode-inlineChat-foreground: #ffffff; + --vscode-inlineChatInput-background: #000000; + --vscode-inlineChatInput-border: #6fc3df; + --vscode-inlineChatInput-focusBorder: #f38518; + --vscode-inlineChatInput-placeholderForeground: rgba(255, 255, 255, 0.7); + --vscode-inlineEdit-gutterIndicator.primaryForeground: #ffffff; + --vscode-inlineEdit-gutterIndicator.secondaryForeground: #ffffff; + --vscode-inlineEdit-gutterIndicator.successfulForeground: #ffffff; + --vscode-input-background: #000000; + --vscode-input-border: #6fc3df; + --vscode-input-foreground: #ffffff; + --vscode-input-placeholderForeground: rgba(255, 255, 255, 0.7); + --vscode-inputOption-activeBackground: rgba(0, 0, 0, 0); + --vscode-inputOption-activeBorder: #6fc3df; + --vscode-inputOption-activeForeground: #ffffff; + --vscode-inputValidation-errorBackground: #000000; + --vscode-inputValidation-errorBorder: #6fc3df; + --vscode-inputValidation-infoBackground: #000000; + --vscode-inputValidation-infoBorder: #6fc3df; + --vscode-inputValidation-warningBackground: #000000; + --vscode-inputValidation-warningBorder: #6fc3df; + --vscode-interactive-activeCodeBorder: #6fc3df; + --vscode-interactive-inactiveCodeBorder: #6fc3df; + --vscode-keybindingLabel-background: rgba(0, 0, 0, 0); + --vscode-keybindingLabel-border: #6fc3df; + --vscode-keybindingLabel-bottomBorder: #6fc3df; + --vscode-keybindingLabel-foreground: #ffffff; + --vscode-list-deemphasizedForeground: #a7a8a9; + --vscode-list-filterMatchBorder: #6fc3df; + --vscode-list-focusHighlightForeground: #f38518; + --vscode-list-focusOutline: #f38518; + --vscode-list-highlightForeground: #f38518; + --vscode-list-hoverBackground: rgba(255, 255, 255, 0.1); + --vscode-list-invalidItemForeground: #b89500; + --vscode-listFilterWidget-background: #0c141f; + --vscode-listFilterWidget-noMatchesOutline: #6fc3df; + --vscode-listFilterWidget-outline: #f38518; + --vscode-menu-background: #000000; + --vscode-menu-border: #6fc3df; + --vscode-menu-foreground: #ffffff; + --vscode-menu-selectionBorder: #f38518; + --vscode-menu-separatorBackground: #6fc3df; + --vscode-menubar-selectionBorder: #f38518; + --vscode-menubar-selectionForeground: #ffffff; + --vscode-merge-border: #c3df6f; + --vscode-mergeEditor-change.background: rgba(155, 185, 85, 0.2); + --vscode-mergeEditor-change.word.background: rgba(156, 204, 44, 0.2); + --vscode-mergeEditor-changeBase.background: #4b1818; + --vscode-mergeEditor-changeBase.word.background: #6f1313; + --vscode-mergeEditor-conflict.handled.minimapOverViewRuler: rgba(173, 172, 168, 0.93); + --vscode-mergeEditor-conflict.handledFocused.border: rgba(193, 193, 193, 0.8); + --vscode-mergeEditor-conflict.handledUnfocused.border: rgba(134, 134, 134, 0.29); + --vscode-mergeEditor-conflict.unhandled.minimapOverViewRuler: #fcba03; + --vscode-mergeEditor-conflict.unhandledFocused.border: #ffa600; + --vscode-mergeEditor-conflict.unhandledUnfocused.border: rgba(255, 166, 0, 0.48); + --vscode-mergeEditor-conflictingLines.background: rgba(255, 234, 0, 0.28); + --vscode-minimap-chatEditHighlight: rgba(0, 0, 0, 0.6); + --vscode-minimap-errorHighlight: #ff3232; + --vscode-minimap-findMatchHighlight: #ab5a00; + --vscode-minimap-foregroundOpacity: #000000; + --vscode-minimap-infoHighlight: rgba(55, 148, 255, 0.8); + --vscode-minimap-selectionHighlight: #ffffff; + --vscode-minimap-selectionOccurrenceHighlight: #ffffff; + --vscode-minimap-warningHighlight: rgba(255, 204, 0, 0.8); + --vscode-minimapGutter-addedBackground: #487e02; + --vscode-minimapGutter-deletedBackground: #f48771; + --vscode-minimapGutter-modifiedBackground: #1b81a8; + --vscode-minimapSlider-activeBackground: rgba(111, 195, 223, 0.5); + --vscode-minimapSlider-background: rgba(111, 195, 223, 0.3); + --vscode-minimapSlider-hoverBackground: rgba(111, 195, 223, 0.4); + --vscode-multiDiffEditor-background: #000000; + --vscode-multiDiffEditor-border: #6fc3df; + --vscode-notebook-cellBorderColor: #6fc3df; + --vscode-notebook-cellInsertionIndicator: #f38518; + --vscode-notebook-cellStatusBarItemHoverBackground: rgba(255, 255, 255, 0.15); + --vscode-notebook-cellToolbarSeparator: #6fc3df; + --vscode-notebook-focusedCellBorder: #f38518; + --vscode-notebook-focusedEditorBorder: #f38518; + --vscode-notebook-inactiveFocusedCellBorder: #6fc3df; + --vscode-notebook-inactiveSelectedCellBorder: #f38518; + --vscode-notebook-selectedCellBorder: #6fc3df; + --vscode-notebookEditorOverviewRuler-runningCellForeground: #89d185; + --vscode-notebookScrollbarSlider-activeBackground: #6fc3df; + --vscode-notebookScrollbarSlider-background: rgba(111, 195, 223, 0.6); + --vscode-notebookScrollbarSlider-hoverBackground: rgba(111, 195, 223, 0.8); + --vscode-notebookStatusErrorIcon-foreground: #f48771; + --vscode-notebookStatusRunningIcon-foreground: #ffffff; + --vscode-notebookStatusSuccessIcon-foreground: #89d185; + --vscode-notificationCenter-border: #6fc3df; + --vscode-notificationCenterHeader-background: #0c141f; + --vscode-notificationLink-foreground: #21a6ff; + --vscode-notificationToast-border: #6fc3df; + --vscode-notifications-background: #0c141f; + --vscode-notifications-border: #0c141f; + --vscode-notifications-foreground: #ffffff; + --vscode-notificationsErrorIcon-foreground: #f48771; + --vscode-notificationsInfoIcon-foreground: #3794ff; + --vscode-notificationsWarningIcon-foreground: #ffd370; + --vscode-panel-background: #000000; + --vscode-panel-border: #6fc3df; + --vscode-panel-dropBorder: #ffffff; + --vscode-panelInput-border: #6fc3df; + --vscode-panelSection-border: #6fc3df; + --vscode-panelSectionHeader-border: #6fc3df; + --vscode-panelStickyScroll-background: #000000; + --vscode-panelTitle-activeBorder: #6fc3df; + --vscode-panelTitle-activeForeground: #ffffff; + --vscode-panelTitle-border: #6fc3df; + --vscode-panelTitle-inactiveForeground: #ffffff; + --vscode-panelTitleBadge-background: #000000; + --vscode-panelTitleBadge-foreground: #ffffff; + --vscode-peekView-border: #6fc3df; + --vscode-peekViewEditor-background: #000000; + --vscode-peekViewEditor-matchHighlightBorder: #f38518; + --vscode-peekViewEditorGutter-background: #000000; + --vscode-peekViewEditorStickyScroll-background: #000000; + --vscode-peekViewResult-background: #000000; + --vscode-peekViewResult-fileForeground: #ffffff; + --vscode-peekViewResult-lineForeground: #ffffff; + --vscode-peekViewResult-selectionForeground: #ffffff; + --vscode-peekViewTitle-background: #000000; + --vscode-peekViewTitleDescription-foreground: rgba(255, 255, 255, 0.6); + --vscode-peekViewTitleLabel-foreground: #ffffff; + --vscode-pickerGroup-border: #ffffff; + --vscode-pickerGroup-foreground: #ffffff; + --vscode-ports-iconRunningProcessForeground: #ffffff; + --vscode-problemsErrorIcon-foreground: #f48771; + --vscode-problemsInfoIcon-foreground: #3794ff; + --vscode-problemsWarningIcon-foreground: #ffd370; + --vscode-profileBadge-background: #ffffff; + --vscode-profileBadge-foreground: #000000; + --vscode-profiles-sashBorder: #6fc3df; + --vscode-progressBar-background: #6fc3df; + --vscode-prompt-frontMatter.background: #6fc3df; + --vscode-prompt-frontMatter.inactiveBackground: #6fc3df; + --vscode-quickInput-background: #0c141f; + --vscode-quickInput-foreground: #ffffff; + --vscode-quickInputTitle-background: #000000; + --vscode-radio-activeBackground: rgba(0, 0, 0, 0); + --vscode-radio-activeBorder: #6fc3df; + --vscode-radio-activeForeground: #ffffff; + --vscode-radio-inactiveBorder: rgba(255, 255, 255, 0.4); + --vscode-sash-hoverBorder: #f38518; + --vscode-scmGraph-foreground1: #ffb000; + --vscode-scmGraph-foreground2: #dc267f; + --vscode-scmGraph-foreground3: #994f00; + --vscode-scmGraph-foreground4: #40b0a6; + --vscode-scmGraph-foreground5: #b66dff; + --vscode-scmGraph-historyItemBaseRefColor: #ea5c00; + --vscode-scmGraph-historyItemHoverAdditionsForeground: #a1e3ad; + --vscode-scmGraph-historyItemHoverDefaultLabelBackground: #000000; + --vscode-scmGraph-historyItemHoverDefaultLabelForeground: #ffffff; + --vscode-scmGraph-historyItemHoverDeletionsForeground: #c74e39; + --vscode-scmGraph-historyItemHoverLabelForeground: #ffffff; + --vscode-scmGraph-historyItemRefColor: #3794ff; + --vscode-scmGraph-historyItemRemoteRefColor: #b180d7; + --vscode-scrollbarSlider-activeBackground: #6fc3df; + --vscode-scrollbarSlider-background: rgba(111, 195, 223, 0.6); + --vscode-scrollbarSlider-hoverBackground: rgba(111, 195, 223, 0.8); + --vscode-search-resultsInfoForeground: #ffffff; + --vscode-searchEditor-findMatchBorder: #f38518; + --vscode-searchEditor-textInputBorder: #6fc3df; + --vscode-selection-background: #008000; + --vscode-settings-checkboxBackground: #000000; + --vscode-settings-checkboxBorder: #6fc3df; + --vscode-settings-checkboxForeground: #ffffff; + --vscode-settings-dropdownBackground: #000000; + --vscode-settings-dropdownBorder: #6fc3df; + --vscode-settings-dropdownForeground: #ffffff; + --vscode-settings-dropdownListBorder: #6fc3df; + --vscode-settings-focusedRowBorder: #f38518; + --vscode-settings-headerBorder: #6fc3df; + --vscode-settings-headerForeground: #ffffff; + --vscode-settings-modifiedItemIndicator: #00497a; + --vscode-settings-numberInputBackground: #000000; + --vscode-settings-numberInputBorder: #6fc3df; + --vscode-settings-numberInputForeground: #ffffff; + --vscode-settings-sashBorder: #6fc3df; + --vscode-settings-settingsHeaderHoverForeground: rgba(255, 255, 255, 0.7); + --vscode-settings-textInputBackground: #000000; + --vscode-settings-textInputBorder: #6fc3df; + --vscode-settings-textInputForeground: #ffffff; + --vscode-sideBar-background: #000000; + --vscode-sideBar-border: #6fc3df; + --vscode-sideBarActivityBarTop-border: #6fc3df; + --vscode-sideBarSectionHeader-border: #6fc3df; + --vscode-sideBarStickyScroll-background: #000000; + --vscode-sideBarTitle-background: #000000; + --vscode-sideBarTitle-border: #6fc3df; + --vscode-sideBarTitle-foreground: #ffffff; + --vscode-sideBySideEditor-horizontalBorder: #6fc3df; + --vscode-sideBySideEditor-verticalBorder: #6fc3df; + --vscode-simpleFindWidget-sashBorder: #6fc3df; + --vscode-statusBar-border: #6fc3df; + --vscode-statusBar-debuggingBackground: #ba592c; + --vscode-statusBar-debuggingBorder: #6fc3df; + --vscode-statusBar-debuggingForeground: #ffffff; + --vscode-statusBar-foreground: #ffffff; + --vscode-statusBar-noFolderBorder: #6fc3df; + --vscode-statusBar-noFolderForeground: #ffffff; + --vscode-statusBarItem-activeBackground: rgba(255, 255, 255, 0.18); + --vscode-statusBarItem-compactHoverBackground: rgba(255, 255, 255, 0.2); + --vscode-statusBarItem-errorForeground: #ffffff; + --vscode-statusBarItem-errorHoverBackground: rgba(255, 255, 255, 0.12); + --vscode-statusBarItem-errorHoverForeground: #ffffff; + --vscode-statusBarItem-hoverBackground: rgba(255, 255, 255, 0.12); + --vscode-statusBarItem-hoverForeground: #ffffff; + --vscode-statusBarItem-offlineBackground: #6c1717; + --vscode-statusBarItem-offlineForeground: #ffffff; + --vscode-statusBarItem-offlineHoverBackground: rgba(255, 255, 255, 0.12); + --vscode-statusBarItem-offlineHoverForeground: #ffffff; + --vscode-statusBarItem-prominentBackground: rgba(0, 0, 0, 0.5); + --vscode-statusBarItem-prominentForeground: #ffffff; + --vscode-statusBarItem-prominentHoverBackground: rgba(255, 255, 255, 0.12); + --vscode-statusBarItem-prominentHoverForeground: #ffffff; + --vscode-statusBarItem-remoteBackground: rgba(0, 0, 0, 0); + --vscode-statusBarItem-remoteForeground: #ffffff; + --vscode-statusBarItem-remoteHoverBackground: rgba(255, 255, 255, 0.12); + --vscode-statusBarItem-remoteHoverForeground: #ffffff; + --vscode-statusBarItem-warningForeground: #ffffff; + --vscode-statusBarItem-warningHoverBackground: rgba(255, 255, 255, 0.12); + --vscode-statusBarItem-warningHoverForeground: #ffffff; + --vscode-symbolIcon-arrayForeground: #ffffff; + --vscode-symbolIcon-booleanForeground: #ffffff; + --vscode-symbolIcon-classForeground: #ee9d28; + --vscode-symbolIcon-colorForeground: #ffffff; + --vscode-symbolIcon-constantForeground: #ffffff; + --vscode-symbolIcon-constructorForeground: #b180d7; + --vscode-symbolIcon-enumeratorForeground: #ee9d28; + --vscode-symbolIcon-enumeratorMemberForeground: #75beff; + --vscode-symbolIcon-eventForeground: #ee9d28; + --vscode-symbolIcon-fieldForeground: #75beff; + --vscode-symbolIcon-fileForeground: #ffffff; + --vscode-symbolIcon-folderForeground: #ffffff; + --vscode-symbolIcon-functionForeground: #b180d7; + --vscode-symbolIcon-interfaceForeground: #75beff; + --vscode-symbolIcon-keyForeground: #ffffff; + --vscode-symbolIcon-keywordForeground: #ffffff; + --vscode-symbolIcon-methodForeground: #b180d7; + --vscode-symbolIcon-moduleForeground: #ffffff; + --vscode-symbolIcon-namespaceForeground: #ffffff; + --vscode-symbolIcon-nullForeground: #ffffff; + --vscode-symbolIcon-numberForeground: #ffffff; + --vscode-symbolIcon-objectForeground: #ffffff; + --vscode-symbolIcon-operatorForeground: #ffffff; + --vscode-symbolIcon-packageForeground: #ffffff; + --vscode-symbolIcon-propertyForeground: #ffffff; + --vscode-symbolIcon-referenceForeground: #ffffff; + --vscode-symbolIcon-snippetForeground: #ffffff; + --vscode-symbolIcon-stringForeground: #ffffff; + --vscode-symbolIcon-structForeground: #ffffff; + --vscode-symbolIcon-textForeground: #ffffff; + --vscode-symbolIcon-typeParameterForeground: #ffffff; + --vscode-symbolIcon-unitForeground: #ffffff; + --vscode-symbolIcon-variableForeground: #75beff; + --vscode-tab-activeBackground: #000000; + --vscode-tab-activeForeground: #ffffff; + --vscode-tab-border: #6fc3df; + --vscode-tab-dragAndDropBorder: #f38518; + --vscode-tab-inactiveForeground: #ffffff; + --vscode-tab-inactiveModifiedBorder: #ffffff; + --vscode-tab-lastPinnedBorder: #6fc3df; + --vscode-tab-selectedBackground: #000000; + --vscode-tab-selectedForeground: #ffffff; + --vscode-tab-unfocusedActiveBackground: #000000; + --vscode-tab-unfocusedActiveForeground: #ffffff; + --vscode-tab-unfocusedActiveModifiedBorder: #ffffff; + --vscode-tab-unfocusedInactiveForeground: #ffffff; + --vscode-tab-unfocusedInactiveModifiedBorder: #ffffff; + --vscode-terminal-ansiBlack: #000000; + --vscode-terminal-ansiBlue: #0000ee; + --vscode-terminal-ansiBrightBlack: #7f7f7f; + --vscode-terminal-ansiBrightBlue: #5c5cff; + --vscode-terminal-ansiBrightCyan: #00ffff; + --vscode-terminal-ansiBrightGreen: #00ff00; + --vscode-terminal-ansiBrightMagenta: #ff00ff; + --vscode-terminal-ansiBrightRed: #ff0000; + --vscode-terminal-ansiBrightWhite: #ffffff; + --vscode-terminal-ansiBrightYellow: #ffff00; + --vscode-terminal-ansiCyan: #00cdcd; + --vscode-terminal-ansiGreen: #00cd00; + --vscode-terminal-ansiMagenta: #cd00cd; + --vscode-terminal-ansiRed: #cd0000; + --vscode-terminal-ansiWhite: #e5e5e5; + --vscode-terminal-ansiYellow: #cdcd00; + --vscode-terminal-border: #6fc3df; + --vscode-terminal-findMatchBorder: #f38518; + --vscode-terminal-findMatchHighlightBorder: #f38518; + --vscode-terminal-foreground: #ffffff; + --vscode-terminal-hoverHighlightBackground: rgba(173, 214, 255, 0.07); + --vscode-terminal-inactiveSelectionBackground: rgba(255, 255, 255, 0.7); + --vscode-terminal-selectionBackground: #ffffff; + --vscode-terminal-selectionForeground: #000000; + --vscode-terminalCommandDecoration-defaultBackground: rgba(255, 255, 255, 0.5); + --vscode-terminalCommandDecoration-errorBackground: #f14c4c; + --vscode-terminalCommandDecoration-successBackground: #1b81a8; + --vscode-terminalCommandGuide-foreground: #6fc3df; + --vscode-terminalOverviewRuler-border: rgba(127, 127, 127, 0.3); + --vscode-terminalOverviewRuler-cursorForeground: rgba(160, 160, 160, 0.8); + --vscode-terminalOverviewRuler-findMatchForeground: #f38518; + --vscode-terminalStickyScroll-border: #6fc3df; + --vscode-terminalStickyScrollHover-background: #e48b39; + --vscode-terminalSymbolIcon-aliasForeground: #b180d7; + --vscode-terminalSymbolIcon-argumentForeground: #75beff; + --vscode-terminalSymbolIcon-fileForeground: #ffffff; + --vscode-terminalSymbolIcon-flagForeground: #ee9d28; + --vscode-terminalSymbolIcon-folderForeground: #ffffff; + --vscode-terminalSymbolIcon-methodForeground: #b180d7; + --vscode-terminalSymbolIcon-optionForeground: #ee9d28; + --vscode-terminalSymbolIcon-optionValueForeground: #75beff; + --vscode-testing-coverCountBadgeBackground: #000000; + --vscode-testing-coverCountBadgeForeground: #ffffff; + --vscode-testing-coveredBorder: #6fc3df; + --vscode-testing-coveredGutterBackground: #89d185; + --vscode-testing-iconErrored: #f14c4c; + --vscode-testing-iconErrored.retired: rgba(241, 76, 76, 0.7); + --vscode-testing-iconFailed: #f14c4c; + --vscode-testing-iconFailed.retired: rgba(241, 76, 76, 0.7); + --vscode-testing-iconPassed: #73c991; + --vscode-testing-iconPassed.retired: rgba(115, 201, 145, 0.7); + --vscode-testing-iconQueued: #cca700; + --vscode-testing-iconQueued.retired: rgba(204, 167, 0, 0.7); + --vscode-testing-iconSkipped: #848484; + --vscode-testing-iconSkipped.retired: rgba(132, 132, 132, 0.7); + --vscode-testing-iconUnset: #848484; + --vscode-testing-iconUnset.retired: rgba(132, 132, 132, 0.7); + --vscode-testing-message.info.decorationForeground: rgba(255, 255, 255, 0.5); + --vscode-testing-messagePeekBorder: #6fc3df; + --vscode-testing-peekBorder: #6fc3df; + --vscode-testing-runAction: #73c991; + --vscode-testing-uncoveredBorder: #6fc3df; + --vscode-testing-uncoveredGutterBackground: #f48771; + --vscode-textBlockQuote-border: #ffffff; + --vscode-textCodeBlock-background: #000000; + --vscode-textLink-activeForeground: #21a6ff; + --vscode-textLink-foreground: #21a6ff; + --vscode-textPreformat-background: #ffffff; + --vscode-textPreformat-foreground: #000000; + --vscode-textSeparator-foreground: #000000; + --vscode-titleBar-activeBackground: #000000; + --vscode-titleBar-activeForeground: #ffffff; + --vscode-titleBar-border: #6fc3df; + --vscode-toolbar-hoverOutline: #f38518; + --vscode-tree-inactiveIndentGuidesStroke: rgba(169, 169, 169, 0.4); + --vscode-tree-indentGuidesStroke: #a9a9a9; + --vscode-welcomePage-progress.background: #000000; + --vscode-welcomePage-progress.foreground: #21a6ff; + --vscode-welcomePage-tileBackground: #000000; + --vscode-welcomePage-tileBorder: #6fc3df; + --vscode-widget-border: #6fc3df; + --vscode-window-activeBorder: #6fc3df; + --vscode-window-inactiveBorder: #6fc3df; +} diff --git a/webview-ui/playwright/themes/vscode-theme-light.css b/webview-ui/playwright/themes/vscode-theme-light.css new file mode 100644 index 0000000000..2b0fcd4157 --- /dev/null +++ b/webview-ui/playwright/themes/vscode-theme-light.css @@ -0,0 +1,780 @@ +/* Generated from Default Light Modern by VS Code 1.100.0. Do not edit manually. */ +.vscode-light { + color-scheme: light; + --vscode-actionBar-toggledBackground: #dddddd; + --vscode-activityBar-activeBorder: #005fb8; + --vscode-activityBar-background: #f8f8f8; + --vscode-activityBar-border: #e5e5e5; + --vscode-activityBar-dropBorder: #1f1f1f; + --vscode-activityBar-foreground: #1f1f1f; + --vscode-activityBar-inactiveForeground: #616161; + --vscode-activityBarBadge-background: #005fb8; + --vscode-activityBarBadge-foreground: #ffffff; + --vscode-activityBarTop-activeBorder: #424242; + --vscode-activityBarTop-dropBorder: #424242; + --vscode-activityBarTop-foreground: #424242; + --vscode-activityBarTop-inactiveForeground: rgba(66, 66, 66, 0.75); + --vscode-activityErrorBadge-background: #e51400; + --vscode-activityErrorBadge-foreground: #ffffff; + --vscode-activityWarningBadge-background: #bf8803; + --vscode-activityWarningBadge-foreground: #ffffff; + --vscode-badge-background: #cccccc; + --vscode-badge-foreground: #3b3b3b; + --vscode-banner-background: #a2a2a2; + --vscode-banner-foreground: #000000; + --vscode-banner-iconForeground: #1a85ff; + --vscode-breadcrumb-activeSelectionForeground: #2f2f2f; + --vscode-breadcrumb-background: #ffffff; + --vscode-breadcrumb-focusForeground: #2f2f2f; + --vscode-breadcrumb-foreground: rgba(59, 59, 59, 0.8); + --vscode-breadcrumbPicker-background: #f8f8f8; + --vscode-button-background: #005fb8; + --vscode-button-border: rgba(0, 0, 0, 0.1); + --vscode-button-foreground: #ffffff; + --vscode-button-hoverBackground: #0258a8; + --vscode-button-secondaryBackground: #e5e5e5; + --vscode-button-secondaryForeground: #3b3b3b; + --vscode-button-secondaryHoverBackground: #cccccc; + --vscode-button-separator: rgba(255, 255, 255, 0.4); + --vscode-chart-axis: rgba(0, 0, 0, 0.6); + --vscode-chart-guide: rgba(0, 0, 0, 0.2); + --vscode-chart-line: #236b8e; + --vscode-charts-blue: #1a85ff; + --vscode-charts-foreground: #3b3b3b; + --vscode-charts-green: #388a34; + --vscode-charts-lines: rgba(59, 59, 59, 0.5); + --vscode-charts-orange: #d18616; + --vscode-charts-purple: #652d90; + --vscode-charts-red: #e51400; + --vscode-charts-yellow: #bf8803; + --vscode-chat-avatarBackground: #f2f2f2; + --vscode-chat-avatarForeground: #3b3b3b; + --vscode-chat-editedFileForeground: #895503; + --vscode-chat-requestBackground: rgba(255, 255, 255, 0.62); + --vscode-chat-requestBorder: rgba(0, 0, 0, 0.1); + --vscode-chat-slashCommandBackground: #d2ecff; + --vscode-chat-slashCommandForeground: #306ca2; + --vscode-checkbox-background: #f8f8f8; + --vscode-checkbox-border: #cecece; + --vscode-checkbox-disabled.background: #b9b9b9; + --vscode-checkbox-disabled.foreground: #797979; + --vscode-checkbox-foreground: #3b3b3b; + --vscode-checkbox-selectBackground: #f8f8f8; + --vscode-checkbox-selectBorder: #3b3b3b; + --vscode-commandCenter-activeBackground: rgba(0, 0, 0, 0.08); + --vscode-commandCenter-activeBorder: rgba(30, 30, 30, 0.3); + --vscode-commandCenter-activeForeground: #1e1e1e; + --vscode-commandCenter-background: rgba(0, 0, 0, 0.05); + --vscode-commandCenter-border: rgba(30, 30, 30, 0.2); + --vscode-commandCenter-debuggingBackground: rgba(253, 113, 108, 0.26); + --vscode-commandCenter-foreground: #1e1e1e; + --vscode-commandCenter-inactiveBorder: rgba(139, 148, 158, 0.25); + --vscode-commandCenter-inactiveForeground: #8b949e; + --vscode-commentsView-resolvedIcon: rgba(97, 97, 97, 0.5); + --vscode-commentsView-unresolvedIcon: #005fb8; + --vscode-debugConsole-errorForeground: #f85149; + --vscode-debugConsole-infoForeground: #1a85ff; + --vscode-debugConsole-sourceForeground: #3b3b3b; + --vscode-debugConsole-warningForeground: #bf8803; + --vscode-debugConsoleInputIcon-foreground: #3b3b3b; + --vscode-debugExceptionWidget-background: #f1dfde; + --vscode-debugExceptionWidget-border: #a31515; + --vscode-debugIcon-breakpointCurrentStackframeForeground: #be8700; + --vscode-debugIcon-breakpointDisabledForeground: #848484; + --vscode-debugIcon-breakpointForeground: #e51400; + --vscode-debugIcon-breakpointStackframeForeground: #89d185; + --vscode-debugIcon-breakpointUnverifiedForeground: #848484; + --vscode-debugIcon-continueForeground: #007acc; + --vscode-debugIcon-disconnectForeground: #a1260d; + --vscode-debugIcon-pauseForeground: #007acc; + --vscode-debugIcon-restartForeground: #388a34; + --vscode-debugIcon-startForeground: #388a34; + --vscode-debugIcon-stepBackForeground: #007acc; + --vscode-debugIcon-stepIntoForeground: #007acc; + --vscode-debugIcon-stepOutForeground: #007acc; + --vscode-debugIcon-stepOverForeground: #007acc; + --vscode-debugIcon-stopForeground: #a1260d; + --vscode-debugTokenExpression-boolean: #0000ff; + --vscode-debugTokenExpression-error: #e51400; + --vscode-debugTokenExpression-name: #9b46b0; + --vscode-debugTokenExpression-number: #098658; + --vscode-debugTokenExpression-string: #a31515; + --vscode-debugTokenExpression-type: #4a90e2; + --vscode-debugTokenExpression-value: rgba(108, 108, 108, 0.8); + --vscode-debugToolBar-background: #f3f3f3; + --vscode-debugView-exceptionLabelBackground: #a31515; + --vscode-debugView-exceptionLabelForeground: #ffffff; + --vscode-debugView-stateLabelBackground: rgba(136, 136, 136, 0.27); + --vscode-debugView-stateLabelForeground: #3b3b3b; + --vscode-debugView-valueChangedHighlight: #569cd6; + --vscode-descriptionForeground: #3b3b3b; + --vscode-diffEditor-diagonalFill: rgba(34, 34, 34, 0.2); + --vscode-diffEditor-insertedLineBackground: rgba(155, 185, 85, 0.2); + --vscode-diffEditor-insertedTextBackground: rgba(156, 204, 44, 0.25); + --vscode-diffEditor-move.border: rgba(139, 139, 139, 0.61); + --vscode-diffEditor-moveActive.border: #ffa500; + --vscode-diffEditor-removedLineBackground: rgba(255, 0, 0, 0.2); + --vscode-diffEditor-removedTextBackground: rgba(255, 0, 0, 0.2); + --vscode-diffEditor-unchangedCodeBackground: rgba(184, 184, 184, 0.16); + --vscode-diffEditor-unchangedRegionBackground: #f8f8f8; + --vscode-diffEditor-unchangedRegionForeground: #3b3b3b; + --vscode-diffEditor-unchangedRegionShadow: rgba(115, 115, 115, 0.75); + --vscode-disabledForeground: rgba(97, 97, 97, 0.5); + --vscode-dropdown-background: #ffffff; + --vscode-dropdown-border: #cecece; + --vscode-dropdown-foreground: #3b3b3b; + --vscode-dropdown-listBackground: #ffffff; + --vscode-editor-background: #ffffff; + --vscode-editor-compositionBorder: #000000; + --vscode-editor-findMatchBackground: #a8ac94; + --vscode-editor-findMatchHighlightBackground: rgba(234, 92, 0, 0.33); + --vscode-editor-findRangeHighlightBackground: rgba(180, 180, 180, 0.3); + --vscode-editor-focusedStackFrameHighlightBackground: rgba(206, 231, 206, 0.45); + --vscode-editor-foldBackground: rgba(173, 214, 255, 0.3); + --vscode-editor-foldPlaceholderForeground: #808080; + --vscode-editor-font-size: 14px; + --vscode-editor-font-weight: normal; + --vscode-editor-foreground: #3b3b3b; + --vscode-editor-hoverHighlightBackground: rgba(173, 214, 255, 0.15); + --vscode-editor-inactiveSelectionBackground: #e5ebf1; + --vscode-editor-inlineValuesBackground: rgba(255, 200, 0, 0.2); + --vscode-editor-inlineValuesForeground: rgba(0, 0, 0, 0.5); + --vscode-editor-lineHighlightBorder: #eeeeee; + --vscode-editor-linkedEditingBackground: rgba(255, 0, 0, 0.3); + --vscode-editor-placeholder.foreground: rgba(0, 0, 0, 0.47); + --vscode-editor-rangeHighlightBackground: rgba(253, 255, 0, 0.2); + --vscode-editor-selectionBackground: #add6ff; + --vscode-editor-selectionHighlightBackground: rgba(173, 214, 255, 0.5); + --vscode-editor-snippetFinalTabstopHighlightBorder: rgba(10, 50, 100, 0.5); + --vscode-editor-snippetTabstopHighlightBackground: rgba(10, 50, 100, 0.2); + --vscode-editor-stackFrameHighlightBackground: rgba(255, 255, 102, 0.45); + --vscode-editor-symbolHighlightBackground: rgba(234, 92, 0, 0.33); + --vscode-editor-wordHighlightBackground: rgba(87, 87, 87, 0.25); + --vscode-editor-wordHighlightStrongBackground: rgba(14, 99, 156, 0.25); + --vscode-editor-wordHighlightTextBackground: rgba(87, 87, 87, 0.25); + --vscode-editorActionList-background: #f8f8f8; + --vscode-editorActionList-focusBackground: #e8e8e8; + --vscode-editorActionList-focusForeground: #000000; + --vscode-editorActionList-foreground: #3b3b3b; + --vscode-editorActiveLineNumber-foreground: #0b216f; + --vscode-editorBracketHighlight-foreground1: #0431fa; + --vscode-editorBracketHighlight-foreground2: #319331; + --vscode-editorBracketHighlight-foreground3: #7b3814; + --vscode-editorBracketHighlight-foreground4: rgba(0, 0, 0, 0); + --vscode-editorBracketHighlight-foreground5: rgba(0, 0, 0, 0); + --vscode-editorBracketHighlight-foreground6: rgba(0, 0, 0, 0); + --vscode-editorBracketHighlight-unexpectedBracket.foreground: rgba(255, 18, 18, 0.8); + --vscode-editorBracketMatch-background: rgba(0, 100, 0, 0.1); + --vscode-editorBracketMatch-border: #b9b9b9; + --vscode-editorBracketPairGuide-activeBackground1: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-activeBackground2: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-activeBackground3: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-activeBackground4: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-activeBackground5: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-activeBackground6: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background1: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background2: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background3: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background4: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background5: rgba(0, 0, 0, 0); + --vscode-editorBracketPairGuide-background6: rgba(0, 0, 0, 0); + --vscode-editorCodeLens-foreground: #919191; + --vscode-editorCommentsWidget-rangeActiveBackground: rgba(0, 95, 184, 0.1); + --vscode-editorCommentsWidget-rangeBackground: rgba(0, 95, 184, 0.1); + --vscode-editorCommentsWidget-replyInputBackground: #f3f3f3; + --vscode-editorCommentsWidget-resolvedBorder: rgba(97, 97, 97, 0.5); + --vscode-editorCommentsWidget-unresolvedBorder: #005fb8; + --vscode-editorCursor-foreground: #000000; + --vscode-editorError-foreground: #e51400; + --vscode-editorGhostText-foreground: rgba(0, 0, 0, 0.47); + --vscode-editorGroup-border: #e5e5e5; + --vscode-editorGroup-dropBackground: rgba(38, 119, 203, 0.18); + --vscode-editorGroup-dropIntoPromptBackground: #f8f8f8; + --vscode-editorGroup-dropIntoPromptForeground: #3b3b3b; + --vscode-editorGroupHeader-noTabsBackground: #ffffff; + --vscode-editorGroupHeader-tabsBackground: #f8f8f8; + --vscode-editorGroupHeader-tabsBorder: #e5e5e5; + --vscode-editorGutter-addedBackground: #2ea043; + --vscode-editorGutter-addedSecondaryBackground: #83db93; + --vscode-editorGutter-background: #ffffff; + --vscode-editorGutter-commentGlyphForeground: #3b3b3b; + --vscode-editorGutter-commentRangeForeground: #d5d8e9; + --vscode-editorGutter-commentUnresolvedGlyphForeground: #3b3b3b; + --vscode-editorGutter-deletedBackground: #f85149; + --vscode-editorGutter-deletedSecondaryBackground: #fcaaa6; + --vscode-editorGutter-foldingControlForeground: #3b3b3b; + --vscode-editorGutter-itemBackground: #d5d8e9; + --vscode-editorGutter-itemGlyphForeground: #3b3b3b; + --vscode-editorGutter-modifiedBackground: #005fb8; + --vscode-editorGutter-modifiedSecondaryBackground: #3aa0ff; + --vscode-editorHint-foreground: #6c6c6c; + --vscode-editorHoverWidget-background: #f8f8f8; + --vscode-editorHoverWidget-border: #c8c8c8; + --vscode-editorHoverWidget-foreground: #3b3b3b; + --vscode-editorHoverWidget-highlightForeground: #0066bf; + --vscode-editorHoverWidget-statusBarBackground: #ececec; + --vscode-editorIndentGuide-activeBackground: rgba(51, 51, 51, 0.2); + --vscode-editorIndentGuide-activeBackground1: #939393; + --vscode-editorIndentGuide-activeBackground2: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-activeBackground3: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-activeBackground4: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-activeBackground5: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-activeBackground6: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-background: rgba(51, 51, 51, 0.2); + --vscode-editorIndentGuide-background1: #d3d3d3; + --vscode-editorIndentGuide-background2: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-background3: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-background4: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-background5: rgba(0, 0, 0, 0); + --vscode-editorIndentGuide-background6: rgba(0, 0, 0, 0); + --vscode-editorInfo-foreground: #1a85ff; + --vscode-editorInlayHint-background: rgba(204, 204, 204, 0.1); + --vscode-editorInlayHint-foreground: #969696; + --vscode-editorInlayHint-parameterBackground: rgba(204, 204, 204, 0.1); + --vscode-editorInlayHint-parameterForeground: #969696; + --vscode-editorInlayHint-typeBackground: rgba(204, 204, 204, 0.1); + --vscode-editorInlayHint-typeForeground: #969696; + --vscode-editorLightBulb-foreground: #ddb100; + --vscode-editorLightBulbAi-foreground: #ddb100; + --vscode-editorLightBulbAutoFix-foreground: #007acc; + --vscode-editorLineNumber-activeForeground: #171184; + --vscode-editorLineNumber-foreground: #6e7681; + --vscode-editorLink-activeForeground: #0000ff; + --vscode-editorMarkerNavigation-background: #ffffff; + --vscode-editorMarkerNavigationError-background: #e51400; + --vscode-editorMarkerNavigationError-headerBackground: rgba(229, 20, 0, 0.1); + --vscode-editorMarkerNavigationInfo-background: #1a85ff; + --vscode-editorMarkerNavigationInfo-headerBackground: rgba(26, 133, 255, 0.1); + --vscode-editorMarkerNavigationWarning-background: #bf8803; + --vscode-editorMarkerNavigationWarning-headerBackground: rgba(191, 136, 3, 0.1); + --vscode-editorMinimap-inlineChatInserted: rgba(156, 204, 44, 0.2); + --vscode-editorMultiCursor-primary.foreground: #000000; + --vscode-editorMultiCursor-secondary.foreground: #000000; + --vscode-editorOverviewRuler-addedForeground: rgba(46, 160, 67, 0.6); + --vscode-editorOverviewRuler-border: #e5e5e5; + --vscode-editorOverviewRuler-bracketMatchForeground: #a0a0a0; + --vscode-editorOverviewRuler-commentForeground: #d5d8e9; + --vscode-editorOverviewRuler-commentUnresolvedForeground: #d5d8e9; + --vscode-editorOverviewRuler-commonContentForeground: rgba(96, 96, 96, 0.4); + --vscode-editorOverviewRuler-currentContentForeground: rgba(64, 200, 174, 0.5); + --vscode-editorOverviewRuler-deletedForeground: rgba(248, 81, 73, 0.6); + --vscode-editorOverviewRuler-errorForeground: rgba(255, 18, 18, 0.7); + --vscode-editorOverviewRuler-findMatchForeground: rgba(209, 134, 22, 0.49); + --vscode-editorOverviewRuler-incomingContentForeground: rgba(64, 166, 255, 0.5); + --vscode-editorOverviewRuler-infoForeground: #1a85ff; + --vscode-editorOverviewRuler-inlineChatInserted: rgba(156, 204, 44, 0.2); + --vscode-editorOverviewRuler-inlineChatRemoved: rgba(255, 0, 0, 0.16); + --vscode-editorOverviewRuler-modifiedForeground: rgba(0, 95, 184, 0.6); + --vscode-editorOverviewRuler-rangeHighlightForeground: rgba(0, 122, 204, 0.6); + --vscode-editorOverviewRuler-selectionHighlightForeground: rgba(160, 160, 160, 0.8); + --vscode-editorOverviewRuler-warningForeground: #bf8803; + --vscode-editorOverviewRuler-wordHighlightForeground: rgba(160, 160, 160, 0.8); + --vscode-editorOverviewRuler-wordHighlightStrongForeground: rgba(192, 160, 192, 0.8); + --vscode-editorOverviewRuler-wordHighlightTextForeground: rgba(160, 160, 160, 0.8); + --vscode-editorPane-background: #ffffff; + --vscode-editorRuler-foreground: #d3d3d3; + --vscode-editorStickyScroll-background: #ffffff; + --vscode-editorStickyScroll-shadow: #dddddd; + --vscode-editorStickyScrollHover-background: #f0f0f0; + --vscode-editorSuggestWidget-background: #f8f8f8; + --vscode-editorSuggestWidget-border: #c8c8c8; + --vscode-editorSuggestWidget-focusHighlightForeground: #0066bf; + --vscode-editorSuggestWidget-foreground: #3b3b3b; + --vscode-editorSuggestWidget-highlightForeground: #0066bf; + --vscode-editorSuggestWidget-selectedBackground: #e8e8e8; + --vscode-editorSuggestWidget-selectedForeground: #000000; + --vscode-editorSuggestWidget-selectedIconForeground: #000000; + --vscode-editorSuggestWidgetStatus-foreground: rgba(59, 59, 59, 0.5); + --vscode-editorUnicodeHighlight-border: #bf8803; + --vscode-editorUnnecessaryCode-opacity: rgba(0, 0, 0, 0.47); + --vscode-editorWarning-foreground: #bf8803; + --vscode-editorWatermark-foreground: rgba(59, 59, 59, 0.68); + --vscode-editorWhitespace-foreground: rgba(51, 51, 51, 0.2); + --vscode-editorWidget-background: #f8f8f8; + --vscode-editorWidget-border: #c8c8c8; + --vscode-editorWidget-foreground: #3b3b3b; + --vscode-errorForeground: #f85149; + --vscode-extensionBadge-remoteBackground: #005fb8; + --vscode-extensionBadge-remoteForeground: #ffffff; + --vscode-extensionButton-background: #005fb8; + --vscode-extensionButton-foreground: #ffffff; + --vscode-extensionButton-hoverBackground: #0258a8; + --vscode-extensionButton-prominentBackground: #005fb8; + --vscode-extensionButton-prominentForeground: #ffffff; + --vscode-extensionButton-prominentHoverBackground: #0258a8; + --vscode-extensionButton-separator: rgba(255, 255, 255, 0.4); + --vscode-extensionIcon-preReleaseForeground: #1d9271; + --vscode-extensionIcon-privateForeground: rgba(0, 0, 0, 0.38); + --vscode-extensionIcon-sponsorForeground: #b51e78; + --vscode-extensionIcon-starForeground: #df6100; + --vscode-extensionIcon-verifiedForeground: #005fb8; + --vscode-focusBorder: #005fb8; + --vscode-font-size: 13px; + --vscode-font-weight: normal; + --vscode-foreground: #3b3b3b; + --vscode-gauge-background: #007acc; + --vscode-gauge-errorBackground: #be1100; + --vscode-gauge-errorForeground: rgba(190, 17, 0, 0.3); + --vscode-gauge-foreground: rgba(0, 122, 204, 0.3); + --vscode-gauge-warningBackground: #b89500; + --vscode-gauge-warningForeground: rgba(184, 149, 0, 0.3); + --vscode-git-blame.editorDecorationForeground: #969696; + --vscode-gitDecoration-addedResourceForeground: #587c0c; + --vscode-gitDecoration-conflictingResourceForeground: #ad0707; + --vscode-gitDecoration-deletedResourceForeground: #ad0707; + --vscode-gitDecoration-ignoredResourceForeground: #8e8e90; + --vscode-gitDecoration-modifiedResourceForeground: #895503; + --vscode-gitDecoration-renamedResourceForeground: #007100; + --vscode-gitDecoration-stageDeletedResourceForeground: #ad0707; + --vscode-gitDecoration-stageModifiedResourceForeground: #895503; + --vscode-gitDecoration-submoduleResourceForeground: #1258a7; + --vscode-gitDecoration-untrackedResourceForeground: #007100; + --vscode-icon-foreground: #3b3b3b; + --vscode-inlineChat-background: #f8f8f8; + --vscode-inlineChat-border: #c8c8c8; + --vscode-inlineChat-foreground: #3b3b3b; + --vscode-inlineChat-shadow: rgba(0, 0, 0, 0.16); + --vscode-inlineChatDiff-inserted: rgba(156, 204, 44, 0.13); + --vscode-inlineChatDiff-removed: rgba(255, 0, 0, 0.1); + --vscode-inlineChatInput-background: #ffffff; + --vscode-inlineChatInput-border: #c8c8c8; + --vscode-inlineChatInput-focusBorder: #005fb8; + --vscode-inlineChatInput-placeholderForeground: #767676; + --vscode-inlineEdit-gutterIndicator.background: rgba(95, 95, 95, 0.09); + --vscode-inlineEdit-gutterIndicator.primaryBackground: rgba(0, 95, 184, 0.5); + --vscode-inlineEdit-gutterIndicator.primaryBorder: #005fb8; + --vscode-inlineEdit-gutterIndicator.primaryForeground: #ffffff; + --vscode-inlineEdit-gutterIndicator.secondaryBackground: #e5e5e5; + --vscode-inlineEdit-gutterIndicator.secondaryBorder: #e5e5e5; + --vscode-inlineEdit-gutterIndicator.secondaryForeground: #3b3b3b; + --vscode-inlineEdit-gutterIndicator.successfulBackground: #005fb8; + --vscode-inlineEdit-gutterIndicator.successfulBorder: #005fb8; + --vscode-inlineEdit-gutterIndicator.successfulForeground: #ffffff; + --vscode-inlineEdit-modifiedBackground: rgba(156, 204, 44, 0.07); + --vscode-inlineEdit-modifiedBorder: rgba(62, 81, 18, 0.25); + --vscode-inlineEdit-modifiedChangedLineBackground: rgba(155, 185, 85, 0.14); + --vscode-inlineEdit-modifiedChangedTextBackground: rgba(156, 204, 44, 0.18); + --vscode-inlineEdit-originalBackground: rgba(255, 0, 0, 0.04); + --vscode-inlineEdit-originalBorder: rgba(255, 0, 0, 0.2); + --vscode-inlineEdit-originalChangedLineBackground: rgba(255, 0, 0, 0.16); + --vscode-inlineEdit-originalChangedTextBackground: rgba(255, 0, 0, 0.16); + --vscode-inlineEdit-tabWillAcceptModifiedBorder: rgba(62, 81, 18, 0.25); + --vscode-inlineEdit-tabWillAcceptOriginalBorder: rgba(255, 0, 0, 0.2); + --vscode-input-background: #ffffff; + --vscode-input-border: #cecece; + --vscode-input-foreground: #3b3b3b; + --vscode-input-placeholderForeground: #767676; + --vscode-inputOption-activeBackground: #bed6ed; + --vscode-inputOption-activeBorder: #005fb8; + --vscode-inputOption-activeForeground: #000000; + --vscode-inputOption-hoverBackground: rgba(184, 184, 184, 0.31); + --vscode-inputValidation-errorBackground: #f2dede; + --vscode-inputValidation-errorBorder: #be1100; + --vscode-inputValidation-infoBackground: #d6ecf2; + --vscode-inputValidation-infoBorder: #007acc; + --vscode-inputValidation-warningBackground: #f6f5d2; + --vscode-inputValidation-warningBorder: #b89500; + --vscode-interactive-activeCodeBorder: #007acc; + --vscode-interactive-inactiveCodeBorder: #e4e6f1; + --vscode-keybindingLabel-background: rgba(221, 221, 221, 0.4); + --vscode-keybindingLabel-border: rgba(204, 204, 204, 0.4); + --vscode-keybindingLabel-bottomBorder: rgba(187, 187, 187, 0.4); + --vscode-keybindingLabel-foreground: #3b3b3b; + --vscode-keybindingTable-headerBackground: rgba(59, 59, 59, 0.04); + --vscode-keybindingTable-rowsBackground: rgba(59, 59, 59, 0.04); + --vscode-list-activeSelectionBackground: #e8e8e8; + --vscode-list-activeSelectionForeground: #000000; + --vscode-list-activeSelectionIconForeground: #000000; + --vscode-list-deemphasizedForeground: #8e8e90; + --vscode-list-dropBackground: #d6ebff; + --vscode-list-dropBetweenBackground: #3b3b3b; + --vscode-list-errorForeground: #b01011; + --vscode-list-filterMatchBackground: rgba(234, 92, 0, 0.33); + --vscode-list-focusAndSelectionOutline: #005fb8; + --vscode-list-focusHighlightForeground: #0066bf; + --vscode-list-focusOutline: #005fb8; + --vscode-list-highlightForeground: #0066bf; + --vscode-list-hoverBackground: #f2f2f2; + --vscode-list-inactiveSelectionBackground: #e4e6f1; + --vscode-list-invalidItemForeground: #b89500; + --vscode-list-warningForeground: #855f00; + --vscode-listFilterWidget-background: #f8f8f8; + --vscode-listFilterWidget-noMatchesOutline: #be1100; + --vscode-listFilterWidget-outline: rgba(0, 0, 0, 0); + --vscode-listFilterWidget-shadow: rgba(0, 0, 0, 0.16); + --vscode-menu-background: #ffffff; + --vscode-menu-border: #cecece; + --vscode-menu-foreground: #3b3b3b; + --vscode-menu-selectionBackground: #005fb8; + --vscode-menu-selectionForeground: #ffffff; + --vscode-menu-separatorBackground: #d4d4d4; + --vscode-menubar-selectionBackground: rgba(184, 184, 184, 0.31); + --vscode-menubar-selectionForeground: #1e1e1e; + --vscode-merge-commonContentBackground: rgba(96, 96, 96, 0.16); + --vscode-merge-commonHeaderBackground: rgba(96, 96, 96, 0.4); + --vscode-merge-currentContentBackground: rgba(64, 200, 174, 0.2); + --vscode-merge-currentHeaderBackground: rgba(64, 200, 174, 0.5); + --vscode-merge-incomingContentBackground: rgba(64, 166, 255, 0.2); + --vscode-merge-incomingHeaderBackground: rgba(64, 166, 255, 0.5); + --vscode-mergeEditor-change.background: rgba(155, 185, 85, 0.2); + --vscode-mergeEditor-change.word.background: rgba(156, 204, 44, 0.4); + --vscode-mergeEditor-changeBase.background: #ffcccc; + --vscode-mergeEditor-changeBase.word.background: #ffa3a3; + --vscode-mergeEditor-conflict.handled.minimapOverViewRuler: rgba(173, 172, 168, 0.93); + --vscode-mergeEditor-conflict.handledFocused.border: rgba(193, 193, 193, 0.8); + --vscode-mergeEditor-conflict.handledUnfocused.border: rgba(134, 134, 134, 0.29); + --vscode-mergeEditor-conflict.input1.background: rgba(64, 200, 174, 0.2); + --vscode-mergeEditor-conflict.input2.background: rgba(64, 166, 255, 0.2); + --vscode-mergeEditor-conflict.unhandled.minimapOverViewRuler: #fcba03; + --vscode-mergeEditor-conflict.unhandledFocused.border: #ffa600; + --vscode-mergeEditor-conflict.unhandledUnfocused.border: #ffa600; + --vscode-mergeEditor-conflictingLines.background: rgba(255, 234, 0, 0.28); + --vscode-minimap-chatEditHighlight: rgba(255, 255, 255, 0.6); + --vscode-minimap-errorHighlight: rgba(255, 18, 18, 0.7); + --vscode-minimap-findMatchHighlight: #d18616; + --vscode-minimap-foregroundOpacity: #000000; + --vscode-minimap-infoHighlight: #1a85ff; + --vscode-minimap-selectionHighlight: #add6ff; + --vscode-minimap-selectionOccurrenceHighlight: #c9c9c9; + --vscode-minimap-warningHighlight: #bf8803; + --vscode-minimapGutter-addedBackground: #2ea043; + --vscode-minimapGutter-deletedBackground: #f85149; + --vscode-minimapGutter-modifiedBackground: #005fb8; + --vscode-minimapSlider-activeBackground: rgba(0, 0, 0, 0.3); + --vscode-minimapSlider-background: rgba(100, 100, 100, 0.2); + --vscode-minimapSlider-hoverBackground: rgba(100, 100, 100, 0.35); + --vscode-multiDiffEditor-background: #ffffff; + --vscode-multiDiffEditor-border: #cccccc; + --vscode-multiDiffEditor-headerBackground: #f8f8f8; + --vscode-notebook-cellBorderColor: #e5e5e5; + --vscode-notebook-cellEditorBackground: #f8f8f8; + --vscode-notebook-cellInsertionIndicator: #005fb8; + --vscode-notebook-cellStatusBarItemHoverBackground: rgba(0, 0, 0, 0.08); + --vscode-notebook-cellToolbarSeparator: rgba(128, 128, 128, 0.35); + --vscode-notebook-editorBackground: #ffffff; + --vscode-notebook-focusedCellBorder: #005fb8; + --vscode-notebook-focusedEditorBorder: #005fb8; + --vscode-notebook-inactiveFocusedCellBorder: #e5e5e5; + --vscode-notebook-selectedCellBackground: rgba(200, 221, 241, 0.31); + --vscode-notebook-selectedCellBorder: #e5e5e5; + --vscode-notebook-symbolHighlightBackground: rgba(253, 255, 0, 0.2); + --vscode-notebookEditorOverviewRuler-runningCellForeground: #388a34; + --vscode-notebookScrollbarSlider-activeBackground: rgba(0, 0, 0, 0.6); + --vscode-notebookScrollbarSlider-background: rgba(100, 100, 100, 0.4); + --vscode-notebookScrollbarSlider-hoverBackground: rgba(100, 100, 100, 0.7); + --vscode-notebookStatusErrorIcon-foreground: #f85149; + --vscode-notebookStatusRunningIcon-foreground: #3b3b3b; + --vscode-notebookStatusSuccessIcon-foreground: #388a34; + --vscode-notificationCenter-border: #e5e5e5; + --vscode-notificationCenterHeader-background: #ffffff; + --vscode-notificationCenterHeader-foreground: #3b3b3b; + --vscode-notificationLink-foreground: #005fb8; + --vscode-notificationToast-border: #e5e5e5; + --vscode-notifications-background: #ffffff; + --vscode-notifications-border: #e5e5e5; + --vscode-notifications-foreground: #3b3b3b; + --vscode-notificationsErrorIcon-foreground: #e51400; + --vscode-notificationsInfoIcon-foreground: #1a85ff; + --vscode-notificationsWarningIcon-foreground: #bf8803; + --vscode-panel-background: #f8f8f8; + --vscode-panel-border: #e5e5e5; + --vscode-panel-dropBorder: #3b3b3b; + --vscode-panelInput-border: #e5e5e5; + --vscode-panelSection-border: #e5e5e5; + --vscode-panelSection-dropBackground: rgba(38, 119, 203, 0.18); + --vscode-panelSectionHeader-background: rgba(128, 128, 128, 0.2); + --vscode-panelStickyScroll-background: #f8f8f8; + --vscode-panelStickyScroll-shadow: #dddddd; + --vscode-panelTitle-activeBorder: #005fb8; + --vscode-panelTitle-activeForeground: #3b3b3b; + --vscode-panelTitle-inactiveForeground: #3b3b3b; + --vscode-panelTitleBadge-background: #005fb8; + --vscode-panelTitleBadge-foreground: #ffffff; + --vscode-peekView-border: #1a85ff; + --vscode-peekViewEditor-background: #f2f8fc; + --vscode-peekViewEditor-matchHighlightBackground: rgba(187, 128, 9, 0.4); + --vscode-peekViewEditorGutter-background: #f2f8fc; + --vscode-peekViewEditorStickyScroll-background: #f2f8fc; + --vscode-peekViewResult-background: #ffffff; + --vscode-peekViewResult-fileForeground: #1e1e1e; + --vscode-peekViewResult-lineForeground: #646465; + --vscode-peekViewResult-matchHighlightBackground: rgba(187, 128, 9, 0.4); + --vscode-peekViewResult-selectionBackground: rgba(51, 153, 255, 0.2); + --vscode-peekViewResult-selectionForeground: #6c6c6c; + --vscode-peekViewTitle-background: #f3f3f3; + --vscode-peekViewTitleDescription-foreground: #616161; + --vscode-peekViewTitleLabel-foreground: #000000; + --vscode-pickerGroup-border: #e5e5e5; + --vscode-pickerGroup-foreground: #8b949e; + --vscode-ports-iconRunningProcessForeground: #369432; + --vscode-problemsErrorIcon-foreground: #e51400; + --vscode-problemsInfoIcon-foreground: #1a85ff; + --vscode-problemsWarningIcon-foreground: #bf8803; + --vscode-profileBadge-background: #c4c4c4; + --vscode-profileBadge-foreground: #333333; + --vscode-profiles-sashBorder: #e5e5e5; + --vscode-progressBar-background: #005fb8; + --vscode-prompt-frontMatter.background: #f2f2f2; + --vscode-prompt-frontMatter.inactiveBackground: #f9f9f9; + --vscode-quickInput-background: #f8f8f8; + --vscode-quickInput-foreground: #3b3b3b; + --vscode-quickInputList-focusBackground: #e8e8e8; + --vscode-quickInputList-focusForeground: #000000; + --vscode-quickInputList-focusIconForeground: #000000; + --vscode-quickInputTitle-background: rgba(0, 0, 0, 0.06); + --vscode-radio-activeBackground: #bed6ed; + --vscode-radio-activeBorder: #005fb8; + --vscode-radio-activeForeground: #000000; + --vscode-radio-inactiveBorder: rgba(0, 0, 0, 0.2); + --vscode-radio-inactiveHoverBackground: rgba(184, 184, 184, 0.31); + --vscode-sash-hoverBorder: #005fb8; + --vscode-scmGraph-foreground1: #ffb000; + --vscode-scmGraph-foreground2: #dc267f; + --vscode-scmGraph-foreground3: #994f00; + --vscode-scmGraph-foreground4: #40b0a6; + --vscode-scmGraph-foreground5: #b66dff; + --vscode-scmGraph-historyItemBaseRefColor: #ea5c00; + --vscode-scmGraph-historyItemHoverAdditionsForeground: #587c0c; + --vscode-scmGraph-historyItemHoverDefaultLabelBackground: #cccccc; + --vscode-scmGraph-historyItemHoverDefaultLabelForeground: #3b3b3b; + --vscode-scmGraph-historyItemHoverDeletionsForeground: #ad0707; + --vscode-scmGraph-historyItemHoverLabelForeground: #ffffff; + --vscode-scmGraph-historyItemRefColor: #1a85ff; + --vscode-scmGraph-historyItemRemoteRefColor: #652d90; + --vscode-scrollbar-shadow: #dddddd; + --vscode-scrollbarSlider-activeBackground: rgba(0, 0, 0, 0.6); + --vscode-scrollbarSlider-background: rgba(100, 100, 100, 0.4); + --vscode-scrollbarSlider-hoverBackground: rgba(100, 100, 100, 0.7); + --vscode-search-resultsInfoForeground: #3b3b3b; + --vscode-searchEditor-findMatchBackground: rgba(234, 92, 0, 0.22); + --vscode-searchEditor-textInputBorder: #cecece; + --vscode-settings-checkboxBackground: #f8f8f8; + --vscode-settings-checkboxBorder: #cecece; + --vscode-settings-checkboxForeground: #3b3b3b; + --vscode-settings-dropdownBackground: #ffffff; + --vscode-settings-dropdownBorder: #cecece; + --vscode-settings-dropdownForeground: #3b3b3b; + --vscode-settings-dropdownListBorder: #c8c8c8; + --vscode-settings-focusedRowBackground: rgba(242, 242, 242, 0.6); + --vscode-settings-focusedRowBorder: #005fb8; + --vscode-settings-headerBorder: #e5e5e5; + --vscode-settings-headerForeground: #1f1f1f; + --vscode-settings-modifiedItemIndicator: rgba(187, 128, 9, 0.4); + --vscode-settings-numberInputBackground: #ffffff; + --vscode-settings-numberInputBorder: #cecece; + --vscode-settings-numberInputForeground: #3b3b3b; + --vscode-settings-rowHoverBackground: rgba(242, 242, 242, 0.3); + --vscode-settings-sashBorder: #e5e5e5; + --vscode-settings-settingsHeaderHoverForeground: rgba(31, 31, 31, 0.7); + --vscode-settings-textInputBackground: #ffffff; + --vscode-settings-textInputBorder: #cecece; + --vscode-settings-textInputForeground: #3b3b3b; + --vscode-sideBar-background: #f8f8f8; + --vscode-sideBar-border: #e5e5e5; + --vscode-sideBar-dropBackground: rgba(38, 119, 203, 0.18); + --vscode-sideBar-foreground: #3b3b3b; + --vscode-sideBarActivityBarTop-border: #e5e5e5; + --vscode-sideBarSectionHeader-background: #f8f8f8; + --vscode-sideBarSectionHeader-border: #e5e5e5; + --vscode-sideBarSectionHeader-foreground: #3b3b3b; + --vscode-sideBarStickyScroll-background: #f8f8f8; + --vscode-sideBarStickyScroll-shadow: #dddddd; + --vscode-sideBarTitle-background: #f8f8f8; + --vscode-sideBarTitle-foreground: #3b3b3b; + --vscode-sideBySideEditor-horizontalBorder: #e5e5e5; + --vscode-sideBySideEditor-verticalBorder: #e5e5e5; + --vscode-simpleFindWidget-sashBorder: #c8c8c8; + --vscode-statusBar-background: #f8f8f8; + --vscode-statusBar-border: #e5e5e5; + --vscode-statusBar-debuggingBackground: #fd716c; + --vscode-statusBar-debuggingBorder: #e5e5e5; + --vscode-statusBar-debuggingForeground: #000000; + --vscode-statusBar-focusBorder: #005fb8; + --vscode-statusBar-foreground: #3b3b3b; + --vscode-statusBar-noFolderBackground: #f8f8f8; + --vscode-statusBar-noFolderBorder: #e5e5e5; + --vscode-statusBar-noFolderForeground: #3b3b3b; + --vscode-statusBarItem-activeBackground: rgba(255, 255, 255, 0.18); + --vscode-statusBarItem-compactHoverBackground: #cccccc; + --vscode-statusBarItem-errorBackground: #c72e0f; + --vscode-statusBarItem-errorForeground: #ffffff; + --vscode-statusBarItem-errorHoverBackground: rgba(184, 184, 184, 0.31); + --vscode-statusBarItem-errorHoverForeground: #3b3b3b; + --vscode-statusBarItem-focusBorder: #005fb8; + --vscode-statusBarItem-hoverBackground: rgba(184, 184, 184, 0.31); + --vscode-statusBarItem-hoverForeground: #3b3b3b; + --vscode-statusBarItem-offlineBackground: #6c1717; + --vscode-statusBarItem-offlineForeground: #ffffff; + --vscode-statusBarItem-offlineHoverBackground: rgba(184, 184, 184, 0.31); + --vscode-statusBarItem-offlineHoverForeground: #3b3b3b; + --vscode-statusBarItem-prominentBackground: rgba(110, 118, 129, 0.4); + --vscode-statusBarItem-prominentForeground: #3b3b3b; + --vscode-statusBarItem-prominentHoverBackground: rgba(184, 184, 184, 0.31); + --vscode-statusBarItem-prominentHoverForeground: #3b3b3b; + --vscode-statusBarItem-remoteBackground: #005fb8; + --vscode-statusBarItem-remoteForeground: #ffffff; + --vscode-statusBarItem-remoteHoverBackground: rgba(184, 184, 184, 0.31); + --vscode-statusBarItem-remoteHoverForeground: #3b3b3b; + --vscode-statusBarItem-warningBackground: #725102; + --vscode-statusBarItem-warningForeground: #ffffff; + --vscode-statusBarItem-warningHoverBackground: rgba(184, 184, 184, 0.31); + --vscode-statusBarItem-warningHoverForeground: #3b3b3b; + --vscode-symbolIcon-arrayForeground: #3b3b3b; + --vscode-symbolIcon-booleanForeground: #3b3b3b; + --vscode-symbolIcon-classForeground: #d67e00; + --vscode-symbolIcon-colorForeground: #3b3b3b; + --vscode-symbolIcon-constantForeground: #3b3b3b; + --vscode-symbolIcon-constructorForeground: #652d90; + --vscode-symbolIcon-enumeratorForeground: #d67e00; + --vscode-symbolIcon-enumeratorMemberForeground: #007acc; + --vscode-symbolIcon-eventForeground: #d67e00; + --vscode-symbolIcon-fieldForeground: #007acc; + --vscode-symbolIcon-fileForeground: #3b3b3b; + --vscode-symbolIcon-folderForeground: #3b3b3b; + --vscode-symbolIcon-functionForeground: #652d90; + --vscode-symbolIcon-interfaceForeground: #007acc; + --vscode-symbolIcon-keyForeground: #3b3b3b; + --vscode-symbolIcon-keywordForeground: #3b3b3b; + --vscode-symbolIcon-methodForeground: #652d90; + --vscode-symbolIcon-moduleForeground: #3b3b3b; + --vscode-symbolIcon-namespaceForeground: #3b3b3b; + --vscode-symbolIcon-nullForeground: #3b3b3b; + --vscode-symbolIcon-numberForeground: #3b3b3b; + --vscode-symbolIcon-objectForeground: #3b3b3b; + --vscode-symbolIcon-operatorForeground: #3b3b3b; + --vscode-symbolIcon-packageForeground: #3b3b3b; + --vscode-symbolIcon-propertyForeground: #3b3b3b; + --vscode-symbolIcon-referenceForeground: #3b3b3b; + --vscode-symbolIcon-snippetForeground: #3b3b3b; + --vscode-symbolIcon-stringForeground: #3b3b3b; + --vscode-symbolIcon-structForeground: #3b3b3b; + --vscode-symbolIcon-textForeground: #3b3b3b; + --vscode-symbolIcon-typeParameterForeground: #3b3b3b; + --vscode-symbolIcon-unitForeground: #3b3b3b; + --vscode-symbolIcon-variableForeground: #007acc; + --vscode-tab-activeBackground: #ffffff; + --vscode-tab-activeBorder: #f8f8f8; + --vscode-tab-activeBorderTop: #005fb8; + --vscode-tab-activeForeground: #3b3b3b; + --vscode-tab-activeModifiedBorder: #33aaee; + --vscode-tab-border: #e5e5e5; + --vscode-tab-dragAndDropBorder: #3b3b3b; + --vscode-tab-hoverBackground: #ffffff; + --vscode-tab-inactiveBackground: #f8f8f8; + --vscode-tab-inactiveForeground: #868686; + --vscode-tab-inactiveModifiedBorder: rgba(51, 170, 238, 0.5); + --vscode-tab-lastPinnedBorder: #d4d4d4; + --vscode-tab-selectedBackground: rgba(255, 255, 255, 0.65); + --vscode-tab-selectedBorderTop: #68a3da; + --vscode-tab-selectedForeground: rgba(51, 51, 51, 0.7); + --vscode-tab-unfocusedActiveBackground: #ffffff; + --vscode-tab-unfocusedActiveBorder: #f8f8f8; + --vscode-tab-unfocusedActiveBorderTop: #e5e5e5; + --vscode-tab-unfocusedActiveForeground: rgba(59, 59, 59, 0.7); + --vscode-tab-unfocusedActiveModifiedBorder: rgba(51, 170, 238, 0.7); + --vscode-tab-unfocusedHoverBackground: #f8f8f8; + --vscode-tab-unfocusedInactiveBackground: #f8f8f8; + --vscode-tab-unfocusedInactiveForeground: rgba(134, 134, 134, 0.5); + --vscode-tab-unfocusedInactiveModifiedBorder: rgba(51, 170, 238, 0.25); + --vscode-terminal-ansiBlack: #000000; + --vscode-terminal-ansiBlue: #0451a5; + --vscode-terminal-ansiBrightBlack: #666666; + --vscode-terminal-ansiBrightBlue: #0451a5; + --vscode-terminal-ansiBrightCyan: #0598bc; + --vscode-terminal-ansiBrightGreen: #14ce14; + --vscode-terminal-ansiBrightMagenta: #bc05bc; + --vscode-terminal-ansiBrightRed: #cd3131; + --vscode-terminal-ansiBrightWhite: #a5a5a5; + --vscode-terminal-ansiBrightYellow: #b5ba00; + --vscode-terminal-ansiCyan: #0598bc; + --vscode-terminal-ansiGreen: #107c10; + --vscode-terminal-ansiMagenta: #bc05bc; + --vscode-terminal-ansiRed: #cd3131; + --vscode-terminal-ansiWhite: #555555; + --vscode-terminal-ansiYellow: #949800; + --vscode-terminal-border: #e5e5e5; + --vscode-terminal-dropBackground: rgba(38, 119, 203, 0.18); + --vscode-terminal-findMatchBackground: #a8ac94; + --vscode-terminal-findMatchHighlightBackground: rgba(234, 92, 0, 0.33); + --vscode-terminal-foreground: #3b3b3b; + --vscode-terminal-hoverHighlightBackground: rgba(173, 214, 255, 0.07); + --vscode-terminal-inactiveSelectionBackground: #e5ebf1; + --vscode-terminal-initialHintForeground: rgba(0, 0, 0, 0.47); + --vscode-terminal-selectionBackground: #add6ff; + --vscode-terminal-tab.activeBorder: #005fb8; + --vscode-terminalCommandDecoration-defaultBackground: rgba(0, 0, 0, 0.25); + --vscode-terminalCommandDecoration-errorBackground: #e51400; + --vscode-terminalCommandDecoration-successBackground: #2090d3; + --vscode-terminalCommandGuide-foreground: #e4e6f1; + --vscode-terminalCursor-foreground: #005fb8; + --vscode-terminalOverviewRuler-border: #e5e5e5; + --vscode-terminalOverviewRuler-cursorForeground: rgba(160, 160, 160, 0.8); + --vscode-terminalOverviewRuler-findMatchForeground: rgba(209, 134, 22, 0.49); + --vscode-terminalStickyScrollHover-background: #f0f0f0; + --vscode-terminalSymbolIcon-aliasForeground: #652d90; + --vscode-terminalSymbolIcon-argumentForeground: #007acc; + --vscode-terminalSymbolIcon-fileForeground: #3b3b3b; + --vscode-terminalSymbolIcon-flagForeground: #d67e00; + --vscode-terminalSymbolIcon-folderForeground: #3b3b3b; + --vscode-terminalSymbolIcon-methodForeground: #652d90; + --vscode-terminalSymbolIcon-optionForeground: #d67e00; + --vscode-terminalSymbolIcon-optionValueForeground: #007acc; + --vscode-testing-coverCountBadgeBackground: #cccccc; + --vscode-testing-coverCountBadgeForeground: #3b3b3b; + --vscode-testing-coveredBackground: rgba(156, 204, 44, 0.25); + --vscode-testing-coveredBorder: rgba(156, 204, 44, 0.19); + --vscode-testing-coveredGutterBackground: rgba(156, 204, 44, 0.15); + --vscode-testing-iconErrored: #f14c4c; + --vscode-testing-iconErrored.retired: rgba(241, 76, 76, 0.7); + --vscode-testing-iconFailed: #f14c4c; + --vscode-testing-iconFailed.retired: rgba(241, 76, 76, 0.7); + --vscode-testing-iconPassed: #73c991; + --vscode-testing-iconPassed.retired: rgba(115, 201, 145, 0.7); + --vscode-testing-iconQueued: #cca700; + --vscode-testing-iconQueued.retired: rgba(204, 167, 0, 0.7); + --vscode-testing-iconSkipped: #848484; + --vscode-testing-iconSkipped.retired: rgba(132, 132, 132, 0.7); + --vscode-testing-iconUnset: #848484; + --vscode-testing-iconUnset.retired: rgba(132, 132, 132, 0.7); + --vscode-testing-message.error.badgeBackground: #e51400; + --vscode-testing-message.error.badgeBorder: #e51400; + --vscode-testing-message.error.badgeForeground: #ffffff; + --vscode-testing-message.info.decorationForeground: rgba(59, 59, 59, 0.5); + --vscode-testing-messagePeekBorder: #1a85ff; + --vscode-testing-messagePeekHeaderBackground: rgba(26, 133, 255, 0.1); + --vscode-testing-peekBorder: #e51400; + --vscode-testing-peekHeaderBackground: rgba(229, 20, 0, 0.1); + --vscode-testing-runAction: #73c991; + --vscode-testing-uncoveredBackground: rgba(255, 0, 0, 0.2); + --vscode-testing-uncoveredBorder: rgba(255, 0, 0, 0.15); + --vscode-testing-uncoveredBranchBackground: #ff9999; + --vscode-testing-uncoveredGutterBackground: rgba(255, 0, 0, 0.3); + --vscode-textBlockQuote-background: #f8f8f8; + --vscode-textBlockQuote-border: #e5e5e5; + --vscode-textCodeBlock-background: #f8f8f8; + --vscode-textLink-activeForeground: #005fb8; + --vscode-textLink-foreground: #005fb8; + --vscode-textPreformat-background: rgba(0, 0, 0, 0.12); + --vscode-textPreformat-foreground: #3b3b3b; + --vscode-textSeparator-foreground: #21262d; + --vscode-titleBar-activeBackground: #f8f8f8; + --vscode-titleBar-activeForeground: #1e1e1e; + --vscode-titleBar-border: #e5e5e5; + --vscode-titleBar-inactiveBackground: #f8f8f8; + --vscode-titleBar-inactiveForeground: #8b949e; + --vscode-toolbar-activeBackground: rgba(166, 166, 166, 0.31); + --vscode-toolbar-hoverBackground: rgba(184, 184, 184, 0.31); + --vscode-tree-inactiveIndentGuidesStroke: rgba(169, 169, 169, 0.4); + --vscode-tree-indentGuidesStroke: #a9a9a9; + --vscode-tree-tableColumnsBorder: rgba(97, 97, 97, 0.13); + --vscode-tree-tableOddRowsBackground: rgba(59, 59, 59, 0.04); + --vscode-walkThrough-embeddedEditorBackground: #f4f4f4; + --vscode-walkthrough-stepTitle.foreground: #000000; + --vscode-welcomePage-progress.background: #ffffff; + --vscode-welcomePage-progress.foreground: #005fb8; + --vscode-welcomePage-tileBackground: #f3f3f3; + --vscode-welcomePage-tileBorder: rgba(0, 0, 0, 0.1); + --vscode-welcomePage-tileHoverBackground: #dfdfdf; + --vscode-widget-border: #e5e5e5; + --vscode-widget-shadow: rgba(0, 0, 0, 0.16); +} diff --git a/webview-ui/playwright/vscode-theme-base.css b/webview-ui/playwright/vscode-theme-base.css new file mode 100644 index 0000000000..5226acb1cf --- /dev/null +++ b/webview-ui/playwright/vscode-theme-base.css @@ -0,0 +1,41 @@ +:root, +body { + /* Font settings are environment/user configuration, not theme colors. Keep CT typography stable across runners. */ + --vscode-font-family: system-ui, "Ubuntu", "Droid Sans", sans-serif; + --vscode-editor-font-family: "Droid Sans Mono", "monospace", monospace; +} + +body { + margin: 0; + background: var(--vscode-editor-background); + color: var(--vscode-editor-foreground); + font-family: var(--vscode-font-family); + font-size: var(--vscode-font-size); +} + +#root { + padding: 16px; +} + +/* @vscode/webview-ui-toolkit/react renders VSCodeButton as a bare +
, +})) + +describe("LiteLLM", () => { + const organizationAllowList: OrganizationAllowList = { allowAll: true, providers: {} } + + beforeEach(() => { + vi.clearAllMocks() + mockUseExtensionState.mockReturnValue({ routerModels: { [providerIdentifiers.litellm]: {} } }) + }) + + it("invalidates both LiteLLM caches after a successful model refresh", async () => { + const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } }) + const invalidateQueries = vi.spyOn(queryClient, "invalidateQueries") + const apiConfiguration: ProviderSettings = { + apiProvider: providerIdentifiers.litellm, + litellmApiKey: "test-key", + litellmBaseUrl: "http://localhost:4000", + } + + render( + + + , + ) + + fireEvent.click(screen.getByTestId("refresh-button")) + act(() => { + window.dispatchEvent(new MessageEvent("message", { data: { type: "routerModels" } })) + }) + + await waitFor(() => { + expect(invalidateQueries).toHaveBeenCalledWith({ + queryKey: ["routerModels", providerIdentifiers.litellm], + }) + expect(invalidateQueries).toHaveBeenCalledWith({ queryKey: ["routerModels", allRouterModelsProvider] }) + }) + }) + + it("recognizes failed refresh responses for the canonical LiteLLM provider", () => { + const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } }) + render( + + + , + ) + + act(() => { + window.dispatchEvent( + new MessageEvent("message", { + data: { + type: "singleRouterModelFetchResponse", + success: false, + values: { provider: providerIdentifiers.litellm }, + error: "LiteLLM unavailable", + }, + }), + ) + }) + + expect(screen.getByText("LiteLLM unavailable")).toBeInTheDocument() + }) + + it("does not invalidate caches when a LiteLLM error and router models arrive in the same tick", () => { + const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } }) + const invalidateQueries = vi.spyOn(queryClient, "invalidateQueries") + + render( + + + , + ) + + fireEvent.click(screen.getByTestId("refresh-button")) + act(() => { + window.dispatchEvent( + new MessageEvent("message", { + data: { + type: "singleRouterModelFetchResponse", + success: false, + values: { provider: providerIdentifiers.litellm }, + error: "LiteLLM unavailable", + }, + }), + ) + window.dispatchEvent(new MessageEvent("message", { data: { type: "routerModels" } })) + }) + + expect(screen.getByText("LiteLLM unavailable")).toBeInTheDocument() + expect(invalidateQueries).not.toHaveBeenCalled() + }) + + it("ignores failed refresh responses for another provider", () => { + const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } }) + render( + + + , + ) + + fireEvent.click(screen.getByTestId("refresh-button")) + expect(screen.getByText("settings:providers.refreshModels.loading")).toBeInTheDocument() + + act(() => { + window.dispatchEvent( + new MessageEvent("message", { + data: { + type: "singleRouterModelFetchResponse", + success: false, + values: { provider: providerIdentifiers.openrouter }, + error: "OpenRouter unavailable", + }, + }), + ) + }) + + expect(screen.queryByText("OpenRouter unavailable")).not.toBeInTheDocument() + expect(screen.getByText("settings:providers.refreshModels.loading")).toBeInTheDocument() + }) +}) diff --git a/webview-ui/src/components/settings/providers/__tests__/Moonshot.spec.tsx b/webview-ui/src/components/settings/providers/__tests__/Moonshot.spec.tsx index 1ffcf9b683..1cffc1d5ba 100644 --- a/webview-ui/src/components/settings/providers/__tests__/Moonshot.spec.tsx +++ b/webview-ui/src/components/settings/providers/__tests__/Moonshot.spec.tsx @@ -2,7 +2,8 @@ import React from "react" import { render, screen, fireEvent, waitFor, act } from "@/utils/test-utils" -import type { ProviderSettings } from "@roo-code/types" +import { QueryClient, QueryClientProvider } from "@tanstack/react-query" +import { allRouterModelsProvider, providerIdentifiers, type ProviderSettings } from "@roo-code/types" import { Moonshot } from "../Moonshot" @@ -47,13 +48,18 @@ vi.mock("@vscode/webview-ui-toolkit/react", async (importOriginal) => { }) // Mock the ModelPicker - must be a simple component that doesn't import anything -vi.mock("../ModelPicker", () => ({ - ModelPicker: function MockModelPicker() { +vi.mock("../../ModelPicker", () => ({ + ModelPicker: function MockModelPicker({ onModelChange }: { onModelChange?: (modelId: string) => void }) { return React.createElement( "div", { "data-testid": "model-picker" }, React.createElement("span", { "data-testid": "model-picker-default" }, "mock-default"), React.createElement("span", { "data-testid": "model-picker-count" }, "0"), + React.createElement( + "button", + { "data-testid": "change-model", onClick: () => onModelChange?.("moonshot-v1-128k") }, + "Change model", + ), ) }, })) @@ -103,11 +109,6 @@ vi.mock("@src/components/common/VSCodeButtonLink", () => ({ ), })) -// Mock handleModelChangeSideEffects -vi.mock("../utils/providerModelConfig", () => ({ - handleModelChangeSideEffects: vi.fn(), -})) - import { useExtensionState } from "@src/context/ExtensionStateContext" import { vscode } from "@src/utils/vscode" @@ -117,7 +118,7 @@ describe("Moonshot Component", () => { const mockSetApiConfigurationField = vi.fn() const createDefaultApiConfiguration = (overrides?: Partial): ProviderSettings => ({ - apiProvider: "moonshot", + apiProvider: providerIdentifiers.moonshot, moonshotBaseUrl: "https://api.moonshot.ai/v1", ...overrides, }) @@ -223,6 +224,38 @@ describe("Moonshot Component", () => { }) }) + it("invalidates only the Moonshot and shared router-model caches after a successful refresh", async () => { + const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } }) + const invalidateQueries = vi.spyOn(queryClient, "invalidateQueries") + + render( + + + , + ) + + const refreshButton = screen + .getAllByTestId("button") + .find((button) => button.getAttribute("data-variant") === "outline")! + fireEvent.click(refreshButton) + act(() => { + window.dispatchEvent(new MessageEvent("message", { data: { type: "routerModels" } })) + }) + + await waitFor(() => { + expect(invalidateQueries).toHaveBeenCalledWith({ + queryKey: ["routerModels", providerIdentifiers.moonshot], + }) + expect(invalidateQueries).toHaveBeenCalledWith({ + queryKey: ["routerModels", allRouterModelsProvider], + }) + expect(invalidateQueries).not.toHaveBeenCalledWith({ queryKey: ["routerModels"] }) + }) + }) + it("shows error state after singleRouterModelFetchResponse error message", async () => { mockUseExtensionState.mockReturnValue({ routerModels: {}, @@ -258,7 +291,7 @@ describe("Moonshot Component", () => { type: "singleRouterModelFetchResponse", success: false, error: "API connection failed", - values: { provider: "moonshot" }, + values: { provider: providerIdentifiers.moonshot }, }, "*", ) @@ -274,6 +307,77 @@ describe("Moonshot Component", () => { }) }) + it("ignores another provider's failed refresh response while loading", async () => { + render( + , + ) + + const refreshButton = screen + .getAllByTestId("button") + .find((button) => button.getAttribute("data-variant") === "outline")! + fireEvent.click(refreshButton) + await waitFor(() => expect(screen.getByText("settings:providers.refreshModels.loading")).toBeInTheDocument()) + + act(() => { + window.dispatchEvent( + new MessageEvent("message", { + data: { + type: "singleRouterModelFetchResponse", + success: false, + error: "OpenRouter unavailable", + values: { provider: providerIdentifiers.openrouter }, + }, + }), + ) + }) + + expect(screen.queryByText("OpenRouter unavailable")).not.toBeInTheDocument() + expect(screen.getByText("settings:providers.refreshModels.loading")).toBeInTheDocument() + }) + + it("ignores a Moonshot failure response before refresh starts", () => { + render( + , + ) + + act(() => { + window.dispatchEvent( + new MessageEvent("message", { + data: { + type: "singleRouterModelFetchResponse", + success: false, + error: "Moonshot unavailable", + values: { provider: providerIdentifiers.moonshot }, + }, + }), + ) + }) + + expect(screen.queryByText("Moonshot unavailable")).not.toBeInTheDocument() + expect(screen.queryByText("settings:providers.refreshModels.loading")).not.toBeInTheDocument() + }) + + it("resets model-specific settings when the selected model changes", () => { + render( + , + ) + + fireEvent.click(screen.getByTestId("change-model")) + + expect(mockSetApiConfigurationField).toHaveBeenCalledWith("reasoningEffort", undefined) + expect(mockSetApiConfigurationField).toHaveBeenCalledWith("modelMaxTokens", undefined) + expect(mockSetApiConfigurationField).toHaveBeenCalledWith("modelMaxThinkingTokens", undefined) + }) + it("race condition: error arrives before routerModels success — stays in error state", async () => { mockUseExtensionState.mockReturnValue({ routerModels: {}, @@ -308,7 +412,7 @@ describe("Moonshot Component", () => { type: "singleRouterModelFetchResponse", success: false, error: "API connection failed", - values: { provider: "moonshot" }, + values: { provider: providerIdentifiers.moonshot }, }, "*", ) diff --git a/webview-ui/src/components/settings/providers/__tests__/NanoGPT.spec.tsx b/webview-ui/src/components/settings/providers/__tests__/NanoGPT.spec.tsx index d2bf7b3c04..bb810caa75 100644 --- a/webview-ui/src/components/settings/providers/__tests__/NanoGPT.spec.tsx +++ b/webview-ui/src/components/settings/providers/__tests__/NanoGPT.spec.tsx @@ -6,6 +6,8 @@ import { type RouterModels, nanoGptDefaultModelId, nanoGptRoutingPreferences, + providerIdentifiers, + RouterModelsMessageType, } from "@roo-code/types" import { NanoGPT } from "../NanoGPT" @@ -160,8 +162,8 @@ describe("NanoGPT", () => { it("refreshes models with the unsaved cached key whenever it changes", () => { const { rerender } = renderComponent({ nanoGptApiKey: "first-key" }) expect(postMessageMock).toHaveBeenLastCalledWith({ - type: "requestRouterModels", - values: { provider: "nanogpt", nanoGptApiKey: "first-key" }, + type: RouterModelsMessageType.requestRouterModels, + values: { provider: providerIdentifiers.nanogpt, nanoGptApiKey: "first-key" }, }) rerender( @@ -174,8 +176,8 @@ describe("NanoGPT", () => { ) expect(postMessageMock).toHaveBeenLastCalledWith({ - type: "requestRouterModels", - values: { provider: "nanogpt", nanoGptApiKey: "unsaved-key" }, + type: RouterModelsMessageType.requestRouterModels, + values: { provider: providerIdentifiers.nanogpt, nanoGptApiKey: "unsaved-key" }, }) }) }) diff --git a/webview-ui/src/components/settings/providers/__tests__/Poe.spec.tsx b/webview-ui/src/components/settings/providers/__tests__/Poe.spec.tsx new file mode 100644 index 0000000000..b8c9f6e254 --- /dev/null +++ b/webview-ui/src/components/settings/providers/__tests__/Poe.spec.tsx @@ -0,0 +1,150 @@ +import { QueryClient, QueryClientProvider } from "@tanstack/react-query" +import { act, fireEvent, render, screen, waitFor } from "@testing-library/react" + +import { + allRouterModelsProvider, + providerIdentifiers, + type OrganizationAllowList, + type ProviderSettings, +} from "@roo-code/types" + +import { Poe } from "../Poe" + +const { mockUseExtensionState } = vi.hoisted(() => ({ + mockUseExtensionState: vi.fn(), +})) + +vi.mock("@src/context/ExtensionStateContext", () => ({ + useExtensionState: mockUseExtensionState, +})) + +vi.mock("@src/i18n/TranslationContext", () => ({ + useAppTranslation: () => ({ t: (key: string) => key }), +})) + +vi.mock("@vscode/webview-ui-toolkit/react", () => ({ + VSCodeTextField: ({ children }: { children: React.ReactNode }) =>
{children}
, +})) + +vi.mock("@src/components/common/VSCodeButtonLink", () => ({ + VSCodeButtonLink: ({ children }: { children: React.ReactNode }) =>
{children}
, +})) + +vi.mock("@src/components/ui", () => ({ + Button: ({ children, onClick, disabled }: React.ComponentProps<"button">) => ( + + ), +})) + +vi.mock("../../ModelPicker", () => ({ + ModelPicker: ({ onModelChange }: { onModelChange?: (modelId: string) => void }) => ( + + ), +})) + +describe("Poe", () => { + const organizationAllowList: OrganizationAllowList = { allowAll: true, providers: {} } + const setApiConfigurationField = vi.fn() + + const renderComponent = (apiConfiguration: ProviderSettings = { apiProvider: providerIdentifiers.poe }) => { + const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } }) + + return render( + + + , + ) + } + + beforeEach(() => { + vi.clearAllMocks() + mockUseExtensionState.mockReturnValue({ routerModels: { [providerIdentifiers.poe]: {} } }) + }) + + it("shows the Poe refresh error returned by the extension", () => { + renderComponent({ apiProvider: providerIdentifiers.poe, poeApiKey: "test-key" }) + + act(() => { + window.dispatchEvent( + new MessageEvent("message", { + data: { + type: "singleRouterModelFetchResponse", + success: false, + values: { provider: providerIdentifiers.poe }, + error: "Poe authentication failed", + }, + }), + ) + }) + + expect(screen.getByText("Poe authentication failed")).toBeInTheDocument() + }) + + it("ignores failed refresh responses for another provider", () => { + renderComponent({ apiProvider: providerIdentifiers.poe, poeApiKey: "test-key" }) + + act(() => { + window.dispatchEvent( + new MessageEvent("message", { + data: { + type: "singleRouterModelFetchResponse", + success: false, + values: { provider: providerIdentifiers.openrouter }, + error: "OpenRouter authentication failed", + }, + }), + ) + }) + + expect(screen.queryByText("OpenRouter authentication failed")).not.toBeInTheDocument() + expect(screen.queryByText("settings:providers.refreshModels.error")).not.toBeInTheDocument() + }) + + it("invalidates only the Poe and shared router-model caches after a successful refresh", async () => { + const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } }) + const invalidateQueries = vi.spyOn(queryClient, "invalidateQueries") + + render( + + + , + ) + + fireEvent.click(screen.getByTestId("refresh-button")) + act(() => { + window.dispatchEvent(new MessageEvent("message", { data: { type: "routerModels" } })) + }) + + await waitFor(() => { + expect(invalidateQueries).toHaveBeenCalledWith({ + queryKey: ["routerModels", providerIdentifiers.poe], + }) + expect(invalidateQueries).toHaveBeenCalledWith({ + queryKey: ["routerModels", allRouterModelsProvider], + }) + expect(invalidateQueries).not.toHaveBeenCalledWith({ queryKey: ["routerModels"] }) + }) + }) + + it("clears model-specific reasoning settings when the Poe model changes", () => { + renderComponent() + + fireEvent.click(screen.getByTestId("model-picker")) + + expect(setApiConfigurationField).toHaveBeenCalledWith("reasoningEffort", undefined) + expect(setApiConfigurationField).toHaveBeenCalledWith("modelMaxTokens", undefined) + expect(setApiConfigurationField).toHaveBeenCalledWith("modelMaxThinkingTokens", undefined) + }) +}) diff --git a/webview-ui/src/components/settings/providers/__tests__/ProviderRouting.spec.tsx b/webview-ui/src/components/settings/providers/__tests__/ProviderRouting.spec.tsx new file mode 100644 index 0000000000..e355baa08c --- /dev/null +++ b/webview-ui/src/components/settings/providers/__tests__/ProviderRouting.spec.tsx @@ -0,0 +1,82 @@ +import { fireEvent, render, screen } from "@testing-library/react" + +import { providerIdentifiers, type OrganizationAllowList, type RouterModels } from "@roo-code/types" + +import { vscode } from "@src/utils/vscode" + +import { Unbound } from "../Unbound" +import { VercelAiGateway } from "../VercelAiGateway" + +const { modelPickerMock } = vi.hoisted(() => ({ modelPickerMock: vi.fn(() => null) })) + +vi.mock("@src/i18n/TranslationContext", () => ({ + useAppTranslation: () => ({ t: (key: string) => key }), +})) + +vi.mock("@vscode/webview-ui-toolkit/react", () => ({ + VSCodeTextField: ({ children }: { children: React.ReactNode }) =>
{children}
, +})) + +vi.mock("@src/components/ui", () => ({ + Button: ({ children, onClick }: React.ComponentProps<"button">) => , +})) + +vi.mock("../../ModelPicker", () => ({ ModelPicker: modelPickerMock })) +vi.mock("@src/components/common/VSCodeButtonLink", () => ({ VSCodeButtonLink: () => null })) + +describe("provider model routing", () => { + const organizationAllowList: OrganizationAllowList = { allowAll: true, providers: {} } + + beforeEach(() => vi.clearAllMocks()) + + it("requests fresh Unbound models when the refresh button is clicked", () => { + const postMessage = vi.spyOn(vscode, "postMessage").mockImplementation(() => undefined) + + render( + , + ) + + fireEvent.click(screen.getByRole("button", { name: "settings:providers.refreshModels.label" })) + + expect(postMessage).toHaveBeenCalledWith({ + type: "requestRouterModels", + values: { provider: providerIdentifiers.unbound, refresh: true }, + }) + }) + + it("passes Vercel AI Gateway models selected by its provider identifier to the model picker", () => { + const models = { "anthropic/claude": { contextWindow: 1, supportsPromptCache: false } } + const routerModels = Object.fromEntries( + Object.values(providerIdentifiers).map((provider) => [provider, {}]), + ) as RouterModels + routerModels[providerIdentifiers.vercelAiGateway] = models + + render( + , + ) + + expect(modelPickerMock).toHaveBeenCalledWith(expect.objectContaining({ models }), expect.anything()) + }) + + it("passes an empty model set when Vercel AI Gateway models are unavailable", () => { + render( + , + ) + + expect(modelPickerMock).toHaveBeenCalledWith(expect.objectContaining({ models: {} }), expect.anything()) + }) +}) diff --git a/webview-ui/src/components/settings/providers/__tests__/Requesty.spec.tsx b/webview-ui/src/components/settings/providers/__tests__/Requesty.spec.tsx new file mode 100644 index 0000000000..bb7d4e234f --- /dev/null +++ b/webview-ui/src/components/settings/providers/__tests__/Requesty.spec.tsx @@ -0,0 +1,57 @@ +import { fireEvent, render, screen } from "@testing-library/react" + +import { providerIdentifiers, type OrganizationAllowList } from "@roo-code/types" + +import { vscode } from "@src/utils/vscode" + +import { Requesty } from "../Requesty" + +vi.mock("@src/i18n/TranslationContext", () => ({ + useAppTranslation: () => ({ t: (key: string) => key }), +})) + +vi.mock("@vscode/webview-ui-toolkit/react", () => ({ + VSCodeTextField: ({ children }: { children: React.ReactNode }) =>
{children}
, + VSCodeCheckbox: ({ children }: { children: React.ReactNode }) =>
{children}
, +})) + +vi.mock("@src/components/ui", () => ({ + Button: ({ children, onClick }: React.ComponentProps<"button">) => ( + + ), +})) + +vi.mock("../../ModelPicker", () => ({ ModelPicker: () => null })) +vi.mock("../RequestyBalanceDisplay", () => ({ RequestyBalanceDisplay: () => null })) + +describe("Requesty", () => { + const organizationAllowList: OrganizationAllowList = { allowAll: true, providers: {} } + + it("uses the canonical Requesty identifier for OAuth and model refresh", () => { + const postMessage = vi.spyOn(vscode, "postMessage").mockImplementation(() => undefined) + + render( + , + ) + + const href = screen.getByRole("link").getAttribute("href") + expect(href).not.toBeNull() + const callbackUrl = new URL(href!).searchParams.get("callback_url") + expect(callbackUrl).not.toBeNull() + expect(new URL(callbackUrl!).pathname).toMatch(new RegExp(`/${providerIdentifiers.requesty}$`)) + + fireEvent.click(screen.getByTestId("refresh-button")) + expect(postMessage).toHaveBeenCalledWith({ + type: "requestRouterModels", + values: { provider: providerIdentifiers.requesty, refresh: true }, + }) + }) +}) diff --git a/webview-ui/src/components/ui/hooks/useLmStudioModels.ts b/webview-ui/src/components/ui/hooks/useLmStudioModels.ts index 79e46fe6cf..c045865181 100644 --- a/webview-ui/src/components/ui/hooks/useLmStudioModels.ts +++ b/webview-ui/src/components/ui/hooks/useLmStudioModels.ts @@ -1,12 +1,12 @@ import { useQuery } from "@tanstack/react-query" -import { type ModelRecord, type ExtensionMessage } from "@roo-code/types" +import { type ModelRecord, type ExtensionMessage, LmStudioModelsMessageType } from "@roo-code/types" import { vscode } from "@src/utils/vscode" export const requestLmStudioModels = (baseUrl?: string) => vscode.postMessage({ - type: "requestLmStudioModels", + type: LmStudioModelsMessageType.requestLmStudioModels, values: typeof baseUrl === "string" ? { baseUrl } : undefined, }) @@ -24,7 +24,7 @@ const getLmStudioModels = async (baseUrl?: string) => const handler = (event: MessageEvent) => { const message: ExtensionMessage = event.data - if (message.type === "lmStudioModels") { + if (message.type === LmStudioModelsMessageType.lmStudioModels) { clearTimeout(timeout) cleanup() diff --git a/webview-ui/src/components/ui/hooks/useOllamaModels.ts b/webview-ui/src/components/ui/hooks/useOllamaModels.ts index 80fc727f71..5f81ac6b89 100644 --- a/webview-ui/src/components/ui/hooks/useOllamaModels.ts +++ b/webview-ui/src/components/ui/hooks/useOllamaModels.ts @@ -1,6 +1,6 @@ import { useQuery } from "@tanstack/react-query" -import { type ModelRecord, type ExtensionMessage } from "@roo-code/types" +import { type ModelRecord, type ExtensionMessage, OllamaModelsMessageType } from "@roo-code/types" import { vscode } from "@src/utils/vscode" @@ -18,7 +18,7 @@ const getOllamaModels = async () => const handler = (event: MessageEvent) => { const message: ExtensionMessage = event.data - if (message.type === "ollamaModels") { + if (message.type === OllamaModelsMessageType.ollamaModels) { clearTimeout(timeout) cleanup() @@ -31,7 +31,7 @@ const getOllamaModels = async () => } window.addEventListener("message", handler) - vscode.postMessage({ type: "requestOllamaModels" }) + vscode.postMessage({ type: OllamaModelsMessageType.requestOllamaModels }) }) export const useOllamaModels = (modelId?: string) => diff --git a/webview-ui/src/components/ui/hooks/useRouterModels.ts b/webview-ui/src/components/ui/hooks/useRouterModels.ts index 5a562c6a48..a7d6b36725 100644 --- a/webview-ui/src/components/ui/hooks/useRouterModels.ts +++ b/webview-ui/src/components/ui/hooks/useRouterModels.ts @@ -1,6 +1,11 @@ import { useQuery } from "@tanstack/react-query" -import { type RouterModels, type ExtensionMessage } from "@roo-code/types" +import { + allRouterModelsProvider, + RouterModelsMessageType, + type RouterModels, + type ExtensionMessage, +} from "@roo-code/types" import { vscode } from "@src/utils/vscode" @@ -25,7 +30,7 @@ export const fetchRouterModels = async (provider?: string) => const handler = (event: MessageEvent) => { const message: ExtensionMessage = event.data - if (message.type === "routerModels") { + if (message.type === RouterModelsMessageType.routerModels) { const msgProvider = message?.values?.provider as string | undefined // Verify response matches request @@ -47,16 +52,16 @@ export const fetchRouterModels = async (provider?: string) => window.addEventListener("message", handler) if (provider) { - vscode.postMessage({ type: "requestRouterModels", values: { provider } }) + vscode.postMessage({ type: RouterModelsMessageType.requestRouterModels, values: { provider } }) } else { - vscode.postMessage({ type: "requestRouterModels" }) + vscode.postMessage({ type: RouterModelsMessageType.requestRouterModels }) } }) export const useRouterModels = (opts: UseRouterModelsOptions = {}) => { const provider = opts.provider || undefined return useQuery({ - queryKey: ["routerModels", provider || "all"], + queryKey: [RouterModelsMessageType.routerModels, provider || allRouterModelsProvider], queryFn: () => fetchRouterModels(provider), enabled: opts.enabled !== false, }) diff --git a/webview-ui/src/components/ui/hooks/useZooGatewayRouterModelsSync.ts b/webview-ui/src/components/ui/hooks/useZooGatewayRouterModelsSync.ts index 3fa81aa101..b56960bcb2 100644 --- a/webview-ui/src/components/ui/hooks/useZooGatewayRouterModelsSync.ts +++ b/webview-ui/src/components/ui/hooks/useZooGatewayRouterModelsSync.ts @@ -1,7 +1,13 @@ import { useCallback, useEffect, useRef } from "react" import { useQueryClient } from "@tanstack/react-query" -import { type ExtensionMessage, type RouterModels, providerIdentifiers } from "@roo-code/types" +import { + allRouterModelsProvider, + RouterModelsMessageType, + type ExtensionMessage, + type RouterModels, + providerIdentifiers, +} from "@roo-code/types" import { useExtensionState } from "@src/context/ExtensionStateContext" @@ -28,8 +34,9 @@ export function useZooGatewayRouterModelsSync() { return } - queryClient.setQueryData(["routerModels", "all"], (current) => - current ? { ...current, [providerIdentifiers.zooGateway]: zooModels } : partial, + queryClient.setQueryData( + [RouterModelsMessageType.routerModels, allRouterModelsProvider], + (current) => (current ? { ...current, [providerIdentifiers.zooGateway]: zooModels } : partial), ) } catch { // Ignore: bulk router fetch may still be in flight. diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index a672abbdc1..b7fe5a9004 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -18,6 +18,7 @@ import { type Command, type McpServer, RouterModels, + RouterModelsMessageType, ORGANIZATION_ALLOW_ALL, DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, DEFAULT_DIFF_FUZZY_THRESHOLD, @@ -444,7 +445,7 @@ export const ExtensionStateContextProvider: React.FC<{ setListApiConfigMeta(message.listApiConfig ?? []) break } - case "routerModels": { + case RouterModelsMessageType.routerModels: { const provider = message.values?.provider as string | undefined const incoming = message.routerModels if (provider && incoming) { From 5b6a50614610044f1716c025ec982dce65ce398e Mon Sep 17 00:00:00 2001 From: Para <62068271+murd0cc@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:55:07 +0300 Subject: [PATCH 25/66] coverage --- .../__tests__/AutoApproveSettings.manualSnapshots.fixture.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.manualSnapshots.fixture.tsx b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.manualSnapshots.fixture.tsx index 8d7a745462..0475258609 100644 --- a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.manualSnapshots.fixture.tsx +++ b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.manualSnapshots.fixture.tsx @@ -1,3 +1,4 @@ +/* v8 ignore file -- Manual PNG fixtures are baseline assets, not behavior under test. */ import React from "react" import screenshot1 from "./__screenshots__/screenshot-1-.png" From 3e8144a329d6aad60bfde80a9a890c9e8b7154e8 Mon Sep 17 00:00:00 2001 From: "zoomote[bot]" <305051434+zoomote[bot]@users.noreply.github.com> Date: Tue, 18 Aug 2026 18:55:15 +0000 Subject: [PATCH 26/66] feat(api): support official GLM-5.3 Z.ai release (#1284) Co-authored-by: @taltas <6816042+taltas@users.noreply.github.com> --- packages/types/src/providers/zai.ts | 54 +++++++------- src/api/providers/__tests__/zai.spec.ts | 36 +++++++-- src/api/providers/zai.ts | 73 +++++++++++++------ .../__tests__/providerModelConfig.spec.ts | 4 +- .../hooks/__tests__/useSelectedModel.spec.ts | 25 +++++-- 5 files changed, 126 insertions(+), 66 deletions(-) diff --git a/packages/types/src/providers/zai.ts b/packages/types/src/providers/zai.ts index a14edfe9e3..79af21d8dc 100644 --- a/packages/types/src/providers/zai.ts +++ b/packages/types/src/providers/zai.ts @@ -11,6 +11,21 @@ import { ZaiApiLine } from "../provider-settings.js" // https://docs.z.ai/guides/overview/pricing // https://bigmodel.cn/pricing +const glm53ModelInfo = { + maxTokens: 131_072, + contextWindow: 1_000_000, + supportsImages: false, + supportsPromptCache: true, + supportsMaxTokens: true, + supportsReasoningEffort: ["low", "high", "max"], + requiredReasoningEffort: true, + reasoningEffort: "max", + preserveReasoning: true, + defaultTemperature: 1, + description: + "GLM-5.3 is Zhipu's flagship coding and agent model with a 1M context window, 128k max output, and always-on reasoning with configurable effort (Low/High/Max).", +} as const satisfies ModelInfo + export type InternationalZAiModelId = keyof typeof internationalZAiModels export const internationalZAiDefaultModelId: InternationalZAiModelId = "glm-4.7" export const internationalZAiModels = { @@ -171,6 +186,13 @@ export const internationalZAiModels = { description: "GLM-5.2 is Zhipu's flagship model with a 1M context window, 128k max output, and dual thinking-effort modes (High/Max). It delivers top-tier long-context reasoning, coding, and agentic performance for extended engineering sessions.", }, + "glm-5.3": { + ...glm53ModelInfo, + inputPrice: 1.4, + outputPrice: 4.4, + cacheWritesPrice: 0, + cacheReadsPrice: 0.26, + }, "glm-5-turbo": { maxTokens: 131_072, contextWindow: 202_752, @@ -474,34 +496,9 @@ export const mainlandZAiModels = { }, } as const satisfies Record -const glm53CodingPlanModelInfo = { - maxTokens: 131_072, - contextWindow: 1_000_000, - supportsImages: false, - supportsPromptCache: true, - supportsMaxTokens: true, - supportsReasoningEffort: ["low", "high", "max"], - requiredReasoningEffort: true, - reasoningEffort: "max", - preserveReasoning: true, - description: - "GLM-5.3 is Zhipu's flagship coding and agent model with a 1M context window, 128k max output, and always-on reasoning with configurable effort (Low/High/Max). Available to GLM Coding Plan users.", -} as const satisfies ModelInfo - -export const internationalZAiCodingPlanOnlyModels = { - "glm-5.3": { - ...glm53CodingPlanModelInfo, - // GLM-5.3 API pricing is not published yet; use GLM-5.2 pricing provisionally. - inputPrice: 1.4, - outputPrice: 4.4, - cacheWritesPrice: 0, - cacheReadsPrice: 0.26, - }, -} as const satisfies Record - export const mainlandZAiCodingPlanOnlyModels = { "glm-5.3": { - ...glm53CodingPlanModelInfo, + ...glm53ModelInfo, // GLM-5.3 API pricing is not published yet; use GLM-5.2 pricing provisionally. inputPrice: 0.68, outputPrice: 2.28, @@ -538,6 +535,7 @@ export const zaiApiLineConfigs = { export function getZAiModels(apiLine: ZaiApiLine = "international_coding"): Record { const isChina = zaiApiLineConfigs[apiLine].isChina const regionalModels = isChina ? mainlandZAiModels : internationalZAiModels - const codingPlanOnlyModels = isChina ? mainlandZAiCodingPlanOnlyModels : internationalZAiCodingPlanOnlyModels - return apiLine.endsWith("_coding") ? { ...regionalModels, ...codingPlanOnlyModels } : regionalModels + return isChina && apiLine.endsWith("_coding") + ? { ...regionalModels, ...mainlandZAiCodingPlanOnlyModels } + : regionalModels } diff --git a/src/api/providers/__tests__/zai.spec.ts b/src/api/providers/__tests__/zai.spec.ts index 440bbc2328..0230b679a9 100644 --- a/src/api/providers/__tests__/zai.spec.ts +++ b/src/api/providers/__tests__/zai.spec.ts @@ -142,7 +142,7 @@ describe("ZAiHandler", () => { expect(model.info.cacheReadsPrice).toBe(0.26) }) - it("should expose GLM-5.3 for the international Coding Plan with provisional GLM-5.2 pricing", () => { + it("should expose GLM-5.3 for the international Coding Plan with official pricing", () => { const handlerWithModel = new ZAiHandler({ apiModelId: "glm-5.3", zaiApiKey: "test-zai-api-key", @@ -160,6 +160,7 @@ describe("ZAiHandler", () => { requiredReasoningEffort: true, reasoningEffort: "max", preserveReasoning: true, + defaultTemperature: 1, }) expect(model.info.inputPrice).toBe(1.4) expect(model.info.outputPrice).toBe(4.4) @@ -390,14 +391,14 @@ describe("ZAiHandler", () => { expect(model.info).toEqual(internationalZAiModels[testModelId]) }) - it("should not expose Coding Plan-only models", () => { - expect(getZAiModels("international_api")).not.toHaveProperty("glm-5.3") + it("should expose GLM-5.3 on the international API", () => { + expect(getZAiModels("international_api")).toHaveProperty("glm-5.3") const handlerWithModel = new ZAiHandler({ apiModelId: "glm-5.3", zaiApiKey: "test-zai-api-key", zaiApiLine: "international_api", }) - expect(handlerWithModel.getModel().id).toBe(internationalZAiDefaultModelId) + expect(handlerWithModel.getModel().id).toBe("glm-5.3") }) }) @@ -668,7 +669,7 @@ describe("ZAiHandler", () => { ) }) - it("should keep GLM-5.3 reasoning enabled when a persisted setting requests disable", async () => { + it("should use the official GLM-5.3 thinking and sampling defaults", async () => { const handlerWithModel = new ZAiHandler({ apiModelId: "glm-5.3", zaiApiKey: "test-zai-api-key", @@ -684,8 +685,9 @@ describe("ZAiHandler", () => { expect(mockCreate).toHaveBeenCalledWith( expect.objectContaining({ model: "glm-5.3", - thinking: { type: "enabled" }, + thinking: { type: "enabled", clear_thinking: false }, reasoning_effort: "max", + temperature: 1, }), ) }) @@ -706,12 +708,32 @@ describe("ZAiHandler", () => { expect(mockCreate).toHaveBeenCalledWith( expect.objectContaining({ model: "glm-5.3", - thinking: { type: "enabled" }, + thinking: { type: "enabled", clear_thinking: false }, reasoning_effort: "max", }), ) }) + it("should use the official GLM-5.3 parameters for completePrompt", async () => { + const handlerWithModel = new ZAiHandler({ + apiModelId: "glm-5.3", + zaiApiKey: "test-zai-api-key", + zaiApiLine: "international_api", + reasoningEffort: "low", + }) + + mockCreate.mockResolvedValueOnce({ choices: [{ message: { content: "response" } }] }) + + await expect(handlerWithModel.completePrompt("prompt")).resolves.toBe("response") + expect(mockCreate).toHaveBeenCalledWith({ + model: "glm-5.3", + messages: [{ role: "user", content: "prompt" }], + temperature: 1, + thinking: { type: "enabled", clear_thinking: false }, + reasoning_effort: "low", + }) + }) + it("should omit reasoning_effort for GLM-5.2 when reasoningEffort is set to disable", async () => { const handlerWithModel = new ZAiHandler({ apiModelId: "glm-5.2", diff --git a/src/api/providers/zai.ts b/src/api/providers/zai.ts index 65a6bf458c..5ebc0e19a3 100644 --- a/src/api/providers/zai.ts +++ b/src/api/providers/zai.ts @@ -13,7 +13,7 @@ import { import { type ApiHandlerOptions, getModelMaxOutputTokens } from "../../shared/api" import { convertToZAiFormat } from "../transform/zai-format" -import type { ApiHandlerCreateMessageMetadata } from "../index" +import type { ApiHandlerCreateMessageMetadata, CompletePromptOptions } from "../index" import { BaseOpenAiCompatibleProvider } from "./base-openai-compatible-provider" import { handleOpenAIError } from "./utils/error-handler" @@ -21,8 +21,8 @@ import { handleOpenAIError } from "./utils/error-handler" // Z.ai accepts the standard `reasoning_effort` ladder (none/minimal/low/medium/high/xhigh/max) // alongside the GLM-specific `thinking` toggle. Omit the OpenAI-typed `reasoning_effort` so we // can widen it to include provider-specific values such as "max". -type ZAiChatCompletionParams = Omit & { - thinking?: { type: "enabled" | "disabled" } +type ZAiChatCompletionParams = Omit & { + thinking?: { type: "enabled" | "disabled"; clear_thinking?: boolean } reasoning_effort?: "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max" } @@ -78,22 +78,7 @@ export class ZAiHandler extends BaseOpenAiCompatibleProvider { metadata?: ApiHandlerCreateMessageMetadata, ) { const { id: model, info } = this.getModel() - - // Fall back to the model default when the resolved effort isn't supported by the model. - const supported = info.supportsReasoningEffort - const raw = - this.options.enableReasoningEffort === false - ? undefined - : (this.options.reasoningEffort ?? info.reasoningEffort) - const requiresReasoning = info.requiredReasoningEffort === true - const effort = - requiresReasoning && (!raw || raw === "disable") - ? info.reasoningEffort - : raw && Array.isArray(supported) && !supported.includes(raw) - ? info.reasoningEffort - : raw - const reasoningEffort = effort && effort !== "disable" ? effort : undefined - const useReasoning = requiresReasoning || reasoningEffort !== undefined + const { reasoningEffort, useReasoning } = this.getReasoningSettings(info) const max_tokens = this.options.modelMaxTokens || @@ -105,7 +90,7 @@ export class ZAiHandler extends BaseOpenAiCompatibleProvider { }) ?? undefined) - const temperature = this.options.modelTemperature ?? this.defaultTemperature + const temperature = this.options.modelTemperature ?? info.defaultTemperature ?? this.defaultTemperature // Use Z.ai format to preserve reasoning_content and merge post-tool text into tool messages const convertedMessages = convertToZAiFormat(messages, { mergeToolResultText: true }) @@ -118,7 +103,9 @@ export class ZAiHandler extends BaseOpenAiCompatibleProvider { stream: true, stream_options: { include_usage: true }, // Models with required reasoning stay enabled even when an old setting requests disable. - thinking: useReasoning ? { type: "enabled" } : { type: "disabled" }, + thinking: useReasoning + ? { type: "enabled", ...(model === "glm-5.3" && { clear_thinking: false }) } + : { type: "disabled" }, reasoning_effort: reasoningEffort, tools: this.convertToolsForOpenAI(metadata?.tools), tool_choice: metadata?.tool_choice, @@ -133,4 +120,48 @@ export class ZAiHandler extends BaseOpenAiCompatibleProvider { throw handleOpenAIError(error, this.providerName) } } + + private getReasoningSettings(info: ModelInfo) { + // Fall back to the model default when the resolved effort isn't supported by the model. + const supported = info.supportsReasoningEffort + const raw = + this.options.enableReasoningEffort === false + ? undefined + : (this.options.reasoningEffort ?? info.reasoningEffort) + const requiresReasoning = info.requiredReasoningEffort === true + const effort = + requiresReasoning && (!raw || raw === "disable") + ? info.reasoningEffort + : raw && Array.isArray(supported) && !supported.includes(raw) + ? info.reasoningEffort + : raw + const reasoningEffort = effort && effort !== "disable" ? effort : undefined + + return { reasoningEffort, useReasoning: requiresReasoning || reasoningEffort !== undefined } + } + + override async completePrompt(prompt: string, options?: CompletePromptOptions): Promise { + const { id: model, info } = this.getModel() + if (model !== "glm-5.3") { + return super.completePrompt(prompt, options) + } + + const { reasoningEffort } = this.getReasoningSettings(info) + const params: ZAiChatCompletionParams = { + model, + messages: [{ role: "user", content: prompt }], + temperature: this.options.modelTemperature ?? info.defaultTemperature ?? this.defaultTemperature, + thinking: { type: "enabled", clear_thinking: false }, + reasoning_effort: reasoningEffort, + } + + try { + const response = await this.client.chat.completions.create( + params as OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming, + ) + return response.choices?.[0]?.message.content || "" + } catch (error) { + throw handleOpenAIError(error, this.providerName) + } + } } diff --git a/webview-ui/src/components/settings/utils/__tests__/providerModelConfig.spec.ts b/webview-ui/src/components/settings/utils/__tests__/providerModelConfig.spec.ts index e19df545e5..2bd91f19aa 100644 --- a/webview-ui/src/components/settings/utils/__tests__/providerModelConfig.spec.ts +++ b/webview-ui/src/components/settings/utils/__tests__/providerModelConfig.spec.ts @@ -206,7 +206,7 @@ describe("providerModelConfig", () => { expect(Object.keys(models).length).toBe(0) }) - it("shows GLM-5.3 only for Z.ai Coding Plan entrypoints", () => { + it("shows GLM-5.3 for international Z.ai API and Coding Plan entrypoints", () => { const internationalCoding = getStaticModelsForProvider("zai", undefined, { apiProvider: "zai", zaiApiLine: "international_coding", @@ -226,7 +226,7 @@ describe("providerModelConfig", () => { expect(internationalCoding).toHaveProperty("glm-5.3") expect(chinaCoding).toHaveProperty("glm-5.3") - expect(internationalApi).not.toHaveProperty("glm-5.3") + expect(internationalApi).toHaveProperty("glm-5.3") expect(chinaApi).not.toHaveProperty("glm-5.3") }) }) diff --git a/webview-ui/src/components/ui/hooks/__tests__/useSelectedModel.spec.ts b/webview-ui/src/components/ui/hooks/__tests__/useSelectedModel.spec.ts index dbc52e390b..3558d47e38 100644 --- a/webview-ui/src/components/ui/hooks/__tests__/useSelectedModel.spec.ts +++ b/webview-ui/src/components/ui/hooks/__tests__/useSelectedModel.spec.ts @@ -33,7 +33,6 @@ import { lMStudioDefaultModelInfo, opencodeGoDefaultModelInfo, getZAiModels, - internationalZAiDefaultModelId, mainlandZAiDefaultModelId, providerIdentifiers, retiredProviderIdentifiers, @@ -1355,20 +1354,30 @@ describe("useSelectedModel", () => { expect(result.current.info?.inputPrice).toBe(0.68) }) - it.each([ - ["international_api", internationalZAiDefaultModelId], - ["china_api", mainlandZAiDefaultModelId], - ] as const)("falls back when GLM-5.3 is unavailable on %s", (zaiApiLine, expectedModelId) => { + it("uses the International API catalog for GLM-5.3", () => { const apiConfiguration: ProviderSettings = { apiProvider: providerIdentifiers.zai, apiModelId: "glm-5.3", - zaiApiLine, + zaiApiLine: "international_api", } const { result } = renderHook(() => useSelectedModel(apiConfiguration), { wrapper: createWrapper() }) - expect(result.current.id).toBe(expectedModelId) - expect(result.current.info).toEqual(getZAiModels(zaiApiLine)[expectedModelId]) + expect(result.current.id).toBe("glm-5.3") + expect(result.current.info).toEqual(getZAiModels("international_api")["glm-5.3"]) + }) + + it("falls back when GLM-5.3 is unavailable on the China API", () => { + const apiConfiguration: ProviderSettings = { + apiProvider: providerIdentifiers.zai, + apiModelId: "glm-5.3", + zaiApiLine: "china_api", + } + + const { result } = renderHook(() => useSelectedModel(apiConfiguration), { wrapper: createWrapper() }) + + expect(result.current.id).toBe(mainlandZAiDefaultModelId) + expect(result.current.info).toEqual(getZAiModels("china_api")[mainlandZAiDefaultModelId]) }) }) From dbad4af1058fa2949ff79c81254b6d784b5bb69d Mon Sep 17 00:00:00 2001 From: eason liang <136036952+easonLiangWorldedtech@users.noreply.github.com> Date: Tue, 18 Aug 2026 23:12:37 +0000 Subject: [PATCH 27/66] feat(api): introduce RequestConfigBuilder for SDK-agnostic abort signal support (#1008) * feat(api): add RequestConfigBuilder class for SDK-agnostic request configuration Body: Implement generic request configuration builder with chainable methods (addAbortSignal, addHeaders, setOption), static factory methods (fromMetadata, mergeAbortSignals), and 40 unit tests. * docs(config-builder): enhance README with generic architecture design and multi-SDK examples * fix(config-builder): fix broken TOC link and simplify mergeAbortSignals early-abort - Fix README TOC: change #how-mergesignals-works to #how-mergeabortsignals-works to match the actual heading anchor - Simplify mergeAbortSignals: return primarySignal directly when it's already aborted instead of creating a new AbortController * fix: addHeaders default param and mergeAbortSignals order in RequestConfigBuilder (#615) - Add default empty object parameter to addHeaders() so calling with undefined no longer throws TypeError from Object.keys(undefined) - Reorder mergeAbortSignals to check primarySignal.aborted before allocating AbortController, preventing unnecessary controller creation * refactor: use AbortSignal.any() for mergeAbortSignals * feat(api): add abort signal builder utilities * fix(api): prevent cleanup leaking into request config * fix(api): chain request config cleanup * docs(api): remove config builder readme * fix(api): relax request config option constraints * fix(api): address review feedback on request config builder - rename addAbortSignal to setAbortSignal and document replace semantics - type build()/fromMetadata() as Partial | undefined - drop static mergeAbortSignals delegation in favor of the exported utility - cover internal-controller abort propagation through addMergedSignal - cover timeout-alone and primary-signal abort cases in abort-signal tests * refactor(api): use native AbortSignal.timeout() in mergeAbortSignalAndTimeout Replace the hand-rolled setTimeout/clearTimeout with AbortSignal.timeout(), which self-manages its timer. This removes the MergedAbortSignal cleanup contract and the leak risk when a caller forgets to run it, matching existing usage in zoo-code-auth, mcp oauth, and openai-codex oauth. - mergeAbortSignalAndTimeout now returns AbortSignal | undefined - RequestConfigBuilder drops getCleanup()/cleanupFn accumulation * fix(api): isolate builder headers and harden config-builder tests --------- Co-authored-by: Eason Liang Co-authored-by: Elliott de Launay --- .../__tests__/request-config-builder.spec.ts | 508 ++++++++++++++++++ .../config-builder/request-config-builder.ts | 166 ++++++ src/api/providers/index.ts | 1 + .../utils/__tests__/abort-signal.spec.ts | 102 ++++ src/api/providers/utils/abort-signal.ts | 37 ++ src/test-utils/api.ts | 14 + 6 files changed, 828 insertions(+) create mode 100644 src/api/providers/__tests__/request-config-builder.spec.ts create mode 100644 src/api/providers/config-builder/request-config-builder.ts create mode 100644 src/api/providers/utils/__tests__/abort-signal.spec.ts create mode 100644 src/api/providers/utils/abort-signal.ts diff --git a/src/api/providers/__tests__/request-config-builder.spec.ts b/src/api/providers/__tests__/request-config-builder.spec.ts new file mode 100644 index 0000000000..977b09df6b --- /dev/null +++ b/src/api/providers/__tests__/request-config-builder.spec.ts @@ -0,0 +1,508 @@ +import { describe, expect, test, vi } from "vitest" + +import { makeCreateMessageMetadata } from "../../../test-utils/api" +import { RequestConfigBuilder } from "../config-builder/request-config-builder" + +describe("RequestConfigBuilder", () => { + describe("constructor", () => { + test("should initialize with empty options by default", () => { + const builder = new RequestConfigBuilder() + expect(builder.build()).toBeUndefined() + }) + + test("should initialize with provided defaultOptions", () => { + const defaults = { modelId: "test-model" } + const builder = new RequestConfigBuilder(defaults) + const result = builder.build() + expect(result).toEqual({ modelId: "test-model" }) + }) + + test("should create a shallow copy of defaultOptions", () => { + const defaults = { modelId: "test-model" } + const builder = new RequestConfigBuilder(defaults) + defaults.modelId = "modified-model" + const result = builder.build() + expect(result?.modelId).toBe("test-model") + }) + + test("should ignore undefined values from defaultOptions", () => { + const builder = new RequestConfigBuilder({ modelId: undefined }) + + expect(builder.build()).toBeUndefined() + }) + + test("should keep falsy-but-defined values", () => { + const builder = new RequestConfigBuilder({ count: 0, enabled: false, label: "" }) + + expect(builder.build()).toEqual({ count: 0, enabled: false, label: "" }) + }) + + test("should not alias the caller's default headers", () => { + const defaults = { headers: { A: "1" } } + const builder = new RequestConfigBuilder(defaults) + + defaults.headers.A = "2" + + expect(builder.getOption("headers")).toEqual({ A: "1" }) + }) + }) + + describe("setAbortSignal", () => { + test("should set signal when metadata contains abortSignal", () => { + const controller = new AbortController() + const metadata = makeCreateMessageMetadata({ abortSignal: controller.signal }) + + const builder = new RequestConfigBuilder() + const result = builder.setAbortSignal(metadata) + + expect(result).toBe(builder) // chainable + const config = builder.build() as { signal?: AbortSignal } + expect(config?.signal).toBe(controller.signal) + }) + + test("should do nothing when metadata is undefined", () => { + const builder = new RequestConfigBuilder({ initial: "value" }) + builder.setAbortSignal(undefined) + + const config = builder.build() as { signal?: AbortSignal } + expect(config.signal).toBeUndefined() + }) + + test("should do nothing when metadata.abortSignal is undefined", () => { + const metadata = makeCreateMessageMetadata() + + const builder = new RequestConfigBuilder({ initial: "value" }) + builder.setAbortSignal(metadata) + + const config = builder.build() as { signal?: AbortSignal } + expect(config.signal).toBeUndefined() + }) + + test("should replace existing signal if metadata contains abortSignal", () => { + const controller1 = new AbortController() + const controller2 = new AbortController() + + const builder = new RequestConfigBuilder({ signal: controller1.signal }) + builder.setAbortSignal(makeCreateMessageMetadata({ abortSignal: controller2.signal })) + + const config = builder.build() as { signal?: AbortSignal } + expect(config?.signal).toBe(controller2.signal) + }) + + test("should support chaining with other methods", () => { + const controller = new AbortController() + const metadata = makeCreateMessageMetadata({ abortSignal: controller.signal }) + + const builder = new RequestConfigBuilder() + const result = builder.setAbortSignal(metadata).setOption("customKey", "customValue") + + expect(result).toBe(builder) + const config = builder.build() as { signal?: AbortSignal; customKey?: string } + expect(config?.signal).toBe(controller.signal) + expect(config?.customKey).toBe("customValue") + }) + }) + + describe("addHeaders", () => { + test("should merge headers when provided", () => { + const builder = new RequestConfigBuilder() + const result = builder.addHeaders({ "X-Custom": "value1" }) + + expect(result).toBe(builder) // chainable + const config = builder.build() as { headers?: Record } + expect(config?.headers).toEqual({ "X-Custom": "value1" }) + }) + + test("should do nothing when headers are undefined", () => { + const builder = new RequestConfigBuilder({ initial: "value" }) + const result = builder.addHeaders() + + expect(result).toBe(builder) // chainable + const config = builder.build() as { headers?: Record } + expect(config.headers).toBeUndefined() + }) + + test("should do nothing when headers object is empty", () => { + const builder = new RequestConfigBuilder({ initial: "value" }) + const result = builder.addHeaders({}) + + expect(result).toBe(builder) // chainable + const config = builder.build() as { headers?: Record } + expect(config.headers).toBeUndefined() + }) + + test("should override existing header values", () => { + const builder = new RequestConfigBuilder({ headers: { "X-Existing": "old" } }) + builder.addHeaders({ "X-Existing": "new" }) + + const config = builder.build() as { headers?: Record } + expect(config?.headers?.["X-Existing"]).toBe("new") + }) + + test("should merge with existing headers without overwriting unrelated keys", () => { + const builder = new RequestConfigBuilder({ headers: { "X-Existing": "value" } }) + builder.addHeaders({ "X-New": "newValue" }) + + const config = builder.build() as { headers?: Record } + expect(config?.headers).toEqual({ "X-Existing": "value", "X-New": "newValue" }) + }) + + test("should create headers object if none exists", () => { + const builder = new RequestConfigBuilder() + builder.addHeaders({ "X-Custom": "value" }) + + const config = builder.build() as { headers?: Record } + expect(config?.headers).toEqual({ "X-Custom": "value" }) + }) + + test("should support chaining with other methods", () => { + const builder = new RequestConfigBuilder() + builder.addHeaders({ "X-First": "1" }).addHeaders({ "X-Second": "2" }) + + const config = builder.build() as { headers?: Record } + expect(config?.headers).toEqual({ "X-First": "1", "X-Second": "2" }) + }) + }) + + describe("setOption", () => { + test("should set option when value is defined", () => { + const builder = new RequestConfigBuilder() + const result = builder.setOption("modelId", "test-model") + + expect(result).toBe(builder) // chainable + const config = builder.build() as { modelId?: string } + expect(config?.modelId).toBe("test-model") + }) + + test("should do nothing when value is undefined", () => { + const builder = new RequestConfigBuilder({ initial: "value" }) + builder.setOption("initial", undefined as unknown as string) + + const config = builder.build() as { initial?: string } + // When setOption receives undefined, it should NOT modify the existing value + expect(config.initial).toBe("value") + }) + + test("should replace existing option value", () => { + const builder = new RequestConfigBuilder({ modelId: "old-model" }) + builder.setOption("modelId", "new-model") + + const config = builder.build() as { modelId?: string } + expect(config?.modelId).toBe("new-model") + }) + + test("should support different value types", () => { + const builder = new RequestConfigBuilder() + + builder.setOption("stringKey", "stringValue") + builder.setOption("numberKey", 42) + builder.setOption("booleanKey", true) + builder.setOption("objectKey", { nested: true }) + + const config = builder.build() as { + stringKey?: string + numberKey?: number + booleanKey?: boolean + objectKey?: { nested: boolean } + } + expect(config.stringKey).toBe("stringValue") + expect(config.numberKey).toBe(42) + expect(config.booleanKey).toBe(true) + expect(config.objectKey).toEqual({ nested: true }) + }) + + test("should keep falsy-but-defined values", () => { + const builder = new RequestConfigBuilder() + builder.setOption("count", 0).setOption("enabled", false).setOption("label", "") + + const config = builder.build() as { count?: number; enabled?: boolean; label?: string } + expect(config.count).toBe(0) + expect(config.enabled).toBe(false) + expect(config.label).toBe("") + }) + + test("should support chaining", () => { + const builder = new RequestConfigBuilder() + const result = builder.setOption("key1", "value1").setOption("key2", "value2") + + expect(result).toBe(builder) + const config = builder.build() as { key1?: string; key2?: string } + expect(config.key1).toBe("value1") + expect(config.key2).toBe("value2") + }) + }) + + describe("getOption", () => { + test("should return existing option value", () => { + const builder = new RequestConfigBuilder({ modelId: "test-model" }) + expect(builder.getOption("modelId")).toBe("test-model") + }) + + test("should return undefined for non-existent key", () => { + const builder = new RequestConfigBuilder() + expect(builder.getOption("nonExistent")).toBeUndefined() + }) + }) + + describe("build", () => { + test("should return shallow copy of options", () => { + const builder = new RequestConfigBuilder({ key: "value" }) + const result1 = builder.build() + const result2 = builder.build() + + expect(result1).toEqual(result2) + expect(result1).not.toBe(result2) // different references + }) + + test("should return undefined when options are empty", () => { + const builder = new RequestConfigBuilder() + expect(builder.build()).toBeUndefined() + }) + + test("modifying build result should not affect internal state", () => { + const builder = new RequestConfigBuilder({ key: "value" }) + const result = builder.build() as { key: string } + + result.key = "modified" + expect(builder.getOption("key")).toBe("value") + }) + + test("mutating returned headers should not affect internal state", () => { + const builder = new RequestConfigBuilder({ headers: { Authorization: "Bearer x" } }) + const config = builder.build() as { headers?: Record } + + config.headers!.Authorization = "TAMPERED" + + expect(builder.getOption("headers")).toEqual({ Authorization: "Bearer x" }) + }) + + test("should return all set options", () => { + const controller = new AbortController() + const metadata = makeCreateMessageMetadata({ abortSignal: controller.signal }) + + const builder = new RequestConfigBuilder() + builder.setAbortSignal(metadata).addHeaders({ "X-Custom": "value" }).setOption("modelId", "test-model") + + const config = builder.build() as { + signal?: AbortSignal + headers?: Record + modelId?: string + } + expect(config.signal).toBe(controller.signal) + expect(config.headers).toEqual({ "X-Custom": "value" }) + expect(config.modelId).toBe("test-model") + }) + }) + + describe("static fromMetadata", () => { + test("should return undefined when both metadata and extraOptions are undefined", () => { + const result = RequestConfigBuilder.fromMetadata() + expect(result).toBeUndefined() + }) + + test("should set signal from metadata.abortSignal", () => { + const controller = new AbortController() + const metadata = makeCreateMessageMetadata({ abortSignal: controller.signal }) + + const result = RequestConfigBuilder.fromMetadata(metadata) as { signal?: AbortSignal } + expect(result.signal).toBe(controller.signal) + }) + + test("should merge extraOptions with metadata signal", () => { + const controller = new AbortController() + const metadata = makeCreateMessageMetadata({ abortSignal: controller.signal }) + const extraOptions = { modelId: "test-model", customKey: "customValue" } + + const result = RequestConfigBuilder.fromMetadata(metadata, extraOptions) as { + signal?: AbortSignal + modelId?: string + customKey?: string + } + expect(result.signal).toBe(controller.signal) + expect(result.modelId).toBe("test-model") + expect(result.customKey).toBe("customValue") + }) + + test("should return only extraOptions when metadata is undefined", () => { + const extraOptions = { modelId: "test-model" } + const result = RequestConfigBuilder.fromMetadata(undefined, extraOptions) as { modelId?: string } + expect(result.modelId).toBe("test-model") + }) + + test("should treat undefined extraOptions values as absent", () => { + const result = RequestConfigBuilder.fromMetadata(undefined, { signal: undefined }) + + expect(result).toBeUndefined() + }) + + test("should not set signal when metadata.abortSignal is undefined", () => { + const metadata = makeCreateMessageMetadata() + const extraOptions = { modelId: "test-model" } + + const result = RequestConfigBuilder.fromMetadata(metadata, extraOptions) as { + signal?: AbortSignal + modelId?: string + } + expect(result.signal).toBeUndefined() + expect(result.modelId).toBe("test-model") + }) + }) + + describe("addMergedSignal", () => { + test("should add internal controller signal when metadata and timeout are absent", () => { + const internalController = new AbortController() + const builder = new RequestConfigBuilder() + + const result = builder.addMergedSignal(internalController) + + expect(result).toBe(builder) + const config = builder.build() as { signal?: AbortSignal } + expect(config.signal).toBe(internalController.signal) + }) + + test("should merge internal controller signal with metadata abort signal", () => { + const internalController = new AbortController() + const externalController = new AbortController() + const builder = new RequestConfigBuilder() + + builder.addMergedSignal( + internalController, + makeCreateMessageMetadata({ abortSignal: externalController.signal }), + ) + + const config = builder.build() as { signal?: AbortSignal } + expect(config.signal).not.toBe(internalController.signal) + expect(config.signal).not.toBe(externalController.signal) + + externalController.abort() + expect(config.signal?.aborted).toBe(true) + }) + + test("should abort merged signal when internal controller is aborted", () => { + const internalController = new AbortController() + const externalController = new AbortController() + const builder = new RequestConfigBuilder() + + builder.addMergedSignal( + internalController, + makeCreateMessageMetadata({ abortSignal: externalController.signal }), + ) + + const config = builder.build() as { signal?: AbortSignal } + expect(config.signal?.aborted).toBe(false) + + internalController.abort() + expect(config.signal?.aborted).toBe(true) + }) + + test("should abort merged signal after timeout elapses without manual cleanup", async () => { + const internalController = new AbortController() + const builder = new RequestConfigBuilder() + + builder.addMergedSignal(internalController, undefined, 50) + + const config = builder.build() as { signal?: AbortSignal } + expect(config.signal).not.toBe(internalController.signal) + expect(config.signal?.aborted).toBe(false) + + await vi.waitFor(() => expect(config.signal?.aborted).toBe(true)) + }) + + test("should immediately abort when metadata signal is already aborted", () => { + const internalController = new AbortController() + const externalController = new AbortController() + externalController.abort() + const builder = new RequestConfigBuilder() + + builder.addMergedSignal( + internalController, + makeCreateMessageMetadata({ abortSignal: externalController.signal }), + ) + + const config = builder.build() as { signal?: AbortSignal } + expect(config.signal?.aborted).toBe(true) + }) + + test("should propagate abort from internal controller when all three sources are merged", () => { + const internalController = new AbortController() + const externalController = new AbortController() + const builder = new RequestConfigBuilder() + + builder.addMergedSignal( + internalController, + makeCreateMessageMetadata({ abortSignal: externalController.signal }), + 10_000, + ) + + const config = builder.build() as { signal?: AbortSignal } + expect(config.signal?.aborted).toBe(false) + + internalController.abort() + expect(config.signal?.aborted).toBe(true) + }) + }) + + describe("integration tests", () => { + test("should support full chain of operations", () => { + const controller = new AbortController() + const metadata = makeCreateMessageMetadata({ abortSignal: controller.signal }) + + type TestOptions = { + modelId?: string + signal?: AbortSignal + headers?: Record + maxTokens?: number + } + + const builder = new RequestConfigBuilder({ modelId: "default-model" }) + builder.setAbortSignal(metadata) + builder.addHeaders({ "X-API-Key": "secret" }) + builder.setOption("maxTokens", 2000) + + const config = builder.build() as TestOptions + expect(config.modelId).toBe("default-model") + expect(config.signal).toBe(controller.signal) + expect(config.headers).toEqual({ "X-API-Key": "secret" }) + expect(config.maxTokens).toBe(2000) + }) + + test("should handle empty builder through full lifecycle", () => { + const builder = new RequestConfigBuilder() + expect(builder.build()).toBeUndefined() + expect(builder.getOption("anyKey")).toBeUndefined() + }) + + test("should work with custom default options type", () => { + type CustomOptions = { apiUrl: string; timeout: number; retryCount?: number } + + const defaults: Partial = { + apiUrl: "https://api.example.com", + timeout: 30000, + } + + const builder = new RequestConfigBuilder(defaults) + builder.setOption("retryCount", 3) + + const config = builder.build() as CustomOptions + expect(config.apiUrl).toBe("https://api.example.com") + expect(config.timeout).toBe(30000) + expect(config.retryCount).toBe(3) + }) + + test("should accept interface-based options without an index signature", () => { + interface SdkOptions { + modelId?: string + signal?: AbortSignal + headers?: Record + maxTokens?: number + } + + const builder = new RequestConfigBuilder({ modelId: "default-model" }) + builder.setOption("maxTokens", 2000) + + const config = builder.build() as SdkOptions + expect(config.modelId).toBe("default-model") + expect(config.maxTokens).toBe(2000) + }) + }) +}) diff --git a/src/api/providers/config-builder/request-config-builder.ts b/src/api/providers/config-builder/request-config-builder.ts new file mode 100644 index 0000000000..2201d735bc --- /dev/null +++ b/src/api/providers/config-builder/request-config-builder.ts @@ -0,0 +1,166 @@ +import type { ApiHandlerCreateMessageMetadata } from "../../index" +import { mergeAbortSignalAndTimeout, mergeAbortSignals } from "../utils/abort-signal" + +/** + * A generic, SDK-agnostic request configuration builder. + * + * Provides a fluent API for building request configurations with: + * - Chainable method calls + * - Generic type support (TOptions) + * - Abort signal handling + * - Header merging + * - Static factory methods + */ +type RequestConfigOptionsBase = object & { + headers?: Record + signal?: AbortSignal +} + +type RequestConfigOptions = RequestConfigOptionsBase & Record + +export class RequestConfigBuilder { + protected options: Partial + + constructor(defaultOptions?: Partial) { + if (!defaultOptions) { + this.options = {} + return + } + + const defined = Object.fromEntries( + Object.entries(defaultOptions).filter(([, value]) => value !== undefined), + ) as Partial + + // Own the headers object so later mutations of the caller's defaults do not leak in. + if (defined.headers) { + defined.headers = { ...defined.headers } + } + + this.options = defined + } + + /** + * Set the abort signal from metadata, replacing any previously configured + * signal (including one created by addMergedSignal). Use addMergedSignal to + * combine signals instead of overwriting them. + * + * @param metadata - Optional metadata containing an abortSignal + * @returns this for chainable calls + */ + setAbortSignal(metadata?: ApiHandlerCreateMessageMetadata): this { + if (!metadata?.abortSignal) { + return this + } + + this.options = { ...this.options, signal: metadata.abortSignal } + return this + } + + /** + * Add or merge custom headers. + * + * @param headers - Key-value pairs of header names and values + * @returns this for chainable calls + */ + addHeaders(headers?: Record): this { + if (!headers || Object.keys(headers).length === 0) { + return this + } + + const existingHeaders = this.options.headers ?? {} + this.options = { ...this.options, headers: { ...existingHeaders, ...headers } } + return this + } + + /** + * Merge an internal controller signal with an external metadata signal and optional timeout. + * + * Use this for providers that already maintain their own AbortController but also need + * to honor the request-level abort signal from metadata and/or a timeout. The timeout is + * created via the native AbortSignal.timeout() API, which self-manages its timer — no + * manual cleanup is required. + * + * @param internalController - Provider-owned AbortController for the current request + * @param metadata - Optional metadata containing an external abortSignal + * @param timeoutMs - Optional positive timeout in milliseconds; <= 0 disables timeout + * @returns this for chainable calls + */ + addMergedSignal( + internalController: AbortController, + metadata?: ApiHandlerCreateMessageMetadata, + timeoutMs?: number, + ): this { + const merged = mergeAbortSignalAndTimeout(metadata?.abortSignal, timeoutMs) + const signal = mergeAbortSignals(internalController.signal, merged) + + this.options = { ...this.options, signal } + return this + } + + /** + * Set a single option by key (type-safe). + * + * @param key - Option key + * @param value - Option value + * @returns this for chainable calls + */ + setOption(key: K, value: TOptions[K]): this { + if (value === undefined) { + return this + } + + this.options = { ...this.options, [key]: value } + return this + } + + /** + * Get an option by key. + * + * @param key - Option key + * @returns The option value or undefined if not set + */ + getOption(key: K): TOptions[K] | undefined { + return this.options[key] + } + + /** + * Build the final configuration object. + * + * Copies the top-level options and the nested headers object, so mutating the + * result does not change builder state. The abort signal is a live object and + * is shared by reference on purpose. Other nested option values are not cloned. + * Returns undefined if no options have been set. + * + * @returns A partial built configuration (only the options that were set) or + * undefined if empty + */ + build(): Partial | undefined { + const keys = Object.keys(this.options as object) + if (keys.length === 0) { + return undefined + } + + const result = { ...this.options } + if (result.headers) { + result.headers = { ...result.headers } + } + + return result + } + + /** + * Factory method to quickly create and configure a builder from metadata. + * + * @param metadata - Optional metadata containing an abortSignal + * @param extraOptions - Additional options to merge + * @returns The built configuration or undefined if empty + */ + static fromMetadata( + metadata?: ApiHandlerCreateMessageMetadata, + extraOptions?: Partial, + ): Partial | undefined { + const builder = new RequestConfigBuilder(extraOptions) + builder.setAbortSignal(metadata) + return builder.build() + } +} diff --git a/src/api/providers/index.ts b/src/api/providers/index.ts index 37fea799a5..8ba1eae382 100644 --- a/src/api/providers/index.ts +++ b/src/api/providers/index.ts @@ -1,3 +1,4 @@ +export { RequestConfigBuilder } from "./config-builder/request-config-builder" export { AnthropicVertexHandler } from "./anthropic-vertex" export { AnthropicHandler } from "./anthropic" export { AwsBedrockHandler } from "./bedrock" diff --git a/src/api/providers/utils/__tests__/abort-signal.spec.ts b/src/api/providers/utils/__tests__/abort-signal.spec.ts new file mode 100644 index 0000000000..ebc7edf3d3 --- /dev/null +++ b/src/api/providers/utils/__tests__/abort-signal.spec.ts @@ -0,0 +1,102 @@ +import { mergeAbortSignalAndTimeout, mergeAbortSignals } from "../abort-signal" + +describe("abort-signal utilities", () => { + describe("mergeAbortSignalAndTimeout", () => { + it("returns undefined when no signal or positive timeout is provided", () => { + expect(mergeAbortSignalAndTimeout(undefined, 0)).toBeUndefined() + expect(mergeAbortSignalAndTimeout(undefined, -1)).toBeUndefined() + expect(mergeAbortSignalAndTimeout(undefined, NaN)).toBeUndefined() + expect(mergeAbortSignalAndTimeout()).toBeUndefined() + }) + + it("forwards external signal directly when timeout is disabled", () => { + const controller = new AbortController() + + expect(mergeAbortSignalAndTimeout(controller.signal, -1)).toBe(controller.signal) + expect(mergeAbortSignalAndTimeout(controller.signal, NaN)).toBe(controller.signal) + expect(mergeAbortSignalAndTimeout(controller.signal)).toBe(controller.signal) + }) + + it("creates a self-managed timeout signal when only positive timeout is provided", async () => { + const result = mergeAbortSignalAndTimeout(undefined, 50) + + expect(result).toBeInstanceOf(AbortSignal) + expect(result?.aborted).toBe(false) + + await vi.waitFor(() => expect(result?.aborted).toBe(true)) + }) + + it("merges external signal and timeout signal", () => { + const controller = new AbortController() + + const result = mergeAbortSignalAndTimeout(controller.signal, 100) + + expect(result).toBeInstanceOf(AbortSignal) + expect(result).not.toBe(controller.signal) + expect(result?.aborted).toBe(false) + + controller.abort() + + expect(result?.aborted).toBe(true) + }) + + it("aborts via timeout alone when the external signal stays active", async () => { + const controller = new AbortController() + + const result = mergeAbortSignalAndTimeout(controller.signal, 50) + + expect(result).not.toBe(controller.signal) + expect(result?.aborted).toBe(false) + + await vi.waitFor(() => expect(result?.aborted).toBe(true)) + }) + }) + + describe("mergeAbortSignals", () => { + it("returns primary signal directly when secondary signal is absent", () => { + const controller = new AbortController() + + const result = mergeAbortSignals(controller.signal) + + expect(result).toBe(controller.signal) + }) + + it("returns a merged signal when secondary signal is present", () => { + const primaryController = new AbortController() + const secondaryController = new AbortController() + + const result = mergeAbortSignals(primaryController.signal, secondaryController.signal) + + expect(result).not.toBe(primaryController.signal) + expect(result).not.toBe(secondaryController.signal) + expect(result.aborted).toBe(false) + + secondaryController.abort() + + expect(result.aborted).toBe(true) + }) + + it("aborts merged signal when primary signal is aborted", () => { + const primaryController = new AbortController() + const secondaryController = new AbortController() + + const result = mergeAbortSignals(primaryController.signal, secondaryController.signal) + + expect(result.aborted).toBe(false) + + primaryController.abort() + + expect(result.aborted).toBe(true) + }) + + it("returns an aborted signal when primary is already aborted", () => { + const primaryController = new AbortController() + const secondaryController = new AbortController() + primaryController.abort() + + const result = mergeAbortSignals(primaryController.signal, secondaryController.signal) + + expect(result.aborted).toBe(true) + }) + }) +}) diff --git a/src/api/providers/utils/abort-signal.ts b/src/api/providers/utils/abort-signal.ts new file mode 100644 index 0000000000..73e0356f7b --- /dev/null +++ b/src/api/providers/utils/abort-signal.ts @@ -0,0 +1,37 @@ +/** + * Merge an optional external abort signal with an optional timeout. + * + * Timeout values <= 0 are treated as disabled. The timeout is created via the + * native AbortSignal.timeout() API, which self-manages its timer — callers do + * not need to (and cannot) clear it manually. + */ +export function mergeAbortSignalAndTimeout(externalSignal?: AbortSignal, timeoutMs?: number): AbortSignal | undefined { + const hasTimeout = typeof timeoutMs === "number" && timeoutMs > 0 + + if (!hasTimeout) { + return externalSignal + } + + const timeoutSignal = AbortSignal.timeout(timeoutMs) + + if (!externalSignal) { + return timeoutSignal + } + + return mergeAbortSignals(externalSignal, timeoutSignal) +} + +/** + * Merge two abort signals using the standard AbortSignal.any() API. + * + * Returns the primary signal directly when no secondary signal is provided to + * avoid creating unnecessary controllers/listeners for the common single-signal + * path. + */ +export function mergeAbortSignals(primarySignal: AbortSignal, secondarySignal?: AbortSignal): AbortSignal { + if (!secondarySignal) { + return primarySignal + } + + return AbortSignal.any([primarySignal, secondarySignal]) +} diff --git a/src/test-utils/api.ts b/src/test-utils/api.ts index 1939fbb7e8..d3381119e7 100644 --- a/src/test-utils/api.ts +++ b/src/test-utils/api.ts @@ -1,5 +1,6 @@ import { expect, vi, type Mock } from "vitest" +import type { ApiHandlerCreateMessageMetadata } from "../api" import type { ApiHandlerOptions } from "../shared/api" export function makeApiHandlerOptions(overrides: Partial = {}): ApiHandlerOptions { @@ -10,6 +11,19 @@ export function makeApiHandlerOptions(overrides: Partial = {} } } +/** + * Build request-message metadata for provider tests. Defaults a taskId so tests + * only pass the fields they care about (for example an abortSignal). + */ +export function makeCreateMessageMetadata( + overrides: Partial = {}, +): ApiHandlerCreateMessageMetadata { + return { + taskId: "test-task", + ...overrides, + } +} + export function mockOpenAiResponsesClient(create: Mock) { return { __esModule: true, From 38d5ee088b11e40e03583bf1ffcd53efccbf388c Mon Sep 17 00:00:00 2001 From: edelauna <54631123+edelauna@users.noreply.github.com> Date: Wed, 19 Aug 2026 05:24:57 +0000 Subject: [PATCH 28/66] fix(shell): delegate VS Code profile reads to Terminal methods (issue #634) (#1033) * fix(terminal): align getShell() scope with Terminal config reads * fix(shell): delegate VS Code profile reads to Terminal methods * fix(shell): make getShell() provider-aware for Zoo profile and execa overrides --- src/eslint-suppressions.json | 2 +- .../shell-system-prompt-divergence.spec.ts | 167 +++++ src/utils/__tests__/shell.spec.ts | 704 +++++++----------- src/utils/shell.ts | 187 ++--- 4 files changed, 478 insertions(+), 582 deletions(-) create mode 100644 src/integrations/terminal/__tests__/shell-system-prompt-divergence.spec.ts diff --git a/src/eslint-suppressions.json b/src/eslint-suppressions.json index 87ff0dfec5..f790fba436 100644 --- a/src/eslint-suppressions.json +++ b/src/eslint-suppressions.json @@ -1706,7 +1706,7 @@ }, "utils/__tests__/shell.spec.ts": { "@typescript-eslint/no-explicit-any": { - "count": 46 + "count": 35 } }, "utils/__tests__/storage.spec.ts": { diff --git a/src/integrations/terminal/__tests__/shell-system-prompt-divergence.spec.ts b/src/integrations/terminal/__tests__/shell-system-prompt-divergence.spec.ts new file mode 100644 index 0000000000..183a98d492 --- /dev/null +++ b/src/integrations/terminal/__tests__/shell-system-prompt-divergence.spec.ts @@ -0,0 +1,167 @@ +// Regression test for https://github.com/Zoo-Code-Org/Zoo-Code/issues/634 +// +// Root cause: getShell() (system prompt) used config.get() which merges all scopes +// including workspace, while Terminal.getConfiguredDefaultProfileName() used +// inspect().globalValue — intentionally excluding workspace scope for security. +// terminal.integrated.defaultProfile.* is APPLICATION-scoped; workspace values are +// technically accepted by VS Code but ignored by the terminal itself. +// +// Fix: getShell() now delegates to Terminal.getConfiguredDefaultProfileName() and +// Terminal.getConfiguredProfiles(), so both paths read the same inspect()-based values +// and can never disagree. +// +// Run: node_modules/.bin/vitest run integrations/terminal/__tests__/shell-system-prompt-divergence.spec.ts + +import { existsSync } from "fs" +import * as vscode from "vscode" + +vi.mock("execa", () => ({ execa: vi.fn() })) +vi.mock("fs", () => ({ existsSync: vi.fn(() => false) })) +vi.mock("os", () => ({ userInfo: vi.fn(() => ({ shell: null })) })) + +const mockedExistsSync = existsSync as unknown as ReturnType + +const { Terminal } = await import("../Terminal") +const { getShell } = await import("../../../utils/shell") + +describe("issue #634 — system prompt shell vs actual terminal shell divergence", () => { + let originalPlatform: NodeJS.Platform + + beforeEach(() => { + originalPlatform = process.platform + Object.defineProperty(process, "platform", { value: "win32", configurable: true }) + Terminal.setTerminalProfile(undefined) + mockedExistsSync.mockReset() + // pwsh.exe exists — getShell() fallback path prefers PowerShell 7 over legacy + mockedExistsSync.mockImplementation((p: string) => p === "C:\\Program Files\\PowerShell\\7\\pwsh.exe") + }) + + afterEach(() => { + Object.defineProperty(process, "platform", { value: originalPlatform, configurable: true }) + Terminal.setTerminalProfile(undefined) + vi.restoreAllMocks() + }) + + /** + * Stubs VS Code config to simulate a workspace-scoped default profile. + * globalValue is undefined for both the profile name and profiles map, + * so Terminal (which reads only globalValue ?? defaultValue) sees no profile. + * The workspace-scoped value is present to verify it is correctly ignored. + */ + function stubWorkspaceScopedProfile(profileName: string, profilePath: string) { + const profiles = { [profileName]: { path: profilePath } } + vi.spyOn(vscode.workspace, "getConfiguration").mockImplementation((section?: string) => { + if (section === "terminal.integrated") { + return { + // get() merges all scopes — shell.ts uses this, picks up workspace value + get: (key: string) => { + if (key === "defaultProfile.windows") return profileName + if (key === "profiles.windows") return profiles + return undefined + }, + // Terminal uses inspect() and only reads globalValue ?? defaultValue + inspect: (_key: string) => ({ + defaultValue: undefined, + globalValue: undefined, + workspaceValue: profileName, + }), + } as unknown as vscode.WorkspaceConfiguration + } + + if (section === "terminal.integrated.profiles") { + return { + inspect: (_key: string) => ({ + defaultValue: undefined, + globalValue: undefined, + workspaceValue: profiles, + }), + } as unknown as vscode.WorkspaceConfiguration + } + + return { + get: (_key: string, dv?: unknown) => dv, + inspect: () => undefined, + } as unknown as vscode.WorkspaceConfiguration + }) + } + + it("Terminal.getConfiguredDefaultProfileName ignores workspace-scoped profile (confirms the bug)", () => { + // User set PowerShell as default only in their workspace .vscode/settings.json + stubWorkspaceScopedProfile("PowerShell", "C:\\Program Files\\PowerShell\\7\\pwsh.exe") + + // Terminal intentionally excludes workspace scope for security. + // With no global/default profile set, it returns undefined. + const terminalSeesProfileName = Terminal.getConfiguredDefaultProfileName("win32") + expect(terminalSeesProfileName).toBeUndefined() + + // As a consequence, isActiveShellPowerShell returns false even though the + // user configured PowerShell — the terminal will not be treated as PowerShell. + expect(Terminal.isActiveShellPowerShell("win32")).toBe(false) + }) + + it("getShell() and Terminal agree on PowerShell when the default profile is set at global/user scope", () => { + // When the profile is set at user (global) scope, both paths see the same value. + const profilePath = "C:\\Program Files\\Git\\bin\\bash.exe" // non-PowerShell so name-matching doesn't hide the bug + const profileName = "Git Bash" + vi.spyOn(vscode.workspace, "getConfiguration").mockImplementation((section?: string) => { + if (section === "terminal.integrated") { + return { + get: (key: string) => { + if (key === "defaultProfile.windows") return profileName + if (key === "profiles.windows") return { [profileName]: { path: profilePath } } + return undefined + }, + inspect: (_key: string) => ({ + defaultValue: undefined, + globalValue: profileName, + workspaceValue: undefined, + }), + } as unknown as vscode.WorkspaceConfiguration + } + + if (section === "terminal.integrated.profiles") { + const profiles = { [profileName]: { path: profilePath } } + return { + inspect: (_key: string) => ({ + defaultValue: undefined, + globalValue: profiles, + workspaceValue: undefined, + }), + } as unknown as vscode.WorkspaceConfiguration + } + + return { + get: (_key: string, dv?: unknown) => dv, + inspect: () => undefined, + } as unknown as vscode.WorkspaceConfiguration + }) + mockedExistsSync.mockImplementation((p: string) => p === profilePath) + + const shellForSystemPrompt = getShell() + const terminalSeesProfileName = Terminal.getConfiguredDefaultProfileName("win32") + + // Both agree: Git Bash + expect(terminalSeesProfileName).toBe(profileName) + expect(shellForSystemPrompt).toBe(profilePath) + }) + + it("convergence: getShell() and Terminal both ignore a workspace-scoped-only profile (fix verification)", () => { + // beforeEach mocks existsSync to return true only for PS7 path. + // Here we want to test the no-profile fallback, so make existsSync return false. + mockedExistsSync.mockReturnValue(false) + stubWorkspaceScopedProfile("PowerShell", "C:\\Program Files\\PowerShell\\7\\pwsh.exe") + + // Terminal reads only inspect().globalValue → no profile configured at global scope. + const terminalSeesProfileName = Terminal.getConfiguredDefaultProfileName("win32") + expect(terminalSeesProfileName).toBeUndefined() + + // After the fix, getShell() delegates to Terminal's inspect()-based methods, + // so it also sees no profile. It falls back to the Windows no-profile default + // (PS legacy, since existsSync returns false for PS7 in this test). + const shellForSystemPrompt = getShell() + expect(shellForSystemPrompt).toBe("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe") + + // Both paths agree: no profile resolved → no active shell identified as PowerShell. + expect(Terminal.isActiveShellPowerShell("win32")).toBe(false) + }) +}) diff --git a/src/utils/__tests__/shell.spec.ts b/src/utils/__tests__/shell.spec.ts index 4c45837680..a3e3bf4e18 100644 --- a/src/utils/__tests__/shell.spec.ts +++ b/src/utils/__tests__/shell.spec.ts @@ -3,25 +3,23 @@ import * as vscode from "vscode" import { existsSync } from "fs" import { userInfo } from "os" import { getShell } from "../shell" +import { BaseTerminal } from "../../integrations/terminal/BaseTerminal" +import { Terminal } from "../../integrations/terminal/Terminal" -// Mock vscode module vi.mock("vscode", () => ({ workspace: { getConfiguration: vi.fn(), }, })) -// Mock the os module vi.mock("os", () => ({ userInfo: vi.fn(() => ({ shell: null })), })) -// Mock the fs module — getWindowsShellFromVSCode probes for PowerShell 7 (pwsh.exe). vi.mock("fs", () => ({ existsSync: vi.fn(() => false), })) -// Mock path module for testing vi.mock("path", async () => { const actual = await vi.importActual("path") return { @@ -35,43 +33,63 @@ describe("Shell Detection Tests", () => { let originalEnv: NodeJS.ProcessEnv let originalGetConfig: any - // Helper to mock VS Code configuration + /** + * Stubs VS Code config using inspect() on the correct section names, matching + * how Terminal.getConfiguredDefaultProfileName and Terminal.getConfiguredProfiles + * read config (globalValue only — workspace excluded per APPLICATION scope). + */ function mockVsCodeConfig(platformKey: string, defaultProfileName: string | null, profiles: Record) { - vscode.workspace.getConfiguration = () => - ({ - get: (key: string) => { - if (key === `defaultProfile.${platformKey}`) { - return defaultProfileName - } - if (key === `profiles.${platformKey}`) { - return profiles - } - return undefined - }, - }) as any + vscode.workspace.getConfiguration = (section?: string) => { + if (section === "terminal.integrated") { + return { + inspect: (key: string) => { + expect(key).toBe(`defaultProfile.${platformKey}`) + return { + defaultValue: undefined, + globalValue: defaultProfileName ?? undefined, + } + }, + get: () => undefined, + } as any + } + if (section === "terminal.integrated.profiles") { + return { + inspect: (key: string) => { + expect(key).toBe(platformKey) + return { + defaultValue: undefined, + globalValue: profiles, + } + }, + get: () => undefined, + } as any + } + return { get: () => undefined, inspect: () => undefined } as any + } } beforeEach(() => { - // Store original references originalPlatform = process.platform originalEnv = { ...process.env } originalGetConfig = vscode.workspace.getConfiguration - // Clear environment variables for a clean test delete process.env.SHELL delete process.env.COMSPEC - // Reset userInfo mock to default vi.mocked(userInfo).mockReturnValue({ shell: null } as any) // Default: PowerShell 7 is not installed, so the probe falls back to legacy. vi.mocked(existsSync).mockReturnValue(false) + // Clear Zoo profile override and execa shell path between tests. + Terminal.setTerminalProfile(undefined) + BaseTerminal.setExecaShellPath(undefined) }) afterEach(() => { - // Restore everything Object.defineProperty(process, "platform", { value: originalPlatform }) process.env = originalEnv vscode.workspace.getConfiguration = originalGetConfig + Terminal.setTerminalProfile(undefined) + BaseTerminal.setExecaShellPath(undefined) vi.clearAllMocks() }) @@ -84,6 +102,7 @@ describe("Shell Detection Tests", () => { }) it("uses explicit PowerShell 7 path from VS Code config (profile path)", () => { + vi.mocked(existsSync).mockImplementation((p: any) => p === "C:\\Program Files\\PowerShell\\7\\pwsh.exe") mockVsCodeConfig("windows", "PowerShell", { PowerShell: { path: "C:\\Program Files\\PowerShell\\7\\pwsh.exe" }, }) @@ -91,65 +110,33 @@ describe("Shell Detection Tests", () => { }) it("should handle array path from VSCode terminal profile", () => { - // Mock VSCode configuration with array path - const mockConfig = { - get: vi.fn((key: string) => { - if (key === "defaultProfile.windows") return "PowerShell" - if (key === "profiles.windows") { - return { - PowerShell: { - // VSCode API may return path as an array - path: ["C:\\Program Files\\PowerShell\\7\\pwsh.exe", "pwsh.exe"], - }, - } - } - return undefined - }), - } - - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue(mockConfig as any) - - const result = getShell() - // Should use the first element of the array - expect(result).toBe("C:\\Program Files\\PowerShell\\7\\pwsh.exe") + vi.mocked(existsSync).mockImplementation((p: any) => p === "C:\\Program Files\\PowerShell\\7\\pwsh.exe") + mockVsCodeConfig("windows", "PowerShell", { + PowerShell: { path: ["C:\\Program Files\\PowerShell\\7\\pwsh.exe", "pwsh.exe"] }, + }) + expect(getShell()).toBe("C:\\Program Files\\PowerShell\\7\\pwsh.exe") }) - it("should handle empty array path and fall back to defaults", () => { - // Mock VSCode configuration with empty array path - const mockConfig = { - get: vi.fn((key: string) => { - if (key === "defaultProfile.windows") return "Custom" - if (key === "profiles.windows") { - return { - Custom: { - path: [], // Empty array - }, - } - } - return undefined - }), - } - - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue(mockConfig as any) - - // Mock environment variable + it("falls through to COMSPEC when profile has an empty array path", () => { + mockVsCodeConfig("windows", "Custom", { + Custom: { path: [] }, + }) process.env.COMSPEC = "C:\\Windows\\System32\\cmd.exe" - - const result = getShell() - // Should fall back to cmd.exe - expect(result).toBe("C:\\Windows\\System32\\cmd.exe") + expect(getShell()).toBe("C:\\Windows\\System32\\cmd.exe") }) it("uses PowerShell 7 path if source is 'PowerShell' but no explicit path", () => { + vi.mocked(existsSync).mockImplementation((p: any) => p === "C:\\Program Files\\PowerShell\\7\\pwsh.exe") mockVsCodeConfig("windows", "PowerShell", { PowerShell: { source: "PowerShell" }, }) expect(getShell()).toBe("C:\\Program Files\\PowerShell\\7\\pwsh.exe") }) - it("falls back to legacy PowerShell if profile includes 'powershell' but no path/source", () => { + it("falls back to legacy PowerShell if source is 'PowerShell' but PS7 is absent", () => { + vi.mocked(existsSync).mockReturnValue(false) mockVsCodeConfig("windows", "PowerShell", { - PowerShell: {}, + PowerShell: { source: "PowerShell" }, }) expect(getShell()).toBe("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe") }) @@ -161,57 +148,48 @@ describe("Shell Detection Tests", () => { expect(getShell()).toBe("/bin/bash") }) - it("uses WSL bash when profile name includes 'wsl'", () => { - mockVsCodeConfig("windows", "Ubuntu WSL", { - "Ubuntu WSL": {}, - }) - expect(getShell()).toBe("/bin/bash") - }) - - it("defaults to cmd.exe if no special profile is matched", () => { + it("falls through to COMSPEC when profile has no path and no source", () => { + // A profile entry with no path and no recognised source is unresolvable; + // getShell falls through to env/fallback rather than guessing cmd.exe. mockVsCodeConfig("windows", "CommandPrompt", { CommandPrompt: {}, }) + process.env.COMSPEC = "C:\\Windows\\System32\\cmd.exe" expect(getShell()).toBe("C:\\Windows\\System32\\cmd.exe") }) - it("handles undefined profile gracefully", () => { - // Mock a case where defaultProfileName exists but the profile doesn't + it("falls through to COMSPEC when configured profile is missing from profiles map", () => { mockVsCodeConfig("windows", "NonexistentProfile", {}) + process.env.COMSPEC = "C:\\Windows\\System32\\cmd.exe" expect(getShell()).toBe("C:\\Windows\\System32\\cmd.exe") }) it("defaults to PowerShell 7 when no profile is configured and pwsh.exe is installed", () => { - // Modern VS Code launches PowerShell by default on Windows (issue #82) and - // prefers PS7 when present, so getShell() should report pwsh.exe. - vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any + // Modern VS Code prefers PS7 on Windows when no profile is explicitly set. + mockVsCodeConfig("windows", null, {}) vi.mocked(existsSync).mockReturnValue(true) - expect(getShell()).toBe("C:\\Program Files\\PowerShell\\7\\pwsh.exe") }) it("falls back to Windows PowerShell 5.1 when no profile is configured and PS7 is absent", () => { - // Without PS7 installed, the probe falls back to the always-present legacy - // PowerShell rather than cmd.exe. - vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any + mockVsCodeConfig("windows", null, {}) vi.mocked(existsSync).mockReturnValue(false) - expect(getShell()).toBe("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe") }) it("falls back to safe shell when the configured profile path is non-allowlisted", () => { + vi.mocked(existsSync).mockImplementation((p: any) => p === "C:\\Custom\\evil.exe") mockVsCodeConfig("windows", "Custom", { Custom: { path: "C:\\Custom\\evil.exe" }, }) - expect(getShell()).toBe("C:\\Windows\\System32\\cmd.exe") }) it("uses cmd.exe when a Command Prompt profile is explicitly configured", () => { + vi.mocked(existsSync).mockImplementation((p: any) => p === "C:\\Windows\\System32\\cmd.exe") mockVsCodeConfig("windows", "Command Prompt", { "Command Prompt": { path: "C:\\Windows\\System32\\cmd.exe" }, }) - expect(getShell()).toBe("C:\\Windows\\System32\\cmd.exe") }) }) @@ -225,6 +203,7 @@ describe("Shell Detection Tests", () => { }) it("uses VS Code profile path if available", () => { + vi.mocked(existsSync).mockImplementation((p: any) => p === "/usr/local/bin/fish") mockVsCodeConfig("osx", "MyCustomShell", { MyCustomShell: { path: "/usr/local/bin/fish" }, }) @@ -232,42 +211,27 @@ describe("Shell Detection Tests", () => { }) it("should handle array path from VSCode terminal profile", () => { - // Mock VSCode configuration with array path - const mockConfig = { - get: vi.fn((key: string) => { - if (key === "defaultProfile.osx") return "zsh" - if (key === "profiles.osx") { - return { - zsh: { - path: ["/opt/homebrew/bin/zsh", "/bin/zsh"], - }, - } - } - return undefined - }), - } - - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue(mockConfig as any) - - const result = getShell() - // Should use the first element of the array - expect(result).toBe("/opt/homebrew/bin/zsh") + vi.mocked(existsSync).mockImplementation((p: any) => p === "/opt/homebrew/bin/zsh") + mockVsCodeConfig("osx", "zsh", { + zsh: { path: ["/opt/homebrew/bin/zsh", "/bin/zsh"] }, + }) + expect(getShell()).toBe("/opt/homebrew/bin/zsh") }) it("falls back to userInfo().shell if no VS Code config is available", () => { - vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any + mockVsCodeConfig("osx", null, {}) vi.mocked(userInfo).mockReturnValue({ shell: "/opt/homebrew/bin/zsh" } as any) expect(getShell()).toBe("/opt/homebrew/bin/zsh") }) it("falls back to SHELL env var if no userInfo shell is found", () => { - vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any + mockVsCodeConfig("osx", null, {}) process.env.SHELL = "/usr/local/bin/zsh" expect(getShell()).toBe("/usr/local/bin/zsh") }) it("falls back to /bin/zsh if no config, userInfo, or env variable is set", () => { - vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any + mockVsCodeConfig("osx", null, {}) expect(getShell()).toBe("/bin/zsh") }) }) @@ -281,6 +245,7 @@ describe("Shell Detection Tests", () => { }) it("uses VS Code profile path if available", () => { + vi.mocked(existsSync).mockImplementation((p: any) => p === "/usr/bin/fish") mockVsCodeConfig("linux", "CustomProfile", { CustomProfile: { path: "/usr/bin/fish" }, }) @@ -288,42 +253,27 @@ describe("Shell Detection Tests", () => { }) it("should handle array path from VSCode terminal profile", () => { - // Mock VSCode configuration with array path - const mockConfig = { - get: vi.fn((key: string) => { - if (key === "defaultProfile.linux") return "bash" - if (key === "profiles.linux") { - return { - bash: { - path: ["/usr/local/bin/bash", "/bin/bash"], - }, - } - } - return undefined - }), - } - - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue(mockConfig as any) - - const result = getShell() - // Should use the first element of the array - expect(result).toBe("/usr/local/bin/bash") + vi.mocked(existsSync).mockImplementation((p: any) => p === "/usr/local/bin/bash") + mockVsCodeConfig("linux", "bash", { + bash: { path: ["/usr/local/bin/bash", "/bin/bash"] }, + }) + expect(getShell()).toBe("/usr/local/bin/bash") }) it("falls back to userInfo().shell if no VS Code config is available", () => { - vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any + mockVsCodeConfig("linux", null, {}) vi.mocked(userInfo).mockReturnValue({ shell: "/usr/bin/zsh" } as any) expect(getShell()).toBe("/usr/bin/zsh") }) it("falls back to SHELL env var if no userInfo shell is found", () => { - vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any + mockVsCodeConfig("linux", null, {}) process.env.SHELL = "/usr/bin/fish" expect(getShell()).toBe("/usr/bin/fish") }) it("falls back to /bin/bash if nothing is set", () => { - vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any + mockVsCodeConfig("linux", null, {}) expect(getShell()).toBe("/bin/bash") }) }) @@ -334,7 +284,7 @@ describe("Shell Detection Tests", () => { describe("Unknown Platform / Error Handling", () => { it("falls back to /bin/bash for unknown platforms", () => { Object.defineProperty(process, "platform", { value: "sunos" }) - vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any + mockVsCodeConfig("linux", null, {}) expect(getShell()).toBe("/bin/bash") }) @@ -349,7 +299,7 @@ describe("Shell Detection Tests", () => { it("handles userInfo errors gracefully, falling back to environment variable if present", () => { Object.defineProperty(process, "platform", { value: "darwin" }) - vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any + mockVsCodeConfig("osx", null, {}) vi.mocked(userInfo).mockImplementation(() => { throw new Error("userInfo error") }) @@ -368,77 +318,79 @@ describe("Shell Detection Tests", () => { delete process.env.SHELL expect(getShell()).toBe("/bin/bash") }) + + it("handles inspect() returning undefined gracefully", () => { + Object.defineProperty(process, "platform", { value: "linux" }) + vscode.workspace.getConfiguration = () => + ({ + inspect: () => undefined, + get: () => undefined, + }) as any + expect(getShell()).toBe("/bin/bash") + }) }) // -------------------------------------------------------------------------- - // getTerminalConfig Behavior (tested via getShell) + // Scope isolation — workspace values must not influence getShell() // -------------------------------------------------------------------------- - describe("getTerminalConfig", () => { - it("returns defaultProfileName and matching profile for Windows", () => { + describe("Scope isolation (workspace values ignored)", () => { + it("Windows: ignores a workspace-scoped default profile", () => { Object.defineProperty(process, "platform", { value: "win32" }) - mockVsCodeConfig("windows", "Command Prompt", { - "Command Prompt": { path: "C:\\Windows\\System32\\cmd.exe" }, - }) - expect(getShell()).toBe("C:\\Windows\\System32\\cmd.exe") - }) - - it("returns defaultProfileName and matching profile for macOS", () => { - Object.defineProperty(process, "platform", { value: "darwin" }) - mockVsCodeConfig("osx", "fish", { - fish: { path: "/usr/local/bin/fish" }, - }) - expect(getShell()).toBe("/usr/local/bin/fish") - }) - - it("returns defaultProfileName and matching profile for Linux", () => { - Object.defineProperty(process, "platform", { value: "linux" }) - mockVsCodeConfig("linux", "zsh", { - zsh: { path: "/usr/bin/zsh" }, - }) - expect(getShell()).toBe("/usr/bin/zsh") - }) - - it("returns null defaultProfileName when config value is undefined", () => { - Object.defineProperty(process, "platform", { value: "linux" }) - const mockConfig = { - get: vi.fn((key: string) => { - if (key === "defaultProfile.linux") return undefined - if (key === "profiles.linux") return { bash: { path: "/bin/bash" } } - return undefined - }), + vi.mocked(existsSync).mockReturnValue(false) + // globalValue is undefined; only workspaceValue is set + vscode.workspace.getConfiguration = (section?: string) => { + if (section === "terminal.integrated") { + return { + inspect: (_key: string) => ({ + defaultValue: undefined, + globalValue: undefined, + workspaceValue: "PowerShell", + }), + get: () => undefined, + } as any + } + if (section === "terminal.integrated.profiles") { + return { + inspect: (_key: string) => ({ + defaultValue: undefined, + globalValue: undefined, + workspaceValue: { PowerShell: { path: "C:\\Program Files\\PowerShell\\7\\pwsh.exe" } }, + }), + get: () => undefined, + } as any + } + return { get: () => undefined, inspect: () => undefined } as any } - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue(mockConfig as any) - expect(getShell()).toBe("/bin/bash") + // No global profile → falls back to PS legacy (existsSync returns false for PS7) + expect(getShell()).toBe("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe") }) - it("returns empty profiles when profiles config is null", () => { + it("Linux: ignores a workspace-scoped default profile", () => { Object.defineProperty(process, "platform", { value: "linux" }) - const mockConfig = { - get: vi.fn((key: string) => { - if (key === "defaultProfile.linux") return "bash" - if (key === "profiles.linux") return null - return undefined - }), + vscode.workspace.getConfiguration = (section?: string) => { + if (section === "terminal.integrated") { + return { + inspect: (_key: string) => ({ + defaultValue: undefined, + globalValue: undefined, + workspaceValue: "CustomShell", + }), + get: () => undefined, + } as any + } + if (section === "terminal.integrated.profiles") { + return { + inspect: (_key: string) => ({ + defaultValue: undefined, + globalValue: undefined, + workspaceValue: { CustomShell: { path: "/usr/bin/fish" } }, + }), + get: () => undefined, + } as any + } + return { get: () => undefined, inspect: () => undefined } as any } - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue(mockConfig as any) - expect(getShell()).toBe("/bin/bash") - }) - - it("returns fallback when getConfiguration throws", () => { - Object.defineProperty(process, "platform", { value: "darwin" }) - vi.mocked(vscode.workspace.getConfiguration).mockImplementation(() => { - throw new Error("config error") - }) - expect(getShell()).toBe("/bin/zsh") - }) - - it("returns fallback when config.get throws", () => { - Object.defineProperty(process, "platform", { value: "linux" }) - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue({ - get: () => { - throw new Error("get error") - }, - } as any) + // No global profile → falls through to /bin/bash expect(getShell()).toBe("/bin/bash") }) }) @@ -447,212 +399,26 @@ describe("Shell Detection Tests", () => { // Non-string defaultProfileName Handling // -------------------------------------------------------------------------- describe("Non-string defaultProfileName handling", () => { - it("Windows: handles numeric defaultProfileName without TypeError", () => { - Object.defineProperty(process, "platform", { value: "win32" }) - const mockConfig = { - get: vi.fn((key: string) => { - if (key === "defaultProfile.windows") return 1 - if (key === "profiles.windows") return {} - return undefined - }), - } - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue(mockConfig as any) - vi.mocked(existsSync).mockReturnValue(false) + // Terminal.getConfiguredDefaultProfileName returns inspect().globalValue as-is. + // If VS Code somehow stores a non-string, it will be undefined (inspect returns + // typed as string | undefined), so getShell falls through to userInfo/env/fallback. - expect(getShell()).toBe("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe") - }) - - it("Windows: handles boolean defaultProfileName without TypeError", () => { - Object.defineProperty(process, "platform", { value: "win32" }) - const mockConfig = { - get: vi.fn((key: string) => { - if (key === "defaultProfile.windows") return true - if (key === "profiles.windows") return {} - return undefined - }), - } - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue(mockConfig as any) - vi.mocked(existsSync).mockReturnValue(false) - - expect(getShell()).toBe("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe") - }) - - it("Windows: handles array defaultProfileName without TypeError", () => { + it("Windows: handles undefined defaultProfileName (no profile set)", () => { Object.defineProperty(process, "platform", { value: "win32" }) - const mockConfig = { - get: vi.fn((key: string) => { - if (key === "defaultProfile.windows") return ["PowerShell"] - if (key === "profiles.windows") return {} - return undefined - }), - } - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue(mockConfig as any) + mockVsCodeConfig("windows", null, {}) vi.mocked(existsSync).mockReturnValue(false) - expect(getShell()).toBe("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe") }) - it("Windows: handles object defaultProfileName without TypeError", () => { - Object.defineProperty(process, "platform", { value: "win32" }) - const mockConfig = { - get: vi.fn((key: string) => { - if (key === "defaultProfile.windows") return { name: "PowerShell" } - if (key === "profiles.windows") return {} - return undefined - }), - } - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue(mockConfig as any) - vi.mocked(existsSync).mockReturnValue(false) - - expect(getShell()).toBe("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe") - }) - - it("macOS: handles numeric defaultProfileName without TypeError", () => { - Object.defineProperty(process, "platform", { value: "darwin" }) - const mockConfig = { - get: vi.fn((key: string) => { - if (key === "defaultProfile.osx") return 1 - if (key === "profiles.osx") return {} - return undefined - }), - } - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue(mockConfig as any) - - expect(getShell()).toBe("/bin/zsh") - }) - - it("macOS: handles boolean defaultProfileName without TypeError", () => { - Object.defineProperty(process, "platform", { value: "darwin" }) - const mockConfig = { - get: vi.fn((key: string) => { - if (key === "defaultProfile.osx") return true - if (key === "profiles.osx") return {} - return undefined - }), - } - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue(mockConfig as any) - - expect(getShell()).toBe("/bin/zsh") - }) - - it("macOS: handles array defaultProfileName without TypeError", () => { - Object.defineProperty(process, "platform", { value: "darwin" }) - const mockConfig = { - get: vi.fn((key: string) => { - if (key === "defaultProfile.osx") return ["zsh"] - if (key === "profiles.osx") return {} - return undefined - }), - } - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue(mockConfig as any) - - expect(getShell()).toBe("/bin/zsh") - }) - - it("macOS: handles object defaultProfileName without TypeError", () => { - Object.defineProperty(process, "platform", { value: "darwin" }) - const mockConfig = { - get: vi.fn((key: string) => { - if (key === "defaultProfile.osx") return {} - if (key === "profiles.osx") return {} - return undefined - }), - } - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue(mockConfig as any) - - expect(getShell()).toBe("/bin/zsh") - }) - - // Mutation-resistant: without the typeof guard, profiles[1] === profiles["1"] in JS, - // so a numeric key that matches a real profile would return its path instead of falling back. - it("macOS: ignores numeric defaultProfileName even when it matches a profile key", () => { + it("macOS: returns fallback when no profile is configured", () => { Object.defineProperty(process, "platform", { value: "darwin" }) - const mockConfig = { - get: vi.fn((key: string) => { - if (key === "defaultProfile.osx") return 1 - // Profile keyed as "1" — would be reached by profiles[1] if the guard were absent - if (key === "profiles.osx") return { "1": { path: "/usr/local/bin/zsh" } } - return undefined - }), - } - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue(mockConfig as any) - - // Guard treats 1 as null → getMacShellFromVSCode returns null → fallback to /bin/zsh - // Without the guard it would return /usr/local/bin/zsh + mockVsCodeConfig("osx", null, {}) expect(getShell()).toBe("/bin/zsh") }) - it("Linux: handles numeric defaultProfileName without TypeError", () => { - Object.defineProperty(process, "platform", { value: "linux" }) - const mockConfig = { - get: vi.fn((key: string) => { - if (key === "defaultProfile.linux") return 1 - if (key === "profiles.linux") return {} - return undefined - }), - } - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue(mockConfig as any) - - expect(getShell()).toBe("/bin/bash") - }) - - it("Linux: handles boolean defaultProfileName without TypeError", () => { - Object.defineProperty(process, "platform", { value: "linux" }) - const mockConfig = { - get: vi.fn((key: string) => { - if (key === "defaultProfile.linux") return true - if (key === "profiles.linux") return {} - return undefined - }), - } - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue(mockConfig as any) - - expect(getShell()).toBe("/bin/bash") - }) - - it("Linux: handles array defaultProfileName without TypeError", () => { - Object.defineProperty(process, "platform", { value: "linux" }) - const mockConfig = { - get: vi.fn((key: string) => { - if (key === "defaultProfile.linux") return ["bash"] - if (key === "profiles.linux") return {} - return undefined - }), - } - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue(mockConfig as any) - - expect(getShell()).toBe("/bin/bash") - }) - - it("Linux: handles object defaultProfileName without TypeError", () => { - Object.defineProperty(process, "platform", { value: "linux" }) - const mockConfig = { - get: vi.fn((key: string) => { - if (key === "defaultProfile.linux") return {} - if (key === "profiles.linux") return {} - return undefined - }), - } - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue(mockConfig as any) - - expect(getShell()).toBe("/bin/bash") - }) - - // Mutation-resistant: same pattern as macOS — numeric key matches profile "1" only if unguarded. - it("Linux: ignores numeric defaultProfileName even when it matches a profile key", () => { + it("Linux: returns fallback when no profile is configured", () => { Object.defineProperty(process, "platform", { value: "linux" }) - const mockConfig = { - get: vi.fn((key: string) => { - if (key === "defaultProfile.linux") return 1 - // Profile keyed as "1" — would be reached by profiles[1] if the guard were absent - if (key === "profiles.linux") return { "1": { path: "/usr/bin/fish" } } - return undefined - }), - } - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue(mockConfig as any) - - // Guard treats 1 as null → getLinuxShellFromVSCode returns null → fallback to /bin/bash - // Without the guard it would return /usr/bin/fish + mockVsCodeConfig("linux", null, {}) expect(getShell()).toBe("/bin/bash") }) }) @@ -663,6 +429,7 @@ describe("Shell Detection Tests", () => { describe("Shell Validation", () => { it("should allow common Windows shells", () => { Object.defineProperty(process, "platform", { value: "win32" }) + vi.mocked(existsSync).mockImplementation((p: any) => p === "C:\\Program Files\\PowerShell\\7\\pwsh.exe") mockVsCodeConfig("windows", "PowerShell", { PowerShell: { path: "C:\\Program Files\\PowerShell\\7\\pwsh.exe" }, }) @@ -671,6 +438,7 @@ describe("Shell Detection Tests", () => { it("should allow common Unix shells", () => { Object.defineProperty(process, "platform", { value: "linux" }) + vi.mocked(existsSync).mockImplementation((p: any) => p === "/usr/bin/fish") mockVsCodeConfig("linux", "CustomProfile", { CustomProfile: { path: "/usr/bin/fish" }, }) @@ -679,6 +447,7 @@ describe("Shell Detection Tests", () => { it("should handle case-insensitive matching on Windows", () => { Object.defineProperty(process, "platform", { value: "win32" }) + vi.mocked(existsSync).mockImplementation((p: any) => p === "c:\\windows\\system32\\cmd.exe") mockVsCodeConfig("windows", "PowerShell", { PowerShell: { path: "c:\\windows\\system32\\cmd.exe" }, }) @@ -687,90 +456,54 @@ describe("Shell Detection Tests", () => { it("should reject unknown shells and use fallback", () => { Object.defineProperty(process, "platform", { value: "linux" }) + vi.mocked(existsSync).mockImplementation((p: any) => p === "/usr/bin/malicious-shell") mockVsCodeConfig("linux", "CustomProfile", { CustomProfile: { path: "/usr/bin/malicious-shell" }, }) expect(getShell()).toBe("/bin/bash") }) - it("should validate array shell paths and use first allowed", () => { + it("should resolve array shell paths and use first path", () => { Object.defineProperty(process, "platform", { value: "win32" }) - - const mockConfig = { - get: vi.fn((key: string) => { - if (key === "defaultProfile.windows") return "PowerShell" - if (key === "profiles.windows") { - return { - PowerShell: { - path: ["C:\\Program Files\\PowerShell\\7\\pwsh.exe", "pwsh"], - }, - } - } - return undefined - }), - } - - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue(mockConfig as any) - - const result = getShell() - // Should return the first allowed shell from the array - expect(result).toBe("C:\\Program Files\\PowerShell\\7\\pwsh.exe") + vi.mocked(existsSync).mockImplementation((p: any) => p === "C:\\Program Files\\PowerShell\\7\\pwsh.exe") + mockVsCodeConfig("windows", "PowerShell", { + PowerShell: { path: ["C:\\Program Files\\PowerShell\\7\\pwsh.exe", "pwsh"] }, + }) + expect(getShell()).toBe("C:\\Program Files\\PowerShell\\7\\pwsh.exe") }) it("should reject non-allowed shell paths and fall back to safe defaults", () => { Object.defineProperty(process, "platform", { value: "win32" }) - - const mockConfig = { - get: vi.fn((key: string) => { - if (key === "defaultProfile.windows") return "Malicious" - if (key === "profiles.windows") { - return { - Malicious: { - path: "C:\\malicious\\shell.exe", - }, - } - } - return undefined - }), - } - - vi.mocked(vscode.workspace.getConfiguration).mockReturnValue(mockConfig as any) - - // Mock environment to provide a fallback + vi.mocked(existsSync).mockImplementation((p: any) => p === "C:\\malicious\\shell.exe") + mockVsCodeConfig("windows", "Malicious", { + Malicious: { path: "C:\\malicious\\shell.exe" }, + }) process.env.COMSPEC = "C:\\Windows\\System32\\cmd.exe" - - const result = getShell() - // Should fall back to safe default (cmd.exe) - expect(result).toBe("C:\\Windows\\System32\\cmd.exe") + expect(getShell()).toBe("C:\\Windows\\System32\\cmd.exe") }) it("should validate shells from VS Code config", () => { Object.defineProperty(process, "platform", { value: "darwin" }) + vi.mocked(existsSync).mockImplementation((p: any) => p === "/usr/local/bin/custom-shell") mockVsCodeConfig("osx", "MyCustomShell", { MyCustomShell: { path: "/usr/local/bin/custom-shell" }, }) - - const result = getShell() - expect(result).toBe("/bin/zsh") // macOS fallback + expect(getShell()).toBe("/bin/zsh") // not in allowlist → macOS fallback }) it("should validate shells from userInfo", () => { Object.defineProperty(process, "platform", { value: "linux" }) - vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any + mockVsCodeConfig("linux", null, {}) vi.mocked(userInfo).mockReturnValue({ shell: "/usr/bin/evil-shell" } as any) - - const result = getShell() - expect(result).toBe("/bin/bash") // Linux fallback + expect(getShell()).toBe("/bin/bash") }) it("should validate shells from environment variables", () => { Object.defineProperty(process, "platform", { value: "linux" }) - vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any + mockVsCodeConfig("linux", null, {}) vi.mocked(userInfo).mockReturnValue({ shell: null } as any) process.env.SHELL = "/opt/custom/shell" - - const result = getShell() - expect(result).toBe("/bin/bash") // Linux fallback + expect(getShell()).toBe("/bin/bash") }) it("should handle WSL bash correctly", () => { @@ -778,19 +511,88 @@ describe("Shell Detection Tests", () => { mockVsCodeConfig("windows", "WSL", { WSL: { source: "WSL" }, }) - - const result = getShell() - expect(result).toBe("/bin/bash") // Should be allowed + expect(getShell()).toBe("/bin/bash") }) it("should handle empty or null shell paths", () => { Object.defineProperty(process, "platform", { value: "linux" }) - vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any + mockVsCodeConfig("linux", null, {}) vi.mocked(userInfo).mockReturnValue({ shell: "" } as any) delete process.env.SHELL + expect(getShell()).toBe("/bin/bash") + }) + }) + + // -------------------------------------------------------------------------- + // Zoo profile override (Terminal.getProfileShell) takes precedence + // -------------------------------------------------------------------------- + describe("Zoo profile override", () => { + it("uses Zoo profile shell over VS Code default profile", () => { + Object.defineProperty(process, "platform", { value: "win32" }) + // VS Code default profile is PowerShell + vi.mocked(existsSync).mockReturnValue(true) + mockVsCodeConfig("windows", "PowerShell", { + PowerShell: { path: "C:\\Program Files\\PowerShell\\7\\pwsh.exe" }, + }) + // Zoo profile override points to Git Bash + Terminal.setTerminalProfile("Git Bash") + vi.spyOn(Terminal, "getProfileShell").mockReturnValue({ + shellPath: "C:\\Program Files\\Git\\bin\\bash.exe", + }) + expect(getShell()).toBe("C:\\Program Files\\Git\\bin\\bash.exe") + }) - const result = getShell() - expect(result).toBe("/bin/bash") // Should fall back to safe default + it("falls through to VS Code default when Zoo profile has no resolvable shell", () => { + Object.defineProperty(process, "platform", { value: "win32" }) + vi.mocked(existsSync).mockImplementation((p) => String(p) === "C:\\Program Files\\PowerShell\\7\\pwsh.exe") + mockVsCodeConfig("windows", "PowerShell", { + PowerShell: { path: "C:\\Program Files\\PowerShell\\7\\pwsh.exe" }, + }) + Terminal.setTerminalProfile("Unresolvable") + vi.spyOn(Terminal, "getProfileShell").mockReturnValue(undefined) + expect(getShell()).toBe("C:\\Program Files\\PowerShell\\7\\pwsh.exe") + }) + }) + + // -------------------------------------------------------------------------- + // Explicit execa shell path takes highest precedence + // -------------------------------------------------------------------------- + describe("Execa shell path override", () => { + it("uses explicit execa shell path over VS Code config", () => { + Object.defineProperty(process, "platform", { value: "win32" }) + vi.mocked(existsSync).mockReturnValue(true) + mockVsCodeConfig("windows", "PowerShell", { + PowerShell: { path: "C:\\Program Files\\PowerShell\\7\\pwsh.exe" }, + }) + BaseTerminal.setExecaShellPath("C:\\Program Files\\Git\\bin\\bash.exe") + expect(getShell()).toBe("C:\\Program Files\\Git\\bin\\bash.exe") + }) + + it("uses explicit execa shell path over Zoo profile override", () => { + Object.defineProperty(process, "platform", { value: "linux" }) + mockVsCodeConfig("linux", null, {}) + Terminal.setTerminalProfile("fish") + vi.spyOn(Terminal, "getProfileShell").mockReturnValue({ + shellPath: "/usr/bin/fish", + }) + BaseTerminal.setExecaShellPath("/bin/zsh") + expect(getShell()).toBe("/bin/zsh") + }) + + it("falls through to VS Code config when execa shell path is not set", () => { + Object.defineProperty(process, "platform", { value: "linux" }) + vi.mocked(existsSync).mockImplementation((p) => String(p) === "/usr/bin/fish") + mockVsCodeConfig("linux", "fish", { + fish: { path: "/usr/bin/fish" }, + }) + expect(getShell()).toBe("/usr/bin/fish") + }) + + it("rejects non-allowlisted execa shell path and uses fallback", () => { + Object.defineProperty(process, "platform", { value: "linux" }) + mockVsCodeConfig("linux", null, {}) + BaseTerminal.setExecaShellPath("/opt/evil/shell") + expect(getShell()).toBe("/bin/bash") }) }) }) diff --git a/src/utils/shell.ts b/src/utils/shell.ts index 31aa0b0fa1..6bc8383b25 100644 --- a/src/utils/shell.ts +++ b/src/utils/shell.ts @@ -3,6 +3,9 @@ import { existsSync } from "fs" import { userInfo } from "os" import * as path from "path" +import { BaseTerminal } from "../integrations/terminal/BaseTerminal" +import { Terminal } from "../integrations/terminal/Terminal" + // Security: Allowlist of approved shell executables to prevent arbitrary command execution const SHELL_ALLOWLIST = new Set([ // Windows PowerShell variants @@ -113,143 +116,70 @@ const SHELL_PATHS = { FALLBACK: "/bin/sh", } as const -interface MacTerminalProfile { - path?: string | string[] -} - -type MacTerminalProfiles = Record - -interface WindowsTerminalProfile { - path?: string | string[] - source?: "PowerShell" | "WSL" -} - -type WindowsTerminalProfiles = Record - -interface LinuxTerminalProfile { - path?: string | string[] -} - -type LinuxTerminalProfiles = Record - // ----------------------------------------------------- -// 1) VS Code Terminal Configuration Helpers +// 1) VS Code Terminal Configuration Helper // ----------------------------------------------------- -type PlatformProfilesMap = { - windows: WindowsTerminalProfiles - osx: MacTerminalProfiles - linux: LinuxTerminalProfiles +function preferredWindowsPowerShell(): string { + return existsSync(SHELL_PATHS.POWERSHELL_7) ? SHELL_PATHS.POWERSHELL_7 : SHELL_PATHS.POWERSHELL_LEGACY } /** - * Reads the VS Code terminal profile configuration for the given platform. - * - * The key must be one of `"windows"`, `"osx"`, or `"linux"` — the exact strings - * VS Code uses in `terminal.integrated.defaultProfile.` and - * `terminal.integrated.profiles.`. Passing any other value is a compile-time - * error, which prevents silent mismatches such as `"darwin"` returning empty config. + * Resolves the shell that VS Code's integrated terminal will use, matching the + * priority order from Terminal constructor: Zoo profile override first, then + * VS Code's configured default profile (trusted scopes only — workspace scope + * excluded per APPLICATION scope restriction). * - * The return type (`defaultProfileName` and `profiles`) is inferred from `K` via - * `PlatformProfilesMap`, so callers don't need an explicit type parameter. - * - * Returns `{ defaultProfileName: null, profiles: {} }` on any VS Code API error. + * Returns null when no profile is configured or the profile has no resolvable path. */ -function getTerminalConfig( - platformKey: K, -): { defaultProfileName: string | null; profiles: PlatformProfilesMap[K] } { +function getShellFromVSCode(): string | null { try { - const config = vscode.workspace.getConfiguration("terminal.integrated") - const rawProfileName = config.get(`defaultProfile.${platformKey}`) - const defaultProfileName = typeof rawProfileName === "string" ? rawProfileName : null - const profiles = config.get(`profiles.${platformKey}`) ?? ({} as PlatformProfilesMap[K]) - return { defaultProfileName, profiles } - } catch { - return { defaultProfileName: null, profiles: {} as PlatformProfilesMap[K] } - } -} + // Zoo profile override takes precedence — this is the same path + // Terminal constructor uses to set shellPath on createTerminal(). + const profileShell = Terminal.getProfileShell() + if (profileShell?.shellPath) { + return profileShell.shellPath + } -// ----------------------------------------------------- -// 2) Platform-Specific VS Code Shell Retrieval -// ----------------------------------------------------- + const profileName = Terminal.getConfiguredDefaultProfileName() -/** - * Normalizes a path that can be either a string or an array of strings. - * If it's an array, returns the first element. Otherwise returns the string. - */ -function normalizeShellPath(path: string | string[] | undefined): string | null { - if (!path) return null - if (Array.isArray(path)) { - return path.length > 0 ? path[0] : null - } - return path -} + if (!profileName) { + // No profile configured at user/default scope. On Windows, VS Code + // auto-detects and prefers PowerShell 7 when installed. Mirror that so + // the system prompt matches what VS Code will actually open. (issue #82) + if (process.platform === "win32") { + return preferredWindowsPowerShell() + } + return null + } -/** Attempts to retrieve a shell path from VS Code config on Windows. */ -function getWindowsShellFromVSCode(): string | null { - const { defaultProfileName, profiles } = getTerminalConfig("windows") - if (!defaultProfileName) { - // No explicit Windows terminal profile is configured. VS Code auto-detects - // the default on modern Windows and prefers PowerShell 7 (pwsh.exe) when it - // is installed, otherwise the always-present Windows PowerShell 5.1. Mirror - // that here so the system prompt advertises the real shell instead of falling - // through to COMSPEC (cmd.exe). See issue #82. - return existsSync(SHELL_PATHS.POWERSHELL_7) ? SHELL_PATHS.POWERSHELL_7 : SHELL_PATHS.POWERSHELL_LEGACY - } + const profiles = Terminal.getConfiguredProfiles() + const profile = profiles[profileName] as { path?: unknown; source?: unknown } | null | undefined - const profile = profiles[defaultProfileName] - - // If the profile name indicates PowerShell, do version-based detection. - // In testing it was found these typically do not have a path, and this - // implementation manages to deductively get the correct version of PowerShell - if (defaultProfileName.toLowerCase().includes("powershell")) { - const normalizedPath = normalizeShellPath(profile?.path) - if (normalizedPath) { - // If there's an explicit PowerShell path, return that - return normalizedPath - } else if (profile?.source === "PowerShell") { - // If the profile is sourced from PowerShell, assume the newest - return SHELL_PATHS.POWERSHELL_7 + if (!profile) { + return null } - // Otherwise, assume legacy Windows PowerShell - return SHELL_PATHS.POWERSHELL_LEGACY - } - // If there's a specific path, return that immediately - const normalizedPath = normalizeShellPath(profile?.path) - if (normalizedPath) { - return normalizedPath - } + const resolved = Terminal.resolveProfilePath(profile.path) + if (resolved) { + return resolved + } - // If the profile indicates WSL - if (profile?.source === "WSL" || defaultProfileName.toLowerCase().includes("wsl")) { - return SHELL_PATHS.WSL_BASH - } + // source-only PowerShell profiles (e.g. { source: "PowerShell" }) have no + // path but we can still identify the shell type from the source field. + if (typeof profile.source === "string" && profile.source.toLowerCase().includes("powershell")) { + return preferredWindowsPowerShell() + } - // If nothing special detected, we assume cmd - return SHELL_PATHS.CMD -} + // source-only WSL profiles + if (typeof profile.source === "string" && profile.source.toLowerCase().includes("wsl")) { + return SHELL_PATHS.WSL_BASH + } -/** Attempts to retrieve a shell path from VS Code config on macOS. */ -function getMacShellFromVSCode(): string | null { - const { defaultProfileName, profiles } = getTerminalConfig("osx") - if (!defaultProfileName) { return null - } - - const profile = profiles[defaultProfileName] - return normalizeShellPath(profile?.path) -} - -/** Attempts to retrieve a shell path from VS Code config on Linux. */ -function getLinuxShellFromVSCode(): string | null { - const { defaultProfileName, profiles } = getTerminalConfig("linux") - if (!defaultProfileName) { + } catch { return null } - - const profile = profiles[defaultProfileName] - return normalizeShellPath(profile?.path) } // ----------------------------------------------------- @@ -340,34 +270,31 @@ function getSafeFallbackShell(): string { export function getShell(): string { let shell: string | null = null - // 1. Check VS Code config first. - if (process.platform === "win32") { - // Special logic for Windows - shell = getWindowsShellFromVSCode() - } else if (process.platform === "darwin") { - // macOS from VS Code - shell = getMacShellFromVSCode() - } else if (process.platform === "linux") { - // Linux from VS Code - shell = getLinuxShellFromVSCode() + // 1. Explicit execa shell path — when set, execa uses this exact executable + // regardless of VS Code profile settings. + shell = BaseTerminal.getExecaShellPath() ?? null + + // 2. VS Code profile config (Zoo override first, then default profile). + if (!shell) { + shell = getShellFromVSCode() } - // 2. If no shell from VS Code, try userInfo() + // 3. If no shell from VS Code, try userInfo() if (!shell) { shell = getShellFromUserInfo() } - // 3. If still nothing, try environment variable + // 4. If still nothing, try environment variable if (!shell) { shell = getShellFromEnv() } - // 4. Finally, fall back to a default + // 5. Finally, fall back to a default if (!shell) { shell = getSafeFallbackShell() } - // 5. Validate the shell against allowlist + // 6. Validate the shell against allowlist if (!isShellAllowed(shell)) { shell = getSafeFallbackShell() } From 959826bd2bafc0d1bc0360bc81cad1df6cc5517e Mon Sep 17 00:00:00 2001 From: Para <62068271+murd0cc@users.noreply.github.com> Date: Wed, 19 Aug 2026 12:28:20 +0300 Subject: [PATCH 29/66] removed manual snapshots --- ...pproveSettings.manualSnapshots.fixture.tsx | 24 ------------------ .../__tests__/AutoApproveSettings.visual.tsx | 2 +- .../__screenshots__/screenshot-1-.png | Bin 135768 -> 0 bytes .../__screenshots__/screenshot-2-.png | Bin 87935 -> 0 bytes .../__screenshots__/screenshot-3-.png | Bin 137219 -> 0 bytes 5 files changed, 1 insertion(+), 25 deletions(-) delete mode 100644 webview-ui/src/components/settings/__tests__/AutoApproveSettings.manualSnapshots.fixture.tsx delete mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-1-.png delete mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-2-.png delete mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-3-.png diff --git a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.manualSnapshots.fixture.tsx b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.manualSnapshots.fixture.tsx deleted file mode 100644 index 0475258609..0000000000 --- a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.manualSnapshots.fixture.tsx +++ /dev/null @@ -1,24 +0,0 @@ -/* v8 ignore file -- Manual PNG fixtures are baseline assets, not behavior under test. */ -import React from "react" - -import screenshot1 from "./__screenshots__/screenshot-1-.png" -import screenshot2 from "./__screenshots__/screenshot-2-.png" -import screenshot3 from "./__screenshots__/screenshot-3-.png" - -const SnapshotImage = ({ src, alt }: { src: string; alt: string }) => ( -
- {alt} -
-) - -export const AutoApproveSettingsManualSnapshot1Fixture = () => ( - -) - -export const AutoApproveSettingsManualSnapshot2Fixture = () => ( - -) - -export const AutoApproveSettingsManualSnapshot3Fixture = () => ( - -) diff --git a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx index d2e5995758..a61a968a68 100644 --- a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx +++ b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx @@ -5,7 +5,7 @@ import { AutoApproveSettingsManualSnapshot1Fixture, AutoApproveSettingsManualSnapshot2Fixture, AutoApproveSettingsManualSnapshot3Fixture, -} from "./AutoApproveSettings.manualSnapshots.fixture" +} from "./AutoApproveSettings.visual.fixture" test("matches provided manual snapshot (1)", async ({ mount, page }) => { const component = await mount() diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-1-.png b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-1-.png deleted file mode 100644 index 48e256c02f97b587b32b30623ade2796cf017d39..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 135768 zcmZ^~WmsF!*M^G}DNb>RqQ%{v0)^sG+}%C6w?J`shvH6fZ*hmB!6CR?a5?Gkf8I~$ zI{A`ZN%rj7GqcyM^*r~EP*IXaM01_pK-1_o{n84mi*;Na&(7#J)V zxz7?BUfCxvNS(Cv-g~H8%a{F=u!2bWB*etlA;ZYnv{b=xlsYpFAr2!FW)ps%d)H*X zCmF|=tMxpt@ysJA!;(Q*l&&8H_UC>~3gmWP*Hk8 zJWtVz|3~ju$9ZV|VsyOE0?9)|;nG*;V0Bf|FthCu>{99*O)}>sDn$rw zGCY#$yMDHHfT4WGk-ZcV{^lv8ALGSDMB>K;St3gM6_oX_w_LE_2XFk~{3KVpih#4* zK;fgIXPsud3^U-&W_9#_M>mNtws0B}G95|E9ifs(G6Qi9rRqqXR(&arG{+B~=!w93 zubPos@Uac$diUq$d)mnG?|19C0Vu8IzY<49lSDX&y2^0ZZ?vx-G;=9Fz0a7BvTUGm zCG!29i^ERb7ZVoz7qR%*OY1&F2ev++J35;~?*9%=*tv0lv9`Bh!~BsNjJVzGvO{EO zQ)94U_nGRM>&JGXEJlOlV355V-)aAP-`&Tlh!-#IyCa&nw!Rx4&O_9g<#(U??%?4& zbBh~m>OknHRy+N{LRCn-e)?4ZckvR%@j-iEZb;Gh)_;V(mx)W+YPh$g#6*eYTPeA6ARrgQdzr*F*%5rA@^{AV3J@MAWp|*a30V9B>4X4_LdA$TeNs92NFZwE za~mDN($dnNo)*J$K{MPthovpXnZF;u-aYe{!2FxA-%KM_`doMKdU`>AqDBn3tu?xG z%nnjaN>L9-cvu%zi(8;zkWFd1*OY42*P;;FE=;y=4(#tu%;bD+BXx8 zsOmc5>aLcu;DUFqgr_c;Hc{)Mf3+8mk1$Qt$swx}emCu(x0eZ^)1!ap&lPpM4WW)D z6!Xr^8xu6#dvG7QZoJCeB)REo%;^AR-A0 zE?4f#f0aEEtR86DnyTkqO$d6zpJ)BAZ@E90=yY}It|%#S@$3SAkeH&t0 z{MgtMdknuyRJ#=|w`~y3PaI)uVh(6sm>aKO)GWxdOI}rbJFe|+Faz6`YBD|+ELK@W zL$r6!-?tBqJL3?Q6Up6P7ehl)5Bf)WCSLhFHvFh~(HbNqBpgceHuuyEpm|oRMpx{- zvg8?`8W;P@$OoqNUZZIp z2@%(|U2M`IlEQG#W?7#$fbeLK2-N6FvoZibUl)DPMU}v~*(zVvzV{>`N~z_$vX%fL z#!wMm*MG6GMn* zvM=k1CGa>FAF)J5Vn`^&!2OXA+$tcZK55}=)`K4wKAzp=aGWYrjX~OBg3I3#L|#JL z@+!Q4I{L*dcBa|kzdj~>6#Y6hr6&;sv+Qa`GdH>tH0xT|tH@tm$&PBr*}RVl@JS)v2=@*))g4LFhNR3oq2R@E1V*BZ`n3At0?r^ zWBgB|tM{z=Z)nue2oR!Cts8xcj>qNxQYT}sIr#p45X!G#J9t4~*f`X_GBGoy$m=lu z(JbX@kujQ%POq{0Gc5a6$Yk(Fa`8vvaX3hS2O$R8zz(?$eYM0%>u6hHfhbCYlddKq z7t3@X-O)}#zN)JlF|5FcJ>dD*RWC-VAr&ox@PeB?PV`1-Amm$Sm=v%8xRan>UvYp*R zm4p+FHmX7nb_dOmy1&@)t(-H8+q)b%04f46Si&CXtv~OO6y0l_QrEPBwqd$WD_ZL3 z=EbAhpZHxkvv)Y#*4Niv+9<1jd=?3O^@CXq*~#rA0%9y;+J)L<@z_2qW(h*{HlCm4 zZGK7%ew0ljHIHTtPn37(b2R^3dS6YE^I7kMm53P1u>gUzo4|g5;A`Luh@S0f_-RV) z9EalVV1U9a&{KBhN-MP}*CXci3s=(nig|e~FV!xY{DEF44a6v&kFJH5)E7U=44S4& zt(x8Y+Y~N*d!8QH0x$2B^gW){m4zo?WU4a@lHnFuRqexxxRx>-5eBIdF1aHg^s9Bz z{iZOV<%?J6=O^A#f!o^bOAIToh(IH%Kb3|U1{_$Tr{}x|Go}w{bD)b~;-dxJ8tFJ0 zF)>`&yELMyQXC7o>tfZ~;EwD436Zx>w+=y}g=zz!Bc#HztNGxf4?~YV@M(d?Uqna* z_zVfNppqcbMjJUjI!gQqM}uAWLy0E|Vh8Zib9~O09{A)YA38Y=k906l_Ju?V4c>7Y z4;5XE#M{yBYw1R|3fU0~(?Hqwz2cbf!nZiNF9pm7qn(~h-;SYoK=<406WN%vs$na>Elv(9pIfk) zZfJo&@9vWIWG2t?n9==qa(UA90E`tpJbasEf?dY>15sK5{0WIzfM1(_LnH~1XE*UH ztH62ZHLv5^Wm@1vTI_tQk=Irz#eFZ*LbcwV(c5w0uEC$Jl0g$0D#IPSku&>4+jHaW zaROI{-1H6Wt3Pl|m3gr|OOAGSD{XF8&{q@pXZ>ee{C6Q}p0-!%(jNcsgW}}0iCYH-OHZ)>?UH!mON@q8LBiML*y>se5 z)La)l6rrEW7Qj(D>cBYRF>m~|)8e@PSva)$wm`l(ek7;$O*a!~9c~HJ43khxKu_qv|s58sNEWZ{dNG4!SDazKt0pWtk z*nthd_paHm2DbE8geU*D*|bfK?BFy)BrlU(U?So3*@{uH0&U9oujXQ?5y9&yNC@6d zB|2jjDNOOK?d0kK@yD@3XYAu6cj5B8rg}m+3rOT%n_PJh5dL8WeDGYh93oU@WwHxkZYXe5|6^Bs>b}!oBwV*j> z&xm;E_h`f%i5n@e6EV!M5Id}aSlL)@*gl)r%}7P8iqasZOXmU*yfLTlw<-U?3uBue}XX<$MB}w@sEy=sj>bp zS%xNdJ)Lz#gl4^S{VPZB|2UhshsWr8y%+O#{PvLLC;DU+cm+9}ExkSqK|t+(m~dM6 zJ?}zGpDj@YuSsDD{1D<>_o9yX-;SVnT&mkTe?2=l9_o2}>QUZZbA2)xB6S;|vr+fD z+h5f8T{Q3%;FaCDSAHA8NY}aIv75Bd?R+TFtAR%J2%Nz{Fv*5-w!LoX$gHy1OLgF* z)!1GSM%~`t$}p|Zz-4e*VRYg7d0kx+G>ct)nHH(9)q&@(@p?mWEAiy3 zu-rYIls&hz>{M40c`4sFy#F0nL(N^cJuOxG`n+dUn8|-#cuf~QCPTa5W@XfI)K20X z7M30Bq3F$3qcwi^ml7#AqxHM7Z#^X;*CsjO<}X{oWmK6KL+ez)EwC4B*153MI{Ghf zR>xsU7O&HKl_Upha?wTi?_gMY3Noi^4Z}8{(_WQwAn@fGl@;z|&&#RPKFR}`kcYcF zAlLc1LD_E`+-=o7SAc%TjNkn@FLpl?SL?1a`9lT>{=9=T4}c*cCqAHW(LbhRG$`Zn z(F0P~s>)*iR^HEf5(O4u(Z-$!-u#Wq3%niiX}X2fz8&_Tv2r1DlYEUcL_5ixjknz$ zNg8|`g8ne~2`7RT0~|l{IVU)&WV6J>x%`=1JA5HKI~USDS_Lao63NfYb6^Qk;R$-ZrhW*wsad zYg<>>y?EnGnYS#bYo17E# z9<2M{D!2>VFt@f!-!Ik#8<(euolp-N&CGg_3BMwM^9#<7{USLcc~5Qh8VibRP(`?n zHySW(Y;k0Ys1(nvx5TMFxk&B1325MG834ZZktf1By|BIQ_V~RV8-~R010;&Adl&{1 zW%O)nOgQVWCTSZ3*P>yn|8kYqGhQZ6o&OlIdk>B~KRcs)5qq48>%J*wdpWTZqZShW zL_u11`rz{dSqwb2GXgILK9&Y@`XtVro~X&~wn%I*{6>jjspc}(N)|Y&G~CbZmWt!8 zr0&L?#qCSM4$)p-H^Xirv-#06#%uRuzpBfN+AQ>NQs|tf&}~YDKtteRC+To;O6=`9 zMa%GE^E>9>+E4@Q42chdPuQ}g9DpMY!Pnc<6?(a8%Fu!=+|eNz=@33)bb-0?ES4Nq zFZHt!8Y|}Q@Fw{08Iwd935|=n@kINAjeGIIg1N|(~NwmZ0GWPAIpJL!cil!v-WfHQs3eI^?Tm_po-r7#uUE4kP^FJWO_n+ zY{-xtbyk0Hzz@!!3!`okE$?V5c{^(dknBz6t<0>=w*ZkUXvz>KOB6C(@3EscMT$ae zv7&V(?GOT%E+`tEV*-Cn$5cXW33;ldE~?s`NavSu{B{R=V~8cL=My`w2X^no?zW5f zvjKnV!woLGaT2(1^n)jFOIbA?}(t7L1EjO#FwI!WSz(nM% zvIy-#ru*yPJ45&9HUQtxm4>Wl2MSXJf>9GN;D#g$gzwb(YUqx!=szT(4t+s-PJOD^R_G09&Oqksnsn7cW3W&fSu;gmAM z;&CM_hR(kcs#fin8%K!z%XNI`6V*v%*5j%?b=w8xk=*om4!CR-%{^}*FE^!PfJ}m1 z!0qAn{#3a8RHiVv9*M&DGE__KrU0`^nKLsc&Cus?sVLSm1yk5NV6C0N(92{bAxa|1 z%F(J|za|r$wmKerhQX$HVIX$l*7Q3wh&JM@FJDl8*GVTCP`<#Xu|d@DDe$HC4I%1z zbzhXv;*m~KxWIi|gj=F7?#uf5Le$)~we(fOGf9&OkbYVa_pDI>O-8*j!1)3-uB*N1MC0%=4qI#xN55#@kHJYu@oD14T`C+ae( zlF`4Y?S_7+NGrL5Q^ECU(G7+UXb|rSTVFa1VnB}$W~WInYypY;Cd0VTYo7nfP2lrM zah?eHM_kukBTk%P`})d8hs{fC$O_RJa>a41Sf|}9?omTC34HDPUW( ztf7IS9aCq6NzUxgDgHx|{alxY5v%TfpwZKIp&7v=r^JfEa+a-Rcef)5LRy$*bxs`zr>^pg=VxHu3+@OHZKdOE?kF)m3n zE#P^!3QZ#&)T0D*=oRMHI;;2fEx?nX|?sTdBrh{ z;{{8QF6pZvw$UO~;x!-na6#}zx7$y^U;bvy=Fp*-oI97WnnA6g?jdvH5+~|9d`id< z8O9}K3uj!nbLnQ<(f}V9hh8b$?e*cEkP4B{PJ(QP%#+0P%v~;EQegjNb;howxy{4b z*x8v2CQ;<3&S9lFnC0E;PSRHP?Rx?;Z((Myui6G&+Hm4kM~N0~`oyDljQDR{iOQG`9`mwD{?s%p_vs;GKQ`k@6ET3$Xos%DjFTQxl8 z$r=3YkODH;$-YZ4wydQ^x}KfdD||3m8_x}?D%t9C=K6J zbtO4!_E4YN8UyTA078uQ>GV_T(A)i0S4!?{to=F~Aq30t4B`51x4rajmmrQHs!d*l zNrAtFFS^@zA1Ky&tb^lXj1k9BUzeA+_bx-8g)t$K($+~Mil~QoiK`$zN?xSxNX7ej zP?Ge)1$jL*7W9gbN%74j?SAkmNM9XsMhZAlq^a%_=Yz7x5F~Vh_7SC=9ua*yRn3w| z{VAEO(s??TQ|HxH6=>>F6k6}zR1Yc0n2YC@e}0!&j6&2@m|FHa&V|qBe=NM@7ER0m z_I2rG`YZMd7L)lNJ-H*a@shS^=o|C!e(MGkgNVOb5D{*Z!<|BjvHZC?QZO?+c9!SB zaS)3K`QThe`QVH*D}{?#hZWDwJ8G=P9i#KuqM?&%E>#R4q8Y&H+m)#Zg3y<=QX&@2 z6ZfkVnr?d!k0XpJU93v3Uih(T0nE7HH}!4}q zPG(bap`Ov}f&Z>UWk^AAArC1!*-dINX@+ks2#(h>tTLjlD)!qpqJM>%sDgv`z?nDM z>0r~c%0N2K=e;Gg-_|K|(sSZ{B;1)z-N6#`67eI85`q_;N#(@*&Z@k_8g?=Xzm`!r z1N3}{Vsk`j;ws>hQN6*Txt~AefU1Q8;Nnt7Er7rF1|Du>T?}#p@52N6ucxKF4T=5f z5STQp4PTFrYsjh!1{q8{DfOx~Z1jp<5kk)YNz*OE@~{^l_FPTa`EUrwRJpvRD?!PX z>}?VkRaf&7MLyP(QSbbyv_X>C#(*lm?0(ud1*IltI#MnDSOMAJ+8@PpHX95QjC6ZS zL>>O#9|D6m!}2g+dPfM0{LIWo85IUu6#0_QM|SI22%5wDIpfRmxOjquvZ7G-zT`36 z$%qddFMRS{P9uZat(5^#|sRng_0mb_X@eTZD}ddmNp zw`8R+A2JJ!r752700$@2@FZ$!W5S5&iHuH?JlLbD+x*pI1X*Y?sMHgP!z~)D^cma% zDW{(Rh#m0icVV9hQ0Q~qKY$UZu5rMpJd65n&=gu|p*7|`76;tM0bk?*?i2YT&2Fn1N195qn}T8nDUW zm|#7@f|QG_W^->{6#)_V7*U*XfHnTg@q|nhVxpeqqBUGWpCc)=37?rv_q6@orZuHr zm%jf)2K`IfI_Z%E)6VuV8fJlzpK+X3v%U6)jT2abOI{+})>?!^M|>50T~vn(P} zYdxX7b2zz{xv@c~2sN(A1kyP}_)e$8S)j96lJe^$(fg#MG@f+0w78vq-GNqhCPHbJ zM|U89stbDML^}+UQafoK&*=N=M$0#E*SvXO5}W<`#Lz zQH?07#{3)R8>CTs5_&5O^8^Cwd#u?!f!K@l3M#Q7bk}NpvzowHpzwDvC^Gmbf7;~= z>UWo7P*t;#DzB@V27=?X(`4U!*8vyzXGgB&AK%WT1`XgHiNwZI)U*Lv3tDKpVeuQn zT{;=VHc;oa!TCof};b zw_TtXG1ID6v&5a{ESZHi1=*qct)XCl)6B`G@rajT)-@<_OF4tTIp{QMaFolDvVn+= ziVZhhVkpE#vViU2DpPBx-2QDbRW<%+UDIqD&Z0>Y;?OPU0ftlkHk(C=J^3#M75#!@ z{)gd^uwx$WFL%#m@KR-(U49%Z>#-#~++EXCAgkyzJofk1WF*Vc{G?SW)6_pwT!YIi zbRsxN3O^1ZP%5V50jq`BYfw1Z0$8rf<-PCPlASJoT9c${_~kxGi75b#0V(6PRdXzYz3Q6 zN9rS-uzut}yU1vLlpThx2)>-PRLbG0_1|t}Ppcgu0_*=COU*HkQ;p-LzT;7z=c2Z( z)Z8}~w$@vdq>kEKK$6L7OTlzlsxw(>cCfs)KctMbD}u*nT1@4867b7`b7U<4b#+d# zMf|KmuHQrgx5Q(p$Fj8s)*A#=h>+!2Y17U81q~-ruG193vbL{hCS9VC;b3Hl0M0s_ zUDPX7g;gpLa==54tDMA}nLAmuy*`^hWrW*4ZoX5u>tuSUl@xNfO_svPqx64Q7rRsb zJ70s?=TO{(+K2hFD4z~G_rkbm};I6e6b!mgqAcv$Gy=cSX_^+ErA)6 zmq~PFt_S@QIM*z`4+)hBQzieW1=Mw;OEb&e-#(w1w)VaM0?U`8p$5|Wh@50}QU=JqtM&h?oqfVV($?KI zv@Z*<@7@%%WY->WVpW88pH*Jq>%i;pbZ>94Up-tcuU+!B&Vj1WV2+y|DXHxq+oteD|ah8Ts%UaC%d0Nf8y0&kmPI9pSYBXbm)h~ zlt3bbz+GznPQ@%4U3QYhOm(9YGY{rw59_w34*)PcXJs?$wp%zG$BwGWLLcAuvuAH6 z^65kTN))KALz*%4F{4D9y6~H>daokXgu2Z*FdzBRII6&PY0%Lz%n?(CYwpAZUsa!5 z#%a%Osi?8rQDKsT^ECQJ{fP~3gE=ZRrh+5kYP{F@-ci`^XRRxXQCQI~-?vZybzQvw zywQ&)UJ>o|u8=FGUDLXl9>?f=QGd}BbrAOgFG?1oZ19rvNm7BBCRvS0&rsNg8Z#Qj zdJO`HneUO@lS$f1rvW)J&MDAd`;IUGTKWIyuD}0ECSbJ@h4O8O@As#nKMRJ>)^T*( z!?{9!7e8P>lLP`&qP_a%?0nzL_6#bGAr=ByFe)c3yDJAoyk#~3o1vXD!@OqPVY&ZX zMVLF)%n7Hg)QavnnjHjlk{WIM()|9D1s%OP$5WYn1=Z_#+YtNt(%?A}>QcoolJSgUz{ug*@I4yhe5(~d!&7l|qL0f&GwrT9^k>DI? zuKjOL(d+IdJD^2|TH{I$2sR+a#3lImVr`#tk`-se2&}7+iY_cJGM2`PmibE$ksT ze-Y>FwFvBC+%Y)3l=)P_=d(pxsry{5Y-&GzNto3yn%Nh} zD=gGAB4mWZ*6Ks~q-o7Di^D>l|3>JenPscLkf*posX|8L)c(v4t6?YqMOV2xUAU@n z;OjFw32$BYUcZTG+Wg-P@YCcguCJ|M@;v}^%{YClorc;v2ifW`rQ;J~^SvhFZu_0TPaJ>TY)WKivP5676U4o854}Nq{y29VXqcQ z6gMGlPzUd%e(1=gU)jVw+AS-FBR5k(CSr94^`*JCjVybOSr z6J(yNuygoP(i|X4qn|P-l`xA%ty1KOpGV3+U1IT4fh2%npG0_}8s8iALUT+K1&{1vhByz)? zBj*y$nkea<&#y-?d`K1|afpIRqiXwq*Ch)PSD!_7bV~hM&7?ium+U#~C!*D6wdxEA zH~pkJ%S3b`e4n$(SHc+SV4;&9#=jbCu7WlRB9+>NqKoUUefS-ITxKz{`cHj!ceibP z>9F;g~xc~2=%lnnj5 zhfL7Gt}D^U|ABJ9Ob48toJeL-8E|_SLc_^;-S(;!=+e2YCZmbC{%N}F-uv~@xBWQE zXRB>o!@HGDg5vg7xZ~cJXL@gLL)Q3Meb?H!m3&+h3wM6p#4%U{^*Es}n+Unbh?bQu zA}E!)acX$dPLr7*tg0)4tutjU1d;Quv}qHPaU>?x$bL6d9^fz{-su5(DTih@S=B+z zdrX7K?E8!K_d{HvA@T#!A|^>+IE6RRh+HEFLR8uLkQeSBZMb7Vq!N~JVw~^UqvwHH z`8)>kHDUB^gv7+A#^8tFza_Rutr{SVw$^d;qx`%p4}ObraxuG`%WL5cLwE3E$hLq{ zij>%6sn=5sT)1d2!Ptg2G`?-GMa^DwtNan3jq$u9F?A~6YL3N=ll$s7fud(sf=Ti> zX!PX!GKknJBTW+4)zw8g49#rzC$fZ`);ll3L+~BY*ud8Fd<8Y9Q4Mh;9n|Qw<4mEE zzAA`m4%H9y2)!i#%=-Lfhs%fo<DVu)aW_F`Ms#J*Q0 zh}$Re_7($+%MM$`JK?o`-FldfR)ry!E%_ZOluDtp8;^%IzG$oNqHdnH?o#IFlo?Md zK+m%pr^6OwhZkSB$D>l1c&`$8U8ax~5tT6BTMURUZwyZVBYS=5>$)^(25ILAbqu3= z*p_24z(+x7n_lISO#jI_GI+f62P57o-bnA&th#ol?_VwG=TaJLil17SyS1-NP!ExZ zuYzIC?|s^{NO@IKdys_zAT@5Udp56BmKh&DYL(D;%xrtFdn}F(4iu z%{oqkYlHb8F&EuOQ%>o=0X6_3@^n#_J%S|cI?BFNZ~nk4}ZmsZ`mLX7GS7aQKY4-S;EOD86jA1tSL*eakxnl$lljiXxL&ijtC%{r!dvEke!niLf@r? zFJGKkR=<@e5zntl-&<3|dWe&V6}G>o`fe}L?h`(iHq926kaD8k%s1L-dVmo)-Z7CK zcn%7aa{;)!ACRI;Ph3zUD%R0xH|2l6N^fPndr0ZcNv+NeDgKzf;7S{Z-Q+iT?K6O~ zIP&`o^;b@b^|@UYC|*kc0AWM`^!&o%G&v>bGwd%}S`hU;TeU3e4tROgub-&@Vy>NK z#oZNSnLM(Wt|nxbz;W!%073I$;Zj(D(uru8RcB4h{}Fic)bn;37x>Rs1l60# z4qkm$bNmUM=?i1-%cv&Re6!^NQhgODoR=vgCgxmOpOGP6hq5Eed7}P)zQIO$-nRn$ zyT;}HYKHcJhJe8XWjh|T>ha~Y8Ao7PXuyIJLhG1bitPa5{AFwoce)YRp4Nuzw?^O& zUt|8%QT~YZCJ9;N+MyL(xh4|QgdoYGmMzucw9!{r>T>Lzwj~fxEQW8NbD}ixrOJ&$ zBpd3IOr)uPLvhN~rCZj*Nd}D@$s#xo+;bCa^&6DsHj5TO%EeE8QP?Tvj#u zO}4XPJlA{Ugkm*Zu}2d=Jaq`Gji}nj)*N|GOt|eG?c!6>=N^DY2`8k-ry+pHw=j7I za~0Ds-?wygR|INEP}(hy7bNL~0He4|j)5DLAd7OA3%@pC{1oNGxH;@>dqCXRViZAl zvEf9m!T#R`ug$k1#{)5zEO}NA)pR**I|Rfz2l(6A+y7Nux`USVc2-4-UQBttXRR*a z){#)1qw=g`!d?{IGCs+o!6py5$=CBX8cTiIAt*cY__Vm{KC2jo?{9JVw|LP2BHtI$ zTNRN+7Xa?@OK5y~*;sEd=|enw4u89#*qh9HaT0rWc@v+a2smVV2+>i0%zL{Ig!}n+ zTKi@@ws(q3z}mSTsjQgJ{l0mr3~DV-OSPJduSSo5_gHiUJ}Uj67O?VqRQoEw@8Y)!Pr-k; z>gM#gs|>}=lsKhTk`l&?0!9(nq9OYS2X%j_3UVTKdHXm^ z{`R3Oc;@ewEWtc|l_shMgBOr!!)Bq%bGcs5o<-gBjpXz}X72DFCsxe+XeYwo&dATw zcy=0 zRXh%c2w-+9uk|t$y=$@{ob9PL@UgrNhomykf9EyJX>IzPRp=?v$?xEY0A!sM=PX~v zwE>T9V|^*N*52cL^KTz4OFB~TXHXJj7N4l=G4+&Fr5Du6whXA@!1aj{MA(i+eR)ri z&3XM(sxaKi%i_3lrXPeO`cSN_fYSMXu=LM#a>T&K+dZw2k^g0;US7GCRj&KsuQ5@N zo9OYI+XBfJ3WYosVH%IcM{cU5intxFh5z>LGDZ5+g`f7OkhxXnPym|^x&{|98O?{%*v zB&qC^;ejx-0Sh{H15lQaw6M$LRJW#0y;?@CnUiYo_3>X$5vk<(dZg9U z{;-$T_MYR%@$ck+G!S$l%?Dod1@iRH*Aam+l%kiM&nvS!)w}(6^W#!Z0cUYWu zby4xH(ik+B%0lh^%W5)P019kz7rQ|H#e9dJ-Bi7r&MW!WQ)oK){o_FhDr+77Xw4oI zr~6l)_t0v=Xg7buN3Ujae=^7Spw-^S_&5?!nd!KfP-?{g;!iM{%KtnIkK zwk{%;FEu)s*}|v>>>7NFnrPGhx8H0b1+LUrAqBQY?CV(^4p+v2>(e{oA0ExBb~krt ztDW9pIj$=lI)&jo<@>0f`>5tyQ(sXWN2B*kFZaQC!D#|}KXnF*<*xoX28szJd3@F?nIO zOUybk9Q5aP?7Rxj2`j_PEIUm;TUxvRE5cvs%n(;a7$NHtig~<7;#9Ex|I8yoV*9y4 z#m#{5#b8#*s9uXrQzX(oZq{tXp9`Tgg=~K8my)xVmKF!bv=|F%+C+#QDdJz(D?3?P zr0n}#-?I^Ocnw=-VHB&RmQZ?5bWL;1{ygC3+7TsEAp-Zm~o0}A$$E=6g zayQF~EUgMmg(G_kt?|X@LUmH4hJ~k=`L9ixIIRz+$s+<2f7`!}0oP{Z3_bRYBbuJC ze$>QDl`7TruY;$0=JYBIe8DVyFVFOz8(yb925v8rOr0LyW#_NOxr&v1jz%p- zjc!9FP`)TEzhp8KXuXA<<5=_Io2}Am88tpWr&1nJWCL$9i)+zN#%{r(dSOk5)FKMu z0{c1VuO`3itwPUPtpTuYOB&t;0q;U(iIhQ$YSRF;8Ve!$!w}eC2tHN~R4HpFD4odb zaJOo!-JbiNJ&RlW_4?#GrDhqp^XKahC}Th$-> zF#+&=zQ25Xe0%C|w3)?c)xSR()tWI=%HX`b8epRK@f9WoNBQzH*e?a|F*n5>uySx zFtQJoLP)~=J)sphOUuTr`*Q=p`+8S7aPwwXSvKeKWVUt;#$)gKq36ywt(GV=g52Zi zX1kKD>-q7xwohbY0e?OSWMJm$Xm6zKTgOOaCF0vezC))44smI$Hwxn1Y~O>Hdht%OyQ4D zC=aWZl?zom9qpRcKkCIC9>)cMR_@Vx&igqn)!J>QFSoCUz&)01x8djvF2u1Er1PHr z(l-x_>?zGvKbyMRHLh+;FLc}Xoh6GQGB*wO#?xgxC_~~;nKVYSZ(ij&KMIBRo*U0V zaiTX%(O`V#TwaTTz82+dcJH$W^{dl1dU7u)rg$&+mM>;9O7&G)prINFju1K*db!~e zT%j+N_dhy(3UC2Wz<=xUz4{R<%lhMoqnAHGdBgYszsM4Nxo=3!=YO;mi!4EIejO7qWZ(6TxH{aA?%?2DE?r6{)q+?0=p4Eelg@JN;AA z5S!5D5+xXlESW%#a)h4bT{aPk#L&Xwl3OOKGA_NGE($KghzY-T{YyeS#>yt`)*WO~ zV)tkeus(kkVp@r_bjv4x3S}*wMihbCq@A^Bg^+GubAx5_m;CyPhf+Wtw zEEM_aS(RIop55<~(?Pzc*w$1R?Pa`JX4vMrFn}}3?9@Z32rrFS&`ie{ePdAgJwp6k z+(wRN9<|bA3^OLnES8VFcG1*te5~jgNFfQ=tX(&M_g_zIom#hYtJ^LQlq%hVh_dkLh?M@kxK;jN6d9B16BqnvH!Wuuo0IS#^FPnk0MaWb-HS z>7awu;F8zeA45VHUfuw9;@h$b5!f2O5}$u!tw$R4CXbJ+6qj&H+P#H~)B$7V3&Yr) zTjZ1-v`)AVx`otj{ZP`dCW$1=jXG*-5Fz=P2g&iFzCeZOavfXz8E&ZV>H{Ro#%lZP(0Xe|hKE6`fjxn7y@KgOa*i@D?EJ17e^p}Vm& z>0-%p(zK1Kv)0GES6oE3mHIYigUUIeyJUZUP@!>rfKfHuBki7lZ3~V;&Y~MvX1YT7TYA}T!ny; zjeEr~YoH_4Tf6)FgFNa5v;e+@VFn2XqwU;`Z6q~5qxP7PEUl9*cH5Y6Jyf{Gso6t? zMtEiwJ;qLS0J^+cw z!KHg_2E^I2bFp6#lclOdW;Q2=$#3CjCDaQMWxmvbjMru?DGY{(jsKPe=?kT=Xc2Ml z3vnL>XfTC4I0iJ#)=kf0E!;z#J@&^|B2YH)5p#)CcP;G-3a;}Ijww7e~oZs+ryj|4B$s~;D;2~ zIK*+D3Sv`kMwOVR6o=|G7Rfk+?6B>Jxv&<O9h<~DrTVqf86k=$ z=9J$?QAmpRiP7z6ONJ~rMuc8U-WBq~v|y(jPc^ti~)laEcM2toyy zh$n=CIxa{v;Pw<5joQ1X(0nsj(Ihg-@5f<-dS-NJa4m!i)(c0u`k)2I2}>TdL=)=R&2!a*Cp+e9p=!?L=aA@@6xHHS*Wng=g)hvMJ;cbhigh(VO zI2PDE&wnoQ+wK*2@QKuhE@Uw|<@vQcQ_@l*isoDa>JQbGRynbHkCp1=!i#05SqtjU zxUy~byu3A}c4`pKiHM|l>xc5C-4_GhO%X;z&y8Tyl%~CsOQ!Wl)ltK=Ey`PuhZJRO zs8NNHOnMVUB4`P=7d_enlDZ43mYA&3Tbgo#(h3XCGAFtbeCeZ66}tQ{bru`IbhGxp zoYdSiDl*(aM3iIGDpq$dZ2&t~wC4#8v4{*SXSQd$kY1^E!cC88`oRh?@_m7=J6x|5 z)?AmP+lgYA?Kq9_m~u`9I3s>LNGJe#nOM3~-HzDpUE({l`S10|eCVvaQaA9IURi0~ z3Q4QKhhBpHu%!B4NT;j{$tw{LT?+Mi*dt^0H7+GxZE@!roLNkot!{tvbU2$3x(ueO z4+NAPmq9C!9-32wCv9zdR8$8`JKdSzrh>EM^(AnE-uBMUb&g6rQ35w6S0j7lgk?Fe&j{=Odvdq@IdyEE&@m*7 zn(YVxwo(cI&7XQPx;uK7`Oc(1>A$ukQ;drG6ulfnN+sf99RN7l^U77ZF@DSj++Y8- z4>AaNDFkJS<5);e$cyHM_g>jx99Aq!m>lAhe)TQh0sLnls@aT`1wGMyvv)P9<>Sm4 zhiXVrwqDF-`}0}n<54A4^-8eQf^{sM`oF(NY^<+04^hZ4BFR)BR}{a3fEZA;TXbeU z^)9=t5_q~q`!(|6WG^O5^yyI96VQlx1A)S=eRrMuqDIx4Gras}NniH=oZPlpMd;ai z%2&tYq_v!jh*Gr1o@cmOMpsLp4DO6vPiVQNPh8~1=3H+7j2g~fs|$a6jKZr`4aF1# z51Cxq9Z#*{-8cqbN{C`Eoy*?zcZ~9`OGzwS+E8fV4IVZ!rg+vzqqHXeD5jG!UNay| zGx&e_dZ*~RzW@6>wv$GU?W93t+qN6qw%O>!w$Z3@W81df7!CgW^Bv>&Tt4^b;_Nf_ zd9StRoUgguR{>b5w)^8X4G6K<4--MQCOI~*f-=F41S`6Wj z1FQ8TD?BXtX4}!+l+~-rbfUbhd;HQ^nHFS+BX>`he~wT*OvdN+9paxN=6R6PI=tIj zU?Vns`U9~X1N@MD+HFUfdKN7JtGhFcaz*xE(=pnattK;R?B%66lQKE(_%Cy=+A5#B zqe+|P+8iFUxvr-zpZi%!#SGR#r=sv?-STBRp3U=`ajk!dXC{{}U#+;nZ*Se=rzL0q zf+Y}eV*WfS`uw;+W0e|`=Twb5X)NCYk7R@^;1e-qz?+gwqHx81tZg*7;`dR^mZn3h)S_@Q$#TJ|C~(j4|rGMV)(EUN$6g<~IS z%HYd{q*HLV_yDgurNI4C9Q4N^0jK!<`jp#sjok?6B8$s-Lnxr`dO&*{L>bbUCw{MC zt%pX;0_}na_NHv=K^ej(ao0TZkkrlpes$TVW^&D$v^6B*(N6rSG>gml)8;dKL^@tc z_Rt8s+oUeWe9E553g*>kD4tl*;*mh8MvYD}on^PnB5(3|vSq8?s5kgO2@il}E-ug6 zrg`0m1SBYXwcLUmq+F`IbduB(G+#G10ekN+o&7O~%RqAYXQJrF^+Qv15*^9USB8qNf38!;E= zp@=iJ8IEL2l87%1lh#*P;b(}QM@R<{gP<*>842`w_uSJg^1K`B>gu|?w=dQb>`CLY zIZ+S|Iu)%J$_F%_RL36A2OE)wDMp8)9{Fj^php+Kwc#kL}S!#((Fov&E_`V;ZjYNhUXkfGJ$F)p}XO zfXl^#-k|c;iQ|S)wC`Vs=Dx?xSfcr1eSevN5iT;=|0tEuQV@7Kz%lflEv_;1CiQ{l zVl}eUlV4MOKX@@H(HlE#n3NzqLXm)6y1cxM+gz2S)#fp@XhSgz^VJ-qVQgA$nF3+Z<3@GwHoY#C#d(f}3=^Hwq&iQ3zkNQ` z;yh7j#2kV*0B+JRtz5n)!8$r7k2T1!ZkbP;R#m&UpO7vli;(cL8K3+|QH_=ne_%A? zMSli^e7&(u*em`l%tqp8$0>#--L(Op8=j;keLOgMIS zcJcg=E0~IW-vG!x;bc+MFo(k?b*W+K&$;mg#8MF%30}`(PY+lHG%rC6?*{rS96x|} zHKpArNCu8tWuygBNOSEE{lo;THQOK@uf~OTWg1q*YRFySDfpWfVHQ|jFk4@We-Js`N`5VZPujZU zzo#ShJ>VeNmdgJy#fh>=i3SZZV=p*QDoQDfs(?0FP7EtKNsOThL7p5z!<0azuR()d z=Whi8t%^*FP1lGfLIN)mB!Uv2s|4;euqq2vZ&{A_JFy+Gp;r8Tt0w--;n>B^X3_Pr z7X4@IL+<-XhRnBHX@8qTl_DL|e~WWyUepcVC44jMCNj-B zw5DvyUzXo87y}e0O!V&fuCZOTr>T-Hp2wi;Lf$tC37hFE+!nBmTPBabe!1^1z$U49 zI~pyYRBM#d*0!Rx-5ZGV71soVMc2o02o3?W_%(jH-U19*|H(`aAlxY{_v5LB;?CwW zki_65%Mz|K=*T+jvBq!1GYx;qRaUa{q4i=a6 zo`77Q6g;RsVg1K2tEC2#()8=^)60gg{vI-Ap^)>Qu+PXixd3Xmiz<4l^0QI~xjN*_4 zv}I@fP8*v5X9EWEgpk$9O~|>!bIEE1b_WeH+rJDiODYA|2_bO&_QLFrfM^%fM~^sQK26(sZ1N*%72r8A{0=XfBZ0#hzRf?f&WyO1uK>knYhGd+SP1cn%$BqW3xiy&A}x14NKg>H&%?VD{w7S+ zW;IkmGttB++rwW|MDl14ZZuL7xq5HV3DI-DItz{#Hs)W7p_m+P@xU?{pHU-gmk^|leK*IK&k z(qL)UV~rP>&UTF5gfFCV6x*!+vdBakX%)!nHE{w#M3nD%UmVSTh<_$Vec42U7>@?! zaUkno^an?h_T3xguC}|;2gbO%yY)UO(Wa}H4y89Em|!rT%%Yaa9-<^V%UABW-cQIf zwL!r>14cH3A3dUt4-zZ`E5UDb*IpIxhI>wrD?O(FQeMj66D^nK*;8XQ}O?MiGj0`d2L^8=_=zG@Sra=n^mD!^#c!l!Hc z0=@dL!-674L?8R`wB6M~80j=%``;F)&*Q~^&ZP!7r9~AXd5pwufy9r=NlmiiiVPZkRu!`4d zifoo_XapKy{)7K~K35W?ct{CvD%5w8{`x%DzMey_ZQwhZ)$7^U<@Z)CPz5|&8 zV7C8oIc)LG4b%_XTP0iM%BaP_np^(F(M$L z$D?80sPu7ex?)E9ezYC?{tY3f2pL+KW()CV8d)IVboF55E7kC=Ac$q9BeD+CWpib; z>u1IA%X^M7vAF*sS~H0vu2t;nJA_}}7I0c)l2PG~8?c9&Cln&b`~?KD7RPf|ZZ@6@ z&M5>YW_2yQK9-z1RjdmouvBLVWMJZhu>k3~DWgvpeATQrzaX-l*mDOQYv9*l9)PBA ze>}E;<6!h3KXre;|L35~t3k~ryr2&`tplng}5Q+|^7ahg}FRlgTaU%MkM#edzGDEL?(50DbP zey^@WU@1u2o>y(hfo}FHVuCNDiusEaytCos?Sbb9T&OA|x^s6bxv}*5$5GU|aC)~) zkuU#wo&U-Gv`jFlXCk7v0L|_M06=U=O7?)aUIvgF@6-RRq72yR z^NEo2$2vAq4q-@e+>ZDAri^KYrQ*w%IVZ@lRK`=!gtyI@8>EZ|LGcuZtAuu0%mO;alc3P^v#S_-`FqJI935M0nBGJOF^ zU}%o; zlcetMQWi0cq(+SnbXgXw71{IN@Z>LzsaEs=g~rr7LX9OKciXyD*&a*+m-STn9q4<& z52*8d9UYe5-B@K)>Bswf%m3~tU<|+hmOn3uxI3P*r$5+9 zdhg;T&3dqY8893EcBbdC>4s*ymE(89zH^;Gi<#%OH%ngI8eC_ub?h=(xh(ybjW@4Z z?fKB_b6tuwE%2U9i`l;3-mXO0`Uhv}YqNKhZLV|Q94P)1cFYUdj()xeyrBxlg~PmF zwLUyHe_ay%c*eXI{LDU8EvxptT+B0cX&zesdA^KCDJO7TBvY%N=Xo(3LDWhdE3o$~ zEU*sEuqrr$*q@91e$!)HzBjlgHtxg`ms@G=Z3k8`@S^`PUhoPkcb2TcWO%Ti_YDX~ zd&I=zp>5lVD8d}|AbMXccYi!Q{dww|upmv5djvO>A_jxS3WjbdwN#T`gEP`hsJ{DR zBTK?jzPg}9!y*TU40YSl{jVe7Zwhn&Dm-ythxsJ_jUGu)z4evpzd*J2hUl;&bdtXV ziW@;MxAd9dD$l?nP)1$mhbIOuWqFJ$}D`e^vt8zHOHl3^-p)J?Ak+*EtmT22Ca}g1pj{s(f0d{Ey zlRqP*D7pe}(3@_Zl9w4nCr^)gv@;Gmmh|xwC2CcYft`(087wcR6PEwR)+lKlg~w zTY=lRh=e=1?(xX?a?h5pOCFo+d*P&ppwgx!)|{T?)Y)SbYTT>>yA6Q-f_qp((($42w`ZbB(N$U{HuYbN;x&k-u7@Tta7hi-gN#nA+h)%D#w4Qd}3Zgr)KSyJ(!)QxteHO>RVjnbBII zTrQTBfCxq^r>y%=!xE$DH*US0E0M)v)G78Gay7(HlDex}uEikf-3DlUUMum041yv?q|jrexPhu8Tp#S6+XW zZLBn(Y!j2rsh&Fzwb-;|v?h2m(8`fgU}#w8gSlOfdaR{mm%yY(ftDt4@4n+7KrInq z)JB@)VljiW@+5sX5Dr2#sG6AOf6^0xw_a8gdJ}$p8Tz&S zHkF&JX`oww-)bhw#2r5P6hY(_D_+LzcZjNWoWXjTpjS}S65#l-_HfQ=|K|h}_`MtM z|F^caJszj&Igb*5j^-u7q#psfNNyG`C>fZHYP7u8o!LblzsYvwRo_`pI!pHNcB{WB z+>aT#kY-Ma8E&2inLh={!413rbp?bmq|tGFR6ZP)3EXj0?YC@u9nVh-7>0j@p&)sd zt4XZ?vARpmGk9S0-20OEO!4CPa+s#YLmrkPceS{z=?pG@T+^Gh%IY($|8x*@i4*Xw zl7K#9lEWCA-Sd!Toc-`-`$wsU1DiqbK4m*EL*ZexwaV3Fs zvpVgU3jzKLR(Ou55lau7G#K$=m9D^o`%-^6q_ikY^kg^u@i6goRmSqJKk^ zr=*S|jA6U+FSPM;KWoZ+h~P8iuMeOa;uGF1b+^XJ676dQ#%)BtxUULyD@eqKb}m7c zXw_&WyQlG08<~w&iiDD44%cWw#70WDE@dq4t9y%^6sG)6DT}NGv+Z>7xa0O!G#igb z-vSD>h%5nB;LaL(Sq^Pnjs$zA@sGj?g$!6JK1G>##zd!FUk3In^K&1q3#YKLQCRn)744Mp6 zmfPXea$tW+8IDY(LF#Z-zBD(EDm3#1!t>t@F;Y^ zMMLYdMmGA@q7Pzp#eOp{eR|oV6Y0cd^%y(5+kWA{3I;} z%_=4(6BSB_Q@^*yVv_*&3ZweyD%xLW?n8Woo9Xm0&tIYzsywMyW4xK!U-BE06T#pp z*-ZPbvkLl>nI*kQK>JLmafc>ySko*V!_S;E;q)(IXiGM3G)|o)%Lp}9M83BSc2 z+Zr08kOgE`m9!HRb%u&Z^Lpi@W5iT*qa^LuQ^|SaKM?>2wv*|c2BdPf> z@gR+7+0EE*pk*w!=UwE3+!#yb51IEZQ({FhiPOG*e__?Qv6ku898xZ`nwweL0;-Br z*GU@1DfM||4@v&Z`><%>d1dy~L?m^USZw8BTz@yiJLeu4tIHmX^Yu8$K%4^4?(?}B zX<8le@G;kl$jW_A80#>YE7=0RS!m^WH)0rT0Ks*ATH5~q zh#!FCbN!;wi%zk5&FC%S5hhD9am{lL{|Ezx(GYM;bx6{1(FJc1Vl|lzQ7Of^k ziCg+66CK);ZyKf-r^NK+Tiu6^+vA@k%e3)}RDKhO+(WlfLmL6xW^6G3V;_OXCZpZ? zAGP=YZwLah`jjI3oZ_F3iP=NXago=pPHgu-sH-`n+d45N?6F{Lxgq$i0Z{K%c<8Qe z2b}0A-tYkl^)3yO^=*Ldbqvxw&B&|8ppM$02Lz%?IXqY)N{J!}JqOo!lq8xV^l>aU z@TmT@&EWz0E;_MBp*pv1ry4qPpQY;F%TbXJAKcc|?qj*xLp#t)OOFi6a_(|{3s6{@ zfc9S~hph!YjQXeV7AYUME7v%J>WsUF$~tS7tvSRC4rnC~V3@xe~m*jSgFVa>PYnJ!vf8 zJ2h@xMNgW85;}e1XoM;;`MWV)`Ro{X1xJeYoNfwq^Ezj9xnGDT;ia94w=qR$oGpU% zEP)aH#EVX8VD#V*l{lHKDXC>}sEvhD{eEhk6>C*V=ZnM^>qs7(r2PBXiU&OfKXqgg zLg(k6NDa`TKa&NDpR%PwRkG_z2$6=3s(2Cx*<67|(3d{7#(8kdu|yR6nPwA38$|_0 zwCEc$Vff6H&RG6_5#vgg%tu@}@to}L{67UfZkEur%e1H|mC`V@nw^zDdfRt$Z-F{^ zi{Vo@(!@B`eY|GdoT(~SJf`+=;WGf?x{FmIQ&KI`6ux13!56@7HIV(qO6!=y#<94% zD*ftanmt!ao#OxSZ7{cZzW!M0WP<&{`auyqV!khbS5@$W^pZzNphEadt4UT@r8FL? zJEf?kXSs7q4%7hXo1C3!#$4E$!byHI1+JQddSRekeS&!iIyQlu9Ly8Y485qZ@Eg=G zvp_MSjPEbBfDnPERyLNrrSfk!(Qi~}(8Su)+dz9ncbAcHdJOuM!f|WSYZ?nKURjck z^Dr@s=R)SEBr>lR2*U}HpM-9Z|1ptA_eZnAURg&Ig2 zA}LqDL@|clP=6>F;+Lmb8I5=EiUY3|tQA3Ir z)O- zkv2sF=M*2%#D@t}rAZ*lbdq{fTL&9~&l{3Z!g90hi07VPSi*XO&l9VplXfi8SvBFV zBCNEwv?ABZr%y^2((Chli~?x(oTWE~3A2L-UNXFK1H4@hp;>QBX_Cl!GS*uDe=%9` zlX6tynYWhVDM~s{;2cgaWDZ5N+4AQ3WV3sOqscPOh1$|0)$A;E(Z$%%9iy%tMm~v| z9dT>wWP`&GwSN`vNp0&D3M$)w&IvkWRI=Ztd{3LW5thy|r$WdF&9GyXi)Na5m{9MA zztV!Ah_w~`6L~4kVL#zw&6!C3OIRZIrY|o(k0>01k}oTQX`!}z*B-5axdH`;K}L>$ zqO~wHQ&P!JqRVhQ3Q0&v2qm5hJdVBCaQ-U6cA+tbB7a_*KcY)}|8`!~nC|!%%DP%1G_}^W}{MX!o z5tGKCEdmbojtFD&N2};75KdSHDYGuBPdnM($(Q{4q|b5m=kLItBnY0t_uoKo5fh4hpkhXdd4a za{;@F@>lK&crr6Jkp@jnx{X#Qm(!jPAfN;8*t}p0(wsX`#5tiI!(-~|LGOjw_>T`~L@YEFi zQg$jP#W2OiybOA+f1?$BgXgr`oGFdZCTuAsCIytq;8o=H#p)5n`U81Il7uOhdDEQ* z?k4zCT^jZZ$Kf9c?y_NQf%DuEsdc0fURJRpGoyYBu3P?th7 zRKYjL%pCLKv%E|u>2C5Ftf|WLO4>UlEtl8RvO6Y0WkugVKnp$0tj;;Mf=x<~RmG#4 zohzw0dqb%>7^axUzLbU<0U{*^E`r1C*ndUXAQt@LsT|%szejBjnQy&f#1=HxR9O_F zP)b@uityAaeX{zIFAd2y_~uezlbJYa%!UeMsN4q$jZ-`}i9-G=E*z0BTU zA1EXec2`icU6G8<7Id`d6!B4^g3Gd<$AB_g&*2=8r~q28sNa%Z`iIOkctnJk?@&si zRPf+f&nlhx0x6yxbTZ7Ooj<(J=IZ{u(g}em{#bJtg$KZ(B8yn^E!FC;FE3L+W)l3h zEg~XHXqCoNEBUK0nr~T@P6#~(b$GmNa5q98Ukyn5fEysnrtr&Ki=!4E%}kb9_)ZA= zRL!bvkaKZjL2aS3q)R^6xX1o?w3Nv&6*A`@XpRw(skSN&GQ1Frp>)a_6Sp<~32}w; zf0ESo$0ENX-wjlOmCzyyY5AfNdF&GK0y$O{VX{%OmvKNV@7}SPY>DIO4|KRvX1<;^ z+W;d$g_F{Y)Bw4>+*J)PU%+x#E;JbxeP->G4`Inmmd|1@h-f$8ZLtMph_vc4#JQ$5+%Yz_e?)` zAvk0%AHF#kCrft7BqvNE(cC42FEiOUwVTHLOU)M2*9AB;12c0yMi({^2Mi)#b}VKb z<-%ZU0?vcoEOvqMhK@c3)0Z?2H+Fk?<3-$TbP9zx*%d~veXm6vFU|V$0}x(&6E?hW z`Hb3+OkwJ1M62&fH%W*U;pM@J94EgQs6?bGMJwdlaaCx`8G|g#ZTw`C*TlZoCh($#_SQ;r)k7(be$vG8fqJBov$w@w|qUGLXZ-1ax1nqpAn$`T613m@w zG=WGAQ};LrEv4vh7%d&G@fN$^>pciiIFGU%N)w$h&t4nz-faO)HP)Xn=MqG%xCMk0 z{hl^q(!lC%GKc{>&ixbAwYqzC3YvT4ln!DS>-f1^kV?X9jrp?e1$J3zHy?nJvF zN5h9a1nwsSJVGK2$5F~OsZrTLEEETQpUY-3;V&ShF>vH*WX_GAi~s69iYF5Yn^G5e z#Th5#wZgC=IgoLhHNO*fK*=DGHmXs6k?#W0d4t!@>x~LjRvsJp!W;DUCsXW#)ci4e zW{p~<$!O7D5pfP&*GrMH2uDjD(}ia6X%Su_rd63;$snl7Dh>YnJ#Z|m^g%dTWsGt` zm+w(R$qUtHLi0GD_hx`Ul}$L2nNa60D-3ETEiyv1X4H?$Pv|Jf*CMW^V9Ft)e)>q z`kuWnnI#6mhK0QY=*0Qwu1}mIh!fj|k6}UJJwoWQDNSF@mM@xb#+8cw4OEg=Co}{dN|$RsWZi!4_{2#GTd-rtr%O*NK8?Jb z6Qk)0cpDBl$Se)$g~pk2eQT{Zn(}>xk2;>(y|XCVLduTJzc5`@;MHowKXK5YzkDG` zHeFkwMfzwopYnWf);ylffh5m2HGM%hRXt-8DR(V?j=xez*Nws8cc|H{%f^ zCUtBX(&xwZ2Pb^T&f8tNCEOA4t#?IB6^m|g`;)kITnBc~mut*$?ZZpo=bOIQ>Q0wa znM*>t6mjK^CK+;lKK;34cE#(t3c>06#91~x9-1Ua$(oKF{{`#IoGlpfjUj6^RTk3R zSyf0?``mKeVY9P9yY6}DYRR%RvPp+lHH!T$3{eiTz)Zz#fr}9HOw!xn;yO#vW9z(* zVcH^i6mv*b<3Xk^eLVc*If4w_Qd#vq0Mf^jACUSx7Eq-%oG9d?!CoGKn*& zw?0g@)BU`x%$p+#asaEh(ep@{oJi*Yc^d~(WR>L^^Psy7=yd7O95J{4eFNOHWID)& z9r|<5YI0RM%XFEKi?b@Gj*AA^tAK>mw|ZGY2myol`6?QEncHNLLg@+6H&1ayE%;hL zF+Oma>-`FVl?Do&rb>F=7fu6iM^ww2!t9W|IfS~F`ZnpcaIWlknwe|?~QYS!3k zO7&~&9}GbiC||Tl$FU2Jli8zn*J1erRk-T>{qDyt3W&98#$99NyvYckGCRJ71Y!oQ zS*POV-4GnWD#$8ubeA_S2n$z4u(ly$*MyBGv*RoEQL=m)3VQ*_$J zCrzjG=U1!AR$Hx`e-}{1^~l2!z8i&7&&2 zP#V|C#jep1?>WR1gO5Hd)$VH!Yg|w(%uB4yWGzMpsa9r18gXXw|95f2aw-CXspPZ* z0$Qrf(vU~|K8m9dJP3CU1|6Ms*XBXa1Pry2LBikA#}B%Djy8SIwn0QmMd`2fvsyh> z@;?fcOsG(>`l~oD(V8AKJt<`+_ zA6xgmwB$2?Up6hFdd0*Byo?)aOpfUVkp=7A@{Gl@XEljdLRW-aItRj&x_~@O!f@UaVVvay)i9%W!3#;4 zJLxY&tKW;iOKT85X-&Br{9#R+U5FA%>7&L)W;D8`hK`wWKM;B9R+WI(W5k!TO0XQG zIeE%;!p|rp{Jb6dYH7+R^qW@9Iz~OsY?!G8P6+l0PMC?=Y}G%7CHlRmXX%lU*J>jM zo4C#T0pDbOpgb)I`=E8n!bj4gLhnZFyZifxKqHY(9Y+IRliJWdG_v}R#o9X0iQA#d zVCAuB1yzs~*_>QxAuMh2{7Xc@Gi(DATS;cc_gT}%y2;;PC$EczeLi6Yo}V!lAuwZM zN4=H93yq%XE zGUxfu`F#AXGAvRTmXq86-T08ZwFUI1C?ie_KJj7J7sYGKv{mc35P_YY6X(k*6^ZnM zahNPC)1W8|r6BBsk}*s(QW;(7Cwog~4ybGLC~V>zg!1#7;K&(?WEYcrfGYUyBn$~e zA{f{ppY*9H>Kr-5Z?1Jkpq}BMdB6PoC5kYo(<{iV#t#uGQoax|>Y?EiYQfJd(eXDI z&i{yHzmTa+O)+I6V^B!VeOp5LCdo_NnU6m79zwa!h}Wf*)&}qx-G{$*C#@BYUb(~2 zh{JV$p?{x!7Ts8*p~sjwp2{`Q$ye?;j)f+zi5rse5_q3z1i}Shg1sJnrh`O#zm4)5 zW(+|X%luAmJP^k>w$ic69u)aHBDEj^S~1EYnQvfzYLmROEN9;Vis`@Hir*FMYm}5z z%jb&Rk%PlLnUuAlGT|vF6(=N7G=DYl&IliiSs~YSe&=8>iUMfV*X`4ZVmcg#)xp1*~M1n#OojwbxZ! zJAM^uC;6C&s(E`b{DiPMCx)BEHezx*={JB)m+=YqQ^KCB<@u+LK_u@`99Rx!nZv$4 zAzGn8lZ(_i@%<}M#MGz!BfVmfAW^TYyzAR*LX2Mt<5De`*at9QH|J{yHT!?Fy9$xxEaS~zM+#r zTPTZsW5yP#I5^d($VKyvHAiSx6QhuzH}Ngek}A+xj}#fVq%bH>nJdEWg)-tlvp*Q>FBxGt>`1V@w1RDa~YObUqiEnub6@p$r&mxl2k)^i!eqpQyDP^Uw`p+JH zX)%2JfR}lue6>HrWpu4b>1yj?N*+2r}K}_z7lF6=Rrknlt9}okZ@*eeAkWEdK<+REwLhEN@yl<#i zs>Za{sty`8lzC(_*d4PI>`9|}98zsEqnQ*bB2Iez9Rj^3QpB41;{-o_8b$#bKp8o@i;L#*azcvVp%79K?W>Kf0 zD})_O2hlIe3X3rhO4d+Jxhm)zBeWkoKZH9i9#}99E^7t3gz(QBcE~0bcF0?)FGY#2 z7q?L>?P|MZ*Jpt`5}-BkRLNh4FJqd;j;6}HKt~c;FO&igw7O2RqH8`ydLfArlPM#) z35G$LLNCq&FBm7h=cr6!CTK4bYF=Oz-zYi1z?{!CNXQb^bjb>@(`GcW6arEexss{) z8z?oebZ`MJwx}XMkz8&J{4m|y#(W^x2O+f6CcM~h_l%0gaxB3k#g<*U_@@QQg-+4B z3HLbHu+?sZi8c!4`sy{WW+P{+BMl`bxivS^3LszDogK{j%TmSa$ZPl!*BcSh!?R{U zxfb7&7f2E{helPZIq>zckI`%n|E!Am=P}EG^L)=Q;aQK=to*ZNk0h=+63S0(BRf?* z5MH*T#&`rstZE!L#vEapu`esdLTGpMVH zd%M>)XDP=jc3VICCF(y}{&wf5CBsu2^Ooa56R$Zt0#D48v*F}tzZ?K57|t*E(lv$K+BKd1bdsb_!!} z#(2Isj?SVW=o)>OGZcTD?!x(7Z_jkP)WT$$T2{xCcxBZ2+4h9)Jwo(Z*zDPGVsMl*bsf2NZz`0vQ0r?@z`mDY(dcHxSvy|Ly z(d+O6ri!U%q4dQvsX&o^AIhMmip?@dDx}_JY5u0}VrO2I*k6@Uh$8y6+9V~;9`2IXUkUgcrzsymA`w;6#GI;j<+9O?f zZUVY?uJt98{pB!7K52fH;cD@0>zP)vd1iPW%-CdHRY8hq8Y%sp(GJ zs6@~(U%R4hj#XLPW*lA6Dbc}3mHfUs59&j%09-V7@}v%NuvaCjmXweQ+Gk=`R>-c@ z311;JMB=CYBA3EAjwD3>0cd4?omUDqOtRP&^W#KpLyfqgv2{p1#4Gls&CvT}_g zNpbo-F6>uFuP~r7mkEh3O{QVO7xc(<7n{ZJ5Gb);k4WdG+Zm(UsDG#{kTa3`mS*fM z79mVJ_$Gyr-*NrtD=X@A5?yLmMv48eA1ZBmi>-S}DmvnfiUgDB{()jS>_hl!wr$Ml zCP@ZzFNe~`p-mC?<1O+cFdU5<^0MTmKfmc*p*hJ)3GdNWuimE7WVv%7mYMzRAq!q# z`%6b>`Z(_H8d*b)tU%5Z&!OYvyN@n_nxb8QU4BTV9CI;R$~8HUd5+y|^+1mvw5!(E zFR#6V75~@zA50O_YaPkbkZhN;TL>aR`N$e%NzdrTj<0Y>jvVMM}+Se zuJMTW{)50#mv}NhMUmUkd8L`vYO|TM6fE7*F>$017-kl)I%D)jyhbkY zj>3@DWO6NK(`F>av{+-1(;(^c?zoY%C@)I(3rPFcH9sl3Kr8dhq7E|z?lOxS zil&-MA0+fc;s;Mb)=^8q`N52=N$x%Tz2NeTlx*Vvrv>nJXmVD3{A%9RK!8e=-$XaD z7K7OtL9CLPIAsUoI;$qnQ5gMJq|Gy?P3WxlZIxM_|D=vkwn&K##DJA(Uny><2YO4l*I ztURP!L^J&yyv(y6;l92)FnMm8PN>eQ@=SpqV(OY`*VCY&$a{>Ie>YtD-Xm zcpx{?qSz2B09Y=Vle0QQDB+;T$gpKyU%YdAt2Jp=7#CC$allM17|l;U$$V+=b*x(K zi`1}6-=eCO+oBk~P-i3T72Cu0@rcqLri8n~)Fdp*WQm7pl^&MGrok|;!2_{~V=2bL zWqU{sT;SL2qwXy^f%*8Z*yOO2N^hWsn{3GBvUE_?F0Do8<*VCNj49q9b=+jP$!yA`TiG<>$^?hgEg>g5{UH)|)D*YtsNz+2cnMbP;Acr06KH?#iXaNc zZy3|2Vvo?B?Ey;PchRXj8+Fz7LT{7`6ngI@`kvA&*8jD|_xbwUTX7q2%}bqHVUhgd zTdIkkJQl$^C)6LGsUDiZEEar8SoIaR%5t|A>5Vn2V(=atZe#Ahg%oX!knsbVT3*}x zcWaG-QjMq0zO7s)=pLbLZWf`cYW6g^1gvdDInBLl?Q2qmN5z-{LtEoat*o%!s7e}17wkFZdoW*|I1$_`om?INF%jg3tbioLO| zn%}#p_E*>L^g>-@yqM#*E#X@U0lalH6&1-+zwo(d`ldLljab@4*1S&Ke70O*)hKAG zAzN+h{}FYLVSUGa8xG61ZM&9j+qLXk##***+qP}@uNIeG%ii|JbCdrcHi1EZM$r1t$NHQ^@E!;Mc2;HRom!#x}`MQx!#FwY-pwB{)tJ?tQP0n zg>Wq(CJ)AHC+W%`o}Ti644qa@hkh$sDUFWYz^f$Pj}GstXxLq^**+7Fzm{WFYCbS| z*Pi^`#n3Ppn0s;J14kc^iGrp@)*U`<79+-!5|X!taGe{4?}Y+tCN2_tCziSr}d`NMZTa3`*0hEDMRd0c83klW|&FB zHB5ZFhTn9m7o^ac%ZV9K2-rEmEI_~AF|`+dWxPDWlLa1pcE!3&gD;x)Ftlmq7-Chg z1uM2*5BG4+x~f3~IVQ%NKxg(x^6_q4nDa>LNV{b*o~)Bj9ViKW)k}T$m$6|XPP{`D z4&J^^EFICTL#C}a22I@0PSn2bv zE_RBmsW-G>KYrqt^PZxVibDW7A6ge_RnO$|r>our6^5kz^c=xdN6uWoUQ>ncJg*0| z(%NDjTBHY0Ph9P0%zEBLM*DLi@5}AR+`Nkz#i#ajo4;-C-!+Zj<;Dno%G@==(mIpX zZOzrsTH9>SEM2I#yXAUTBe7I3V%U9}?CmFUrrDduK}PuFN$gEhG;UIabv$~zA&8kt z=-iEg+tIQjt|RM61A+FBSZf&)w$ih*?unNaQMKQEnMNtKk^zrM?R|L3I_lPCsjtK> zq1~@c>x!RJ-Ah5`)K+?|Aid~@yjArfiTyur z|8;4Aoo3+o0hpindCvy^zheQff?m_1%n+~Ny0ZvbArS!O0Hk6_xPrhyu?4BW=a$-M zbV0>?GKtD6$FIpu_7=#F$3LafQY+{A0wbq?-}RGHkF_3i&&?2kyoj)hXt&$)QbVQ) z16fA{ZH)^!0baU`{b&};BpD?h`yV3s)G-9}0%)z!^BA95gn+d+>P@`wA%zR>l=5LH z?$I>GggJmE%G{Jnso%?H@s)?8MUd zLT)h>^Jpdfp1F0JFt_Q{zuo#CkD!}h$yWkgQ}O|^Yhnrwc#?DqtLyO$8K0WpFcMD! zR~{u>$P5v>?CwlKrz|fd+g8ZxVnR|g)AE@`xx=5F#90LFTVV1kMGL=qA%_|h9MQ~J%wxl$8i`uLDcQC+0AWpcnUS-4eX?H}e`hM@E1h{b;r@{{Cl z$>C_a@uJtSjVsr=KPR4*m!9+N?-V3A}5+)`HAve95*0kVqC-S3VLKEYsELva@VEr0Ewqo5jCpO9v-yV zn?M9)N50p78=8-TvFGzTZEjwt>bhfD}GFJ^aTRmc9Askzb-jj~0<4wf*QQP7m0Q zLFy5+dtIsbgYpA!(qMB3uLv|vVIm9uh1ojOGRe*hu_yzFS58~ku@7HV+=LrE_LW1*DB0Z$c;Y%nCW^x5lp+e>1fom`W7jY1i5R8U8o(td z{__9(-s29G2d3_FEi0J{_&B7Hesu8ui}p_V`RwjU{_K&I9GLd%V`$k;ot3zN9g-3( z?6l~KnH8Z7C|aj9C~fdS@>51QiXfB~E?2ruA#Y<5lW}mhyTewjR&pW~OH&;`G)=A* z8Jj*^`qpz6FR5gLoo%|IG{10|EM3&sq8@-%)rjj@+vHj7>BY9P`>#}SDG&}886eLM zA+oKl@qFQwZ`7{@9nTxfoPf|Xk+q^O)4saXFl~um2>k_Y&gbg+Ny2=cZ@s_%!02Rd zbvbmeV_w6&irwx>6FYEqi zKzBlxKXf$kw;hZ$DZ*puG$>V09Y>eS)h?`}EvEGp)D~Co#6(@?*5!L2cj9n6?sOHG zJAJ9x;&O!We3>$?MeBQelXJW~e2Gl9n$P{)`SW)#i|_69Jq|IkikoPgLG91KyTc(f zqa}39bDuAI4N%hPGY!bJtqbf96UKQWu?-u@g8_x3kbX?eNQkq&Ji`{XEl6@GGvPsPjpavgKs+T8!&!apl2c!eP z{_d>_d8}iF&*dmKV9+Rsit#Z`3+sNRSzX<4z@&pDaL`$X;%Xb|M(T&i;uEk0F79BC zcJK9zlQ$SE(mf-R>uRu+ks-N2fb2^^uMG~eJY*Df#PjYvKIz|$Y`x%F+RY@p1@p(Z zj&`_Wbm6ZgMCG-{t=r_|c~;b?CpF;YKSe|(t(*G3u03gyqJY+!z#=+d7c7gyz{0e| zFF&7Z&sQXR@j4a}oZebD3v~|rHGx&s=(rhPC3~<`T7D~X5+yGVXXUBTy!vxxXj87| z;OoCzX-4q$Z0AP6*Q}DTnWC*{NKkt1af7^NPE1zuL zQl&@D^%|ojwe?POseSioqGR#^HeUJ>6!~CxASz+7rdNv@YCdXOjaYj)gNr3?VoS1L zhy^w z`rtY?qwAND$>T37ZG|H|DDwJN{q6euQ|5`~d=>|%j@WkMJeC_Wlt1eEb-S1u?f-58 zbidvS_z&g7|hA?cTG*qEc=N3<(TsCp}0fhkgAzVXE z3Gh-pzgxfTs#Lbu`#Ubvua z;PgMTJTLI=G$!+tB%=%Rc=wHu(Fp_29fT$qahn((>nW-h^MIX86n=Uk!|hvzO-P{A z_>sG*b`!%`N#i8f0$b}*w0X3UPmza*K{X{YJ2%h*8qwWZbb=CQIopNx&9|MITvHt~qPx8qk} zc%IKWT~ui2G>q_zC{l9qRf!jp9H*O6&$K?=WNEq>%27hXNoRfWWQ2zADl<>^s0FCN8cyiB zbAHlIb^u3*=Z?_;Y`>?P11f+crRRgP9Aqw0-T?NsV()=@68cZyZLAX*QbCWw);Xfb zt1#$|D@*!wv{IJoj0`5l-410RqwnG(T@w%b=?$(8H5($a9OMX6Ed$)aDDbCD(q5F+ z?wxs*Sn`~nH3Pk3jK(1FAk78{r8dBJZ4aE8m)U3kP97%Cb6`i*c=Eojtx6SF#|mIKNH9>DDQ?=8t+ zHZqmM{rIdFv*_=C9z_Me;A3HIn`|c8yNoq4#up)%+gb@XiKR{N&!7=C%$*_n2acq!QVi; zAiSoh@v{jsIscOmgu=1l(%HoqD5j3dhoF5^{KJjrb?V8HUAYP# zO&2AxhZ+(ZjbaSnURWR^&6Ti0j50*VgJyC(A`0UpOr&jdrF6-t(_zDF2kGU?Un z(xPQf<87gq>mp6*xLo7uE&a~bucd)18Kp^Ua$k0R=;3F1IYni+gz2SB(t6NBm2y6x zszcfE#6zC4JT;$NQZ^L?uJ*E?fB40^n>8((R%WbkF$lMdN250&0=32V2 zmY0g#_^aCbU-si%%U>xmpq;p_4$0}zU#un)~xT+^_koEq3v ztD_*)@_ysU=Rql=DkLq{0BJhl`i8_Gje_VxT) zh{c>?hu1X4t!tUy13eOZbBW+~E$Y}%`_?4Re)DOACW$o6)@43H?My5Q%geJO5b`~k zt@N4fu>xk0YV>+lB2=8M^qVJHC4Mk^v5PgRcQgyOyPDnSRo(WKt4Te{`3ijK3w6!x2&$BUsOM= zy4OjRSaZKI)#@_N!P(OP+deM;Obk=M)9|`tk#$+7sMDhMmiwAvu^?eQo1ou^<%%e< zl_NbORi~rOxM-t{o86K_Sk8i_k%A}=VLLv?`gO;)f%#p&=W`ojCdxZDpbh!ynJvRq z&`eL7T{L4fo%)CixHfyIbih3i6_nl*M%*X!@|D4#3zCARN=erZt5ukbuS+tsT$@_N zDAHG*o*r5*ob2~I1MOxkDdgQVS1cFA2Z~o<*fVp?1U0k%pk{yHgo%!}ij{4GPUaSo z1GAc8A4BXmi{9VX&M}i;-2BQ)Ef~W&r?>t1bj=cTUcKG@<}m;M9Zbf8WJ?O@=tQw=Nz>1KUd=JRTn>&qjOooedw@T z;>_pzWH6`V4C(MMQoLi-UB)qulnpsAih;Z^r`+o9`j%*NI@|h1d+u6+qmzcpiv|_W^!LL)s)V(Vm ziA2mmmq^LXedX7|hE{uRby;|>lUpY=LP~`Fu;11Ht&PbeUiPJ!b)1cT#6-Vn;AM&C zOXm1=U>;T5Q%lCgqh2@xP?>p3^;gCV>8uSdPDWCK@&8F|hXqIvVmJ-uFK?30Z+hHp zE_g(defYQRsmr0BN6eS(a!Wf-0>&!DC5F#*AgY&1N`_aIv+i|&XQdP3a;;Jsd(QB6 zu+{m*t07MY>S3lJa&z&1MfSnF2)MmgE17uHk#A~3PNN1SzaN$p8SWjwxKYl{QX9+t z72;9y;Xkh7{%%v7IiLW-zQ(CPPWfi?fB)3|ENf>V7j8PS*-!=Ol)t$mUidzA1aTdv z>$fvI^)HZyNIOZ+1Z;k@np*NE-AfEBXGLtDA2$m-%`;o$r|t&0XYA;jRkGmbMR&kF zV;{QZ{dWW&U_QgQ6}+wB<6kbkG0y=y-R6Sa`Q>txeH731`@P#wdJcC){1wsA%kfh$ z(iPEsWY5G__=%+y)#=m1%l3D}n%IBTkgdV$yeXa{OIWOYrbCn`hyXOR9!r2Z#2K5CaS zhe~Y3SNm*sh(bV_!jw3B4o3N&kcW0bNJp`5d(px$yg9P{;gzxH^F;Wi!$E%D&Tma< zrlFLdyOA@7EXau@ss>7IEQ{=A^-Iy0Wm2sj!Z^lOwf`z?kC-MZ0ybR)K3_U5IOMuj zZ$CFBD7Ot-lhhiF^LcDm#3As5ZQkp;yB9Bb?)#MHJPOv`XOh~2hJBcDUYwf;joH#` z)51D3AH&t_YB3@)%6{Z!*KTXwY1A4krV-3`$iCDOj3RCr5d2O#I1W-M)|>X~1K0&Z zs5es6>5BW3+GH0>`-vkqxu!Pu8@~fkUk=>=L@0@(844w9x{VCYHtditjbwYdkjty_ zM<%;;_9^u!P_-5`TOEd}j-ys^YJ8W?rQVsc_*U;mPr>&`#BnT1Y?kzt`98{WBeL<~-nWurj&^tC zGFypkST_TRep?0{9K3nWOHRrS#IrpJ;1iA9dJ$c*uYHJ$tx!RUHX+ooy~@i+C|01D z;y&;_gnnct`St;@EsRY@h&?AHd(kv6T6RoUYEQyS7F`))eR6~Dwp@zQVdAnM#aPZS zE{#rL`0rl>It%-*G?6}ipU$w|2@#4O&A?frZ3 zp1PV$n87nY_UI>b3KZERCcobcFf4w+bzPqk``-z-#;{wfe6ixg-5wkTk}615y~??S zW3zLZrVwtG%3!*`cFu7@^z&pR-|>PeLfnR-$7x|WKtt}V)~ZE!tSUvBTCdIf+Qn> z-~*d%hj}t^9>qG85C4ZlHOfw!^@isTmLrQlBcvc2EO^TN;--ecw;p&JmOI~ytfSWB zqt;rF5qC15?+?7CfmP(mD2_3uFOhp*&Vqehb>)hiOcFBH5^1?fcEOy$eGM?o`2bkI zN3t#@*W!NVO1Wba&pwE=~-G?k<2~U z;Wep?V_a^K4kw*<;B^&oNoiy%x1={+O$^Tmb|;(M_V~EC6D^s!;fVJl%{WrWIeA@z zFdJ0}AEd=b1<9$C8oMwqI2JM@#kR(BUn@9S|* z2KfIZfJk~^Za+-I1%cDK8x4^x1IgZ8L@)vTD_~mX5Cv~qu$M4Nj^PB~m+IAHzE6ee zP@bAp+9go#=Lxg>r5qy#4)m6Zk)PzZ)QgEbVdqBi7 z;k@?Tp{$FA;BBUXn}xM8jLnG4Q};f_;NRnX5C*uKG8SOd3NEirg7q+{V}6~j%f4(m zaf|k5B;2iEe(~?OxToesS3Z>}S615rKg8?Oa$vy5Z^eIH(V|r$`ZU$;dq-|O?(V6W z&2I53&yqP6rD%Z$0mqCRGoPoO>-oQ103s6NO(od(Z-hSfVI)qsXwnJYnhaVA=tTtv zGGJ>d^qm}|{G1X11OrQ~LQ`>=G&j|yay##xfw8zaswDVQWN9px04fOoql3jsVq{Lg z*=lyH)9l-P98pOK*u`#~nJ*>=)H>Yk*)y^YsrO-e4V@=R--{{v)vqfq$8$U^d$I)X z<$&+`ExaBr3n~(2{~?T%@`*0lcuNcHg%i|!eRqjD{}2# zvWFL7fJ%fC%NF+E+1(ugOpewBc&>d0sXl=D@~F$*?&48z8w@Wwi9V7Z8{v2@Y}-+C z-V_-vv_v3(TCL$2U+?@|nR6If>({MD`L%jO`9_l7!wPl0TJ8Ed3-Cx1^o*&I``f#Ncw*LnPt#=oeh2u*z2vtbTdlcSeEhBrHHJ3(H@d>YcY0d zS_S_q*b104#}4s0EK%10>}7>t_GiT6vuJa=*7JXZ{x}P^jmEl3zeRXqs%t0-S1*xp zUKci-rIN!C&fFGyZW_nx1JDS(cbM}|qyE9@cQ2!D_DH_Wqe(@a#)#DDT5J3cvvK5H z*E&cTN&C^kJ)$kpZCqFKf=(l=YgpTnsa&=jY>~{Q<99R@(-V_Xc{kruM0di%U1c~W z{NU3nH80-{0P5)^ zB<$-^`WLQy)J3J9sWSoBQk7+IzkSImb*qc0hf1=uUH+&zgw!y;tPQMsTINL$MQT`4 zqzo&K3_0R;RgPtol@I#IprsmO#VR-MQfe!g9)=`lD14Mt``HrpXsu)@zPL@k0j4ui z0ba+g&x%#B>PUHZTzb4K%RLG6MMRF8!E$ZKQ~0`EqY`aSKj&bjrFD9|*jTFYlA(ua z9Ogusiy?~ebEqS$BKOo!_VG%SDgNrQ8J(} z2YgKx6FO;z-x!|NP3o8&CJ>T!13pGhWt;+54zX0xi4YH9`N{qqVvSKC_X`M$P48qN zyprfj9>DrPj#vOCqdem$7XZQC3+PdSl(TCuj36TPkj+me>@Yf#hNn|JL!cQj_x*g$ z{pk&eAc2YbWAnUF_K(c-p=%Ogg8GjV&?ET<#N@Jh3b=xFWZ0TV{~()koD4V+ReErT zkR&eyfEZGo5y!}j%rHXY?lBa{i1Y^#KoZ3w#j92!f*IVrjSD@oEi|;ZKLd)lHPAbt zkSv(#JkHE^?23$GbuLRr<(j0%Ng>8ZR0HsH3UYu1kB%~?PXb1rWd+gjDtxK9-#MAK zuJ=g~ZBqIBxw>0F;LzRj*mNi%G*W;KB14xoOil!7x2jy`fkR|cAZm@Du{=9oTh8M| z?jTiqnA39rW++RksZ5Hw2zZWVnG*Dj$c%^*r;{-e$W%a>bWrke30`WF>L>1Z?!c#z zbhO@VrHheCm-0&bH)2IJ1dm7i{6*pt;BrzM{`z+?3|vSM8L0PrtQL@s0c`+34F83<1}K=j~Z`RfA0$>evj)MRx9XG*Js1$1!5)sBTRfS zs;7qoS94-V%(m;dEL<8-lEof z)Ss&zI`zKopxmbdcK5Hj9ksmyYQNW8>sbUXb(;l+PsdAbp{QUf`u{RNNDE7?6F_2V zF3OzhxR{?h*h^Vb^6C#Zb_w{cIG1oD;73KIs)GMIAukeK#5<+rECbLRXcV#8#4q!I zKjuH&K5oaC8L#{Q{*jQDZBDymaLg@~|5?DZbacv5lG%quxLiFs3cM*q=Sv!w7Qij? z)|)I4dL4Iqymu3kpQ)!g9pA8K^%(EG82$koWTCgQju;cs@rejNL)Wj60T5~%qjGsx z${P$-l_~^m#@*C^JM12@Dlh|l&J@bFaWH-lQMG}RlzYnlC8xk(z>ykPxDQ}kso4rL zIPp}Zw1U(_nAESOs1umm8SHzbirL)GihgG^ zry#(w2n#Ew8kn7|#1{#)Zxd3o%>(avuUeLAtN(G9_a$~2Z|Fz)@&WvGJUB%V)u06Y zVWK6QTO)@Q@)#?;ik@K-yoPFtwvjg#Uf}~RIV-G8(dmGvT>K|iwJ6Ns@)*LAYSlDC zG$>8z3N&OW1Z(zV)g(-`Nv&^x_E7vMDqdd>;*-}y{y>_r5kMHa6F1ok|dc(xs;!ag{gObD({m?@t@6pyR`!S1h!}gkxp{ zk&U$HXZ5_2@TD?r+Lm-9U+1xzOsjl9DbR8`WN>n;u5DDuMyyQfJavUqq2-9p}JFW+whY>}Z9^fU-g2Di(B zg&i$>P^{jvHP&JaH$gZtJJI86)SB@D4ac|*NcC?Zey$dfpMqA6VscM`@rc*=QM*q~ z%~sMh;_lL$3k#%3K~{Wxnh-(7Z?699*Mwef@ixOX>(OES5=RkQ*lbS5 z6nZ?wc=$V+OkHHvb04=^>Fgr0gJ%YtBLs)GJdzf3&%DT{lBk4_?uFE%3Y9>YRMLqS zAj4jQS+t)4ldwA&=!bsuqc|Rw4sH{8orT;YVjK{AzmO$KXx8a>haD2NeFcYvgA(Ia zSNKqstN2{0Rh3~y`?Y!NkZ%j<-$7Cmd|tkz#u1Aeks&o(yLc&ym3d2iVAqTl8i=9K60RtZL{sZ78+ zLmf3qO;;{98*zlo1Ceq=Me--XP2E?Gy3464bJ}(?uqR{gw9|J*Y}BEBM-3l;tHpUZ zXT2HLWN8GhrN3`b2z~O4@b?YGTGtk7u!qJA1#a8i0I$ zH}af9Kay(0y96sWG!tJ{gr<(|oA!f&E5JeE9}c}-v=)%Ne0gZ&lh5>EeZp_zVI@%8i`~#-9KM3SlERP zq$a;Au^ca88c7Hwf*P7E?+G6VEpVC2zf&_2o7}~O;e`$;KP;Jh)DTx|TIMD(Xl5xn zrR?jt%6?5=$ViPgku|AOzE;m*hfFxu_(3m;+laCK57EzD@;A{|haSzc{t!wL;>;X< zx8-sPHmwC*e`%e{PWKDprOun8Ur?$@mkBv#ya=rB`F4r@BY8xoP5^irki^YI7y6at zoUwYs8eroW&_^z6<6~jCf)get5i?tV0m@Wd0uKNYgwabhNv04HcLv^T`ds9Z+?`2w zzjlP6Da=2%?-O#NlyI?*44i0Xr`!nzJHzjSV_JHuI@vrah*@3{-k%MFmB4BrTf%N#@@Q2pj12mf1}%FwxefOTjXako7R9m=@iJ8CF1O zy1NsU)Vu^5+^hy)!(mDwEq0D|w%b?9Ky+V-LdCk**zpc0#rgR)kt0KuE%>7=kJ{oq zHU=7La$v8he5JDRnyv6+U8Tcq{xTvHRJTU8G{(isYLTA@)S1yUTTPAEs6|6e5B5{* zXOVQE*|V6stgrE7{%GO~ofr9G-R11tz+(B7 zGTJ64wrsth*x5o@(W6OsjEp`}i5#QoQ|e2Jc}6wF$jnAbkkxS=nW$Z)!2G~)Nva9l z%+e6iOZC&h@C<{fJ}MGagqdgp8V;?=sf7kLa{%OzJH6|cP|*Ym%kdcIDhj3^YZH~2 zjBzkhT4EdOPqA;7A8qnkzEn5G@j_Youz0N$aFz>-$k85ebN{;q9DLQYlbC`9<#o1Q zPI?g^lJi+^`9iIBTGk{5$xNd|G?~}__`#YwZBVSV=<5iy6)C}XJuWxUJiQF(@d~oWgPV*>_Mb z+zWrVwz7h>%V^|lE@Zr`eZ9~^McQf6Lel&Bnz1D?+}(=y;`(cLuJ~TcL_G+mIkci#0HlhalVHOaYee%C zb~{P^f+YP`{-|%3zYWy$wl#Vm=HtOB7u@P%vy>9afioZ7!E0ryZM8Y}SlwoCm_Iqj zVX1WMI`=@gZDcTSl|%T5n%-M*>{Ee9;K=RRh4qIoSE`O%W7_-3piS%aI+8<>$naO^ z{=t>epHiB9TW`G&$dZx#UQ?^v z(>QpC1XBWmO8o zmIBc4fm^2N--+lFq$@x~a(otrnNq?Do5Md4W!XnQVS1`ZbBG6uJ|yZrIT8Nr?N|B$ zi`_OIy`b+l5>htm28MYj*?7ZHs`$2NT!MNEAPiDy>I=pxXX(vd3UjIkRffQr8Jx@$ zFwrH&XuQF|Bxw*Ll9e8yXN1i+V#w7r(Dt%s{;2`FiC4+a4w5p?axA%Lx`-TVE@4+kl3S7{S4a+#K1F1L?ol38V(?}l z@|Pq3b%v>ZXG&&x;`txk$h6#o-6v5XXr-zwDyT<9DYMY;Z8^WptWKv@O>vDAa>DF# zQZKC}NohU9X|qeW3@wgGI<{9--=qRhP3Sby@%t%sF|1y9o0%`q0o&2)*3P^^R8}pQ zVzC%Y|78fq<;^Nf7Rid@bbO)d7LLIs}y1cQl-646d>OL&J}#)tBV_ zkCKfYfXeXv?**FoLP}gXmg2j#o6|7451Cp1-I`C?6?~#X7zCRFDzUGS5hAGC9*!ILi0BHnQa1%-bnd zqWCC-Ax{t!j>gMIHXNPeqJzM=bQb|KphZf|h)SG8H?vjtmfTSW_QBU^O~!0$RLnLB zkxf^yCMzj2TTYyAQ44=PWN{}+5l>7L50R=Yoc@yqWuT!$Xu^`zr_7GiC4=c1ndbM7 zR%PW4FwHvjvFay&-K4)kbuI>HhIxwd@DH!2GOHdN51z7N=5caYrW9w(7( z8;%^o7zZcs`i>2GQ6_DFP$w;TQX`XUhRnfY-n2?QLfq$%mjmUVv*T>}*0PIlM|v5} zOyL^qeC%>prrC`&(FVmx6Zo4y8xoPk#*JO}Z%KEz*S77$_|_f<%BZ{ySWD4BPI2O@CK;#DBLR~2q>^TxOsY>xkPDB z3X<41?JFPED?#mMwM{x?CVZLpJ~P#i=O6UkfdFFF}Vyq%T;- zYxPN>QVIi7B-D&_X-?k)mm!N{SmBCjA8$Ja9iDVSi&Ip`6suhEvznt^aHWQ9a>ZIQ zk;=Z1T%?2z=w!xzf)!7ykKo5=GG`kNSZy?ar;Cn zOyu$54Wnj?C5u{w^i*Gih(JZ=C)KJFn$-H*fmxg{K{7j7lkR#j&y}q*gGHi(s%~jD zl*#g3Uai>ut((c8E@;-5s4lS2Q#Ih-;VH`AG&TUBA(*ag6)Tso8nW%vr)elYLO1mp z^qf^wks^0c9$Hb_V+)9X3QAHUj&mCAAgxXMxAxKSg{-tpj9hYTE@eD$fOpnYfyPeRZu!(2o%3*1`c%$|*gW;MYq5sS zHn>Wai$}bFj6|QnO7SkDHqtTtck| zqrGYh_3hMpY#!SiR4KhYK`foxw1^69S~nL3m5FNGF^&hZa^}v>Id0C*tWtEp*Hp5_ zd?NIF*{cvr(dY_^VGeH%tj)|#D%8rhmtTw^Kd;&;-3tk^fkmT`*Fs=$Zw^|EDOPJ8 z%Ie*7JLJItF=$%;JTIDA$fUo+=+YoZZ$zi0IzBb6IZV_Ituo?(L*f?m2X_X!cqZ7h zD_PdWBo>K9rWQ7(?aHvH@#yEFelj9I7=i$g>Z&F+DlJh}ms$`5AFY;+B$d_RTt}|9 zOcoKq67}F@mtCn&ge2T!T4#+IqrQ-A@@RNBp2?uWwy(_-WP`j8-mKZ!=*1%1C>Z?e zG|43g2W@uDdF4^aI1Skb?lo$<>eLxb%AG|o$QY=1WJpW*A=kle0i{yJb1{SWr_XWt zP5RoufS9W}Q%vM4d?knhhGKStV-Gj~i}NY>a9^HKbLnWHIAY%Sb6I)7n*A1~$s+iq zg6zQ{wBx2D!B(1nv~juVHWloMyRK^niYU$^+S}OrY_Fkv!b;~hYbjTTF_MfxsNWge z)?*hh5DJZyX+|f;l8>h~sQ-m)pQ%s>7H zOdW1mZDF{czY4Q3p!Xe%qGDqrgt2)K=kasS;JZy=OL!sCAk}bXn~Ct6!3ojYStb@5 z$~8H?dPJ_bM`*P_1=w~>QY&G2QOkIUL`I&1W7m46ldV@k6_q(C@zKmXYEB(;8M-67 z969{0w`Eab*Vmp`4tp3O3^J0y29;verJM>Ducif#G)7bWg1NoP8Fu33Q&p5L+|z+g z9*4$LHUGX$#s!0^k9j~%WqOfC$B(T}IDLkDPU}0$%qT;RnkCB5w1zrW=}2u|jR>!% zIhR$A(Hh2w)o~iXoYgEpZptap7DdMwEAD4!mR-iUe-OzL6(VNawYxbR9wn$tmDb1# zC2xaJ)iT9$R3j(rtJ^EGTMZGf=f@q9MZ>gCxMN6OmUL;7>?dMPPMnJ?W3IHgX0%x`2V$P&%nWc8Hw?{(*e#YhxqWU&%P9pqjTe0Y9Q*8TU%??nUv(%EF&UC zHV~fjsTG2cUxrNtYt{U4P?j&uW-u$J{{==3UMAry`9Z{#DBK0dwSvW=vHT*|7Y@e& zLHsQC3YkUkTfDzt(L8Ln%%;6Z)1X=|6|k`hFxSQy5+EGy>}{`q!AvR+1zpi`a3ijt zDQNZ0wR}Zk-s7f3@X-puMuDVG44@-4wz(UtS0az}6r~9G*oEv1y4ZJ@`DBLUBuz(X zA#O#NfNvDK6qrUPI%)nzmLcs1Rt@%0ZX!WHlJz)IANMzh?p7KLwyKT*vx!<4I*%T|et>8+^ z+!xXk4FR+tCJtwmfzm;UTJC|yGf1CO)uz%!BF@V8aRbe`TRF3Ejr#0<$gI<2-g`{3 zIW(VQ3+|;u)*p6L1r8BV{k&t7D9Dn8;bv^<4Oa~~=W_5>F(hN~7X!cgL_e*P{9vv@ ztuhADvDFzuMHzzv1Wv?Q%;w~710x}wX5(?^5`u&J-x#8R(TS&(j0FY{Ub3i4JhltG zdougJ$txqCmTYD-mUe19PSlX*<$N+e-$34003WqWk5m&qhUviL*($sjRvze{Ww#b+wyVp`z#S68k!y;BzuNePz!ja8v zpI?r4N6r#Hx|-zm_*xsIqDP0Hm0!hd3AR{>LEh`3p8f^xq+sO$RjzsWO>B)-rM>Dj zRIiw+U;?sTZluw?>e>uX)3*j|^XHe#P9cOk&661cwE!uxY{E*h+o2!$KD?vbCtD>n z^s^aF?uT$6_I0w0TSbTpqL3v>Jb8vXAUkWo?{7;X+DQ@%6>U$`}&+WDi! zYqzr|R-(za#ti00JYTXlV4v9SJOU)tlKhnu&w?`*qV;j(DQZaE@C%+02+Ceei)TEN z0D8Yi&7o#Y(7;*Tke*si02xgCDan+19`$R}vd)y6C{ppA`0gn?Qmf*6;^-vyA?qAL zo(p3#m15dq!z7L7dc22O5>4 z=^=)&u5pdt7@H~BK{=2pdKp$W(X`-c&j*`&{vYK=0~VnHHt z1MAsiFwoxnMw6s5b(GXbr^6v13y4LnE zGn`MDB~Xax2xrw`Orl+#m@l>J+rt8a$Ejsq#qp#(F&c{`sF8br-q0oa#3kFF`FwUcTfhBuI zUy+MmsiXsif9dS=&E7EJbvSe{BorKxko&?Hl^_=?CFM<8wj?|1eRRw-tVSFyX*1S} z#Wrtgp0jY_)D5?BGVb?=fX5~GM*XtH1uyr}q-I*C0m_SVbK?>lR}fz(GM}=+n_Jlj z2bW9Sr+s9gKrg{ilhje!IK-s*QkwjbtKrkgZvVS2tCy96PX2f2(FuAr=9oTpht!2f zPYqPZRI|IzRGXMieHHKx9fH5kCQssN&}Ar)frKiY-YldJe-*T^R-(gE|DfhvR7>8I z;&DM`?1(%9xW(o1g*%H1Vby}*t#SFsp^?xje#17oe5LOrk*1^b8<9;EZzjebYJy1y z1ZOn{8|le$@hgIFlHzLgr?ZF7^Vit2!kZBCa&%0o&Aex*2b?syeQGuZrc_O{qMcu; zXa0y>YtiFDol3)Z3LswU@(V6(C(D(mgw__4$VCp!bGHy)UZ?qOr)6IJ3Lh2RULeig zHPLdH?DCfDOHdZ^&yh7JK;p?qp&$JO`dP=b2+0n;(9Ag2*%pGAl}~TVkw4rO?Q}=+VkXqfJ^0rtLB~54&ee{Lz?GD-OFpNI$P#! zA=7_HkBaatA>r*lL-e8(aY9hv8T|d8&ZG~$+6(Zm(~bS`3jQ_%^564w+lx~#ATBpB zvH#If$SBwq6aLE|Y%1h9lY^h1f4h<${b>km8mK|U2Oayo=XL)r1Pp&Ibw)8MI6NLZ zoq^1&F7zH8%czGC;nKUFOXN_UmA5OY8M(umuEbQ z^A!PeL3^W75oXA>pm!NZcwrXAV0G7|*MxE;Pb})@|6JqAp8fq_)|Xn-jh?Q){bER+n%1r}aDGh{{`G{iR|5dYEOWCmP#i{RI5Y21N;M?yHO}pn`KY#8l{Q;T}e=kShwQF?PtX3p{{yt;5 z7c{J9?y`Qh(C!7Ki;iW^1>MgyKmYFSdm}J+eYQZQ@v7?fq{R(?t@LD3;vI(a}JK= zd!T)6Y^;rK8ynls#shqd0UmUaHxX<#8s^i`jScooc+gF@ZzsvdLXH-t+lteH+&hw zfpEWaYV-u~SxHXq(J~l*+@-4ox8zP-3wb@9sFY0p{)3E+46-|cls!xIcn(qz!XF|M zmjs|9barTm@cWk{&>t%|0~vN9^+oBw<>O&naZTCiYDI~^XEn^(mVcly*u z&M86qU1o4t%o*E+G@z?FuX`nY$Kof7xbC0S>LKqxuu7ZNc7CnsC`h+=c%7M}f71Lu z&i0Eq_wgNQS6&({!(^DK8pBLsp6#*5A^IPHDtD753 zX|%wmpa>mGd#I&y?whQwtmli36wm1)uCQ!d7xCRZ{U5#00rZI~7BEJva(qAD%dZ)J zwwzokZG%HU&;L7=a&css@eJqqwW?ttwo*M(RS*9W)pom*85kI>q58OfJR+qg!bvUNb6T8Ed4p`9jQYB84$ zJA2XR|K5=z3lpYt3+pueA9~@&!VUQ-o_yhcI06;Y7%!=yvN+^cwnOZD3i3QRbkJ-S zSje^z)K@m_*QRRq^z7GyD4>@NRkc{3=`SDL1vHMHQDw8DwIbBKpwk|hTc5PqU@-K5 zjOoGP`2hry|Hj7CY$$;>-wJ+4mCckP>&M?aPWmaxPsg6OyTxZN_qH~3*t^+Lm%?t_ zJh9r{h9v^1u(=zm)kK-0QzWKV!t?z$4n)UQkryC5p1Noi&F9!M!!m4$bPyMKJ znHAnr@=c>C)6`P4bbYB~I_}f-L3uYNP+fZzxfDSPJf3cydV_=pvB{>#WVP4A4pmOm z62IlD#i4^CO!1WZL6A|@9QGAuO1y(VTXgYaGEl|Ae$oI@b_>zN&WlaiPBKh{Y#5lm zwqo!eOz#=VkK|)7bN#yo$bfvnXb9sy1&j$d-NNhq!IPV`Cef@Hd_+0O&Xyz7KM_fp zrmd(#B{<9p+hxf?K~UJ|j;J#ZJA>D^o+#_8<)jA!)=-k$fo2YaeY=$DG}O zKF}MaC&vdQIFZAZ1m$N4wG*)1q;5?yanh zB9$8S#$yg9&FPep?~kt=|ClLwlk|#Y*ck;F2%tCO|D{5j1C)C)G0#|eA@~^N(U6*e zMg}!b-Uk>=YWCfh+M52~Zci+hejQPz>J0`dczI`(1z}yu>wT()ygbpMas5S_45RXD1dk~=AhETI@SE}V9T@+*d5J8hrdgBde z6&@aTgdmh~bCLQH{oh>DH;GYTXdFSG#!HsDE=|;GG!!-xkz*XS96ph{L-i`Loa*JN zBfQh`-YO_?^$5k5s&|^7DL4_Q3p@GFxx_^5T{~qHArZZ#uASE;w%aNbfM5+eoXZ(H z`?mIfEGH_5P29Sji4@wlZxxeljJ)q z4{EV1$f~3XIw4WxMvy?0!6fPsN#-|FyMZXzVxdk|c^XVoCi#>{+)drWJLjo_Q+)8g zV>wd(mf{f|=*zDx(lbu~4Wjm3qP))!yw#Jb={0F^9Br(#hK;wsgqxz5&uZQG`v$S^rBGEtwtWZ2{kV0Q8<| zS`GamGwQVE+S`O|R4oV<7g9cNWk66rNWexOt3FHY2ybJ0qb@_*m;%=DvhnRL- z4X5{%(w=wS{wutziIQK%znPY#%nlWDWuI^I9+VHAM_NLQs)pXC7{f19R&>xsjHn2I zMc9N{4OWJn;Yfxb#mQ7E)d6i@P|x?@@b4LNtpFb+j%_ZJswYRzb8s_Jge>5NZEvp! zSY|LAH=n`^YIpT~)I8rX_=)4PotE%r{*dCyF_hDBf@|d=n`VXnG=xtufx4lifJf6R zWaQB`bR>RZxKiSYhwE{v1e~{xSg{tG(2%fHa%$L3BY6!VH=U$IMp*_KlQL7}TdQDW z&`KIb4NzU)SNCCP5Y|EHX%SKv=0sqvSIGM?`usN^s@Sq*gQ{K7HS+kYQNHeqrl9-- zZEflMuo0j?C{_Q~FER4`v4eXdKZehg0d6IlDqbKNf!RX#BXlgDPo-H-iG=`N$ak*4 z$uSTMfz~7dt-MS)#vr&=#FsrFJ(L>x%30De_B2+dWP_bBJ8qfzmT<N^X{m2*fv@u@2e1cUdO~oDxM$GyWdFnlDE*WN-cQ5VeQ^S z9*iPZ+1`pH_5L>{lCl8Pf31TGjVg^|!1NllKEif{bth>)kjP^B50hHXM6@>6oLonL z@B@Zu!7HfT+k>uyf8(d&D&X)64LuZZ>P8Eo5$+onBW1vV$8r2~e@0{0^06Dau+ohJqTkorqJFFm zJSm>ZOxlMDFwM}t)it0GH9{=Y5QIm#_dyr9-d&B*DIk;LK!x~0Rw055*BbxqqZOo~ zE347hbJjI^23;^-7o-&)z^h9|)4q&fSlrK62pl>{QyO4lU_wRBYzQirMv*~IWn(ch zNS5c%=Uv!6h+w(Wd#1dU6fDcbzmHMF z9hYgwjyn*V1}lx;)3&sqJwV3ntQD667O(N~*(Vt#3}+)s5xCSQ;J&Ad^ewW<-2{AM+j@!Pd2n$dK?YM96*|lW*;Pb1-PWr2rj`*A|TTwk@A(eEw;=3J2(EC8|z5k2Q~9R znB%;K%t&?)1;qSGSmL0jE|Heu9kfz%B^5u}H9-k5#^( z4!7rR_FG-uiVx4vrlG~3sml(PXO4WVLs!={5S`^e@^d>``0Yi`|7dtDw-~gm!wYl7 zl~7+dnT>>z>}zx~2GCT0S{xY4=t&77W617aK_TfU-$@I}8CXN1kjUN&r60d^!Shz) z^6C<)QTcN@6}#}r6&#nXDo9LIX@u^q)e+Gn^~P2Jra!P?R`Lwk`r9Y;_VxSn}s1$-Nu zzH$%UcVE82hIsN61r1uIbS(FN>haD(BtYKgC^*+?*cRfcAlqX0Vo^o9OY%t^;HQT^ zCh`)aW5UaG{@8Zn)!{T34O4fCoH z(p{Ob#m25kU)ga2HJoOgaZii+XQni!o_L(IG^c1Pjl}6er0YN^g1&jn7EdAZw;cJh zi0#Rq)uJE{I0CUpRI&AUv8x}S{+=o{#CNJp_#KwX%kVN;+B%-^#Hc}voTDUdJG@AC)Ng7w1{|&t%SIx~Nn_WQe8IQX7=OWw5Tfpl;4DT- z4M}mA6sF0ICd*zY19)o?+pSs{2|<+u6+o9Jhh#dmXcOvlb%HS5R^>0IRH1RGtxZX` z#v)&`BF;URqP~Z~nXWn;fr{I8(1V}qj0OUaj2Z4Rq#`NTK7qiWhw~%wcn{m1u9GW? zmKDzTuYM1Ctezyux?(&i*7`gU)kE~H$z)IkV-JEBG&PnqmSyspLtdCB0->3(Yl+|X zAu-DD;ceh+L+Tf0oTZ~$kX~hSwl@gB)l_1}p9w~|mKwpSCsdz&6o~u#`(NZQI24LC z4HaKv_5S$jgr>6h=N2udhQMb8D&iP~cO9-~imWLLJ-e}!^^*Xv6r-VmCtI7g3MMZj z2Juj@(HiArW6M+*YQPmlYZJxyWqEUD|3K0#srA2N0RiGW11Vex1FSv*8TCME6zg|2 zw5J8MJe6%OKCSzE;X>=NJI<&!Xag~|K2MUA#yHi^MpeZsWOGPGt+)LUeRnj`Zw z%A1X`Xj>V|db18n8XaU6w#t3zd8{ClB=ZLBX(z^FGV5G@t{gp4m>4Ujpb?;IQ6dUV z>>fyWW)#GmDY1n)q_b6K{T}Maywc`Xe0Yeot4Na`HK2~@*Um5=ThkMpr1%VUwP>p} zehR+2)SZb=KM=uo=?^bD&cF|0LEnH~Gd7bTCTWf?45BhEP`u1xbNm|8X|}iorIY@B zeKxozL%0^wwSvo@6FLY!ZBW2$q#ZaE1S~PteaXCg^PO^-sbaMsz}C6I1X(jF+meKA z+x&{998(D=$;vT8cS)H8HT2zh&*%9!+!6`7nCGNzo@8bhIZlSG4prgWeneF zu?%JVe3TGF%v(Htkenql4Y6m3oY|hyH=xDp&Dd-UJz}MNFG#x#3zESPC1A@$k~FMT zJyNeC<|ennU=k6B@}_npi#3mo#g+?_)rJ!bbMCdKGeMLFBC1YnHY8E1HTj9RST$8PA1X*qbe%FMSMG=A9$VG!n>q)UTe^ARga(yzg(i(hYo0 zL3NUr)gm|vi`85hvW9hZd*L@F7_m&65T#5d?^05huub}@B7deNtpv4f^fb0C&7$y; z?q(Am^Vuy?EHLG%L1`Rwp^^X-ir?leJh?P(sN44@5A4`QDD75r%5VEVW$S)1G%h*e!cj-jwPr z+{>6gcTGRY1RC)6QcvXjbx878x}Ucd$&t=NUp>n7MN`bMvc0ph)%&UkL$_TUCM{ZZ z(XXizrV|ONn$!FXqDoe(S3J1zH;+^i)(v=BCn)5%|F%|poex4RzaHls_WHEOo|O4n zEUqCV(+aTpkEt(+mE41hRzccjOn_*0J@JyF^)iGkF(m;pf4XTm(e#QDvo!vCrNDzBScFMR#cZsM ziZw}EbBayQ=;ZZ7Sj@Dmz1(wuWsbnH^RfvGr!5=av;c0P7qs+oxZlR%cKm#0SF-=% z#<04Qd_GT^tG<-__HD1I+$6KOX~4JheALzpw(TOrwE7t> z-k$2ll1P(cZzcLK93SR|-V~}Ef+G=*W*xb~5iC}^Y$9pH94Lx>eU>D5_Xbhw>Q0LZ zw6IyZKY;N`q#7eK!XybUeEE9k-`w0}0)^URzrWoiow)#vVTPn(g7{*C1A~we390mX#+ohj3yI>Au)9@M+)c%HH*@8YLY_WiLdYjoR;U?G zDam!v9%@RJKMrMp2F;{=F8;R19J}6I3e6TXUbmIUUmulH6l)WN1IXOJo&IW^*X6FW z9*(05wmmM8me^A@pht|hCrVr93@Bmusyc4aS*FCf8V3B$oT@Ud&1FCGf<#PL_?&pu z0_%Z!3pV_5yN&2*-*a52%hYeAz{cY9{v-hEKd$fTKTgYb)agF@GpBjHuvU91!m4pG z*KruY&)6CaZw%C5uwUp4kn^E{(xjsn7qcyQq!h&QfuS+zwTXhcuh(B+o_7Do5bnqAYPOso zofvn5HWqL?iG(wjj!m(`n)>E0(ib?u2o#y845z}#VGvQ|-`sk>+AtN@tKqOM&hAt$ zquzsqW5~|sW_U=Jx*`aoz&e$OjAYwN+-(KT_K2vlOpTqCxSyKl54KS1GV(EygGTb?ti z5mntY7`<2n2FV3G?Wl{b?g(u5Nvk{WWCp#Bm$fY`FEp6a!w`&;39*!J*|a4@_I5huZN6%%F5=4xB@0KEdU!rzcv%`upxS}s$(u`>(PZ;;~FisKZ z>Vz5UE@7dHND>Xd!w^dX;ljDoezBL$Lyd|lb%2ul@kD}OH^ZoZ-EpfsMNdIS65L_0 z`rHg{m{8*cVAGmK0ct_x!&JI{Dha)~dws#$z=JHiFnc20VV0mT*OfS52c8;qa#)k@ z(y%I?VG>m*Q5UfntG*BzpC4_I^><60LbqGJnIOGl>xOTGF$=+!W|H22WszYx)?ctj zVeuh|L4xvl{GArMHwSn~PJx1oFcNGFXC9x|4GH?Vd`S3M77RP9GS(-QJ*@V)1m?G5 zBF31n1f0TXkPEU$4Bksn6>M$Ud%Iy?@#B1w%pH=+f(7ZccFWUl=P7`1zW}+zPNevc zV;=?Mb*0-{6Nb#M=R!*sslDc6h^Z5~hQfZ$rllW}G-{~=1KbUe)GDmT?~|0OZE#Zo zjfssP(;)JEm)T*l(#PB7ENtIR7&Apy`N!(>)ua4B5Dt3V>E8a|M{nSj*TwC5U9aSA*`Pf*Qo5y*YZ{SVs#Y}0fnnjfSQ^ME3 zz?`ay(vy{=HC|UsJ@@zVpUag;WhPff0gJJ1EruvAkP%N8o87OurwW-c%gMKs$l0vq z%i)K*&?lVJX;m1!VqggP3VS`Utxhub$I07T5S6TFS;CE6_NL&jA~8lrH3pqX!xy#f zJ42g+qpHeV=D2bLvUxl>p(ugjOKa(@hQWYmIeh5ILBNPP2?G_iw?OVSq|>Q!90AJr zU*$r~Bf0PdFzU;$BLAkm2peFKoHtu&wZS1{{M%!#>oevpmrs+q9dvsms-45K0FA2H zg*IWn2C3XcxyXu4-wqJq5xll&apY(q?hI*x?>;_TTR-F5Irhg*r4k_eqr*gn(rqU! zd<)2!(^FWm)y=5Kd*E6l_W~`TS zn63Vk z7V*R!7MS^=4DmOlednIY@RL3*6g4*}T_$bWnmfrQE>ueqdbB0C{ey`8L?)}W2ZYzy zdJ6P0{@Yfx@q@FmvmwyJSI&|(W6M%6=Y-)qPtpw61;cUQ^HOvFPVZ+ygRG+K#ykwL z#0>!>KlM_Itgagf%20H1WN z&BZU+Yd%nSaVm6Se#uLZ(>|Za<+unzoy*XT<=*EciYv1<(=|l*(_pePm5}sbX2b2z z!y?OW&7t8R4YXo})#VQDJzbSTz9qN>v|tkyIxY}Vtp9bkE|=e!EW`$Nf!P!C z>CxCO@y_TQ+W{+KxHLSgpGZ&%?>wqcSC@ag%f-aL9iIm6;E^F1ecS~>i5Co%D~bqq0SH#Kr_6LXv%G^^T`^cP!5kRwgj+QL7Wy`oA5_Y zDSR|WCFlj-x@g|1GXx&jDPalRAPIaM%xrwtxB`K8wb@YFwUYRhwl|d`$9>BxWpq&t{r0hUl@{A^6Wa>GP`kwiLP6yRkT7gqeX- zRTPUHjrHx9A7A7Dq-8^Z|5hCHguiO#@%=fN^`Y5X7LxLKtRuiDt%!mKTp;3mTn=Ry zw&a)%L2d7!{hqS3^}TJkjpYH*ir}LTb>|(|a#&mje3olX^lOIikM;iw+XLw%V3GS= zfZTQ#g}a!K;YEt@tpik$!;qK_AL565%sY{#tUGXTFwsA659_$L$#aoc@SzhX!eU(Z z%C#^?ltt(OYA-QqqwXw*@%CAJr@SK?C{=KO|A7kH`azXDo|l_(g?$#6KVx+pe(FW| zXoa~Y?rZ~%{BRAwIUHk!P`f)Z$#ZEdn?gg%57vZKfoVx_nb}gQb~#wP!p<$giRd%d zxr&PNi4G=4v+Wl;f=LIpxgO7gZq2ZpHY@P<%EC)nRgd#eWNvN2-8<)pGmPX+c}xZ)XZb|1~^0|MZK8Pd0WJ>-}dBag*W zKf*63SNMZ<*5aF7i2}L`q8YP?*&<0I-a)^FnV$PO{tUa3y*OO?w8mQNJ<<0+gF6nVJij)n zwz3qr-7r=(!O^B)qM*m7468Hq|` zFYIyyL^|BJxEAnIo}gIogl4*iPw}&IvN*p`(05a+#?-~w3{N7G=BrXsul@RetpZup zS8&A~-MMCMDu#bT3NtaVB!WdQh?~wB{f2E@+F3){gg}9)o8lRLXsT%)YPdL)wD&P| z8KGl4N&36|TR#*WHdXCIhA_Wxu04{)t^h@$V7%UWlfOw4n^f5e-PLRlsAT}Yr#dd{ z2<2kDLl3TnB_(BC9v;M}j2$FBg>PDuPlA*(fxZ~aYKBk1oU;@e^`W*K{Ui|rK{JTk z;4~P+f<^|pcSpcwCoBRsV)U%yVvn>#RHR#8C3jou*s)#yU6DePVy7JX?koa{oJ6@T+_C*)(O?7F0T#5k27gwMmCudrQBxmy$e`RUL1Un7PQX{@hp-ee!1eqdqs&mjDlYSf}*GnPm*-uTTQ1K++bON$M$&hOedvjH%rP&j@6rtL$#?F0kx-A{s$0F z&aRY}r?TYio+DW!WyW8cYs4!OZ38IBNqB;`hqXcw2!f~ldyS?Cg_dow3eph3XE?MQ z!P5sl9fFYVh8Qzimlh#4Dnt~!o1^3YSX~v@x{BcH#;m(HE%xr=+YG<( zz{jF*b}wZ|_SE9AfJN&{$})hT#Z^pwhbl9CYXa9*Lxjlz%p(&hE`F-(s6g zaG8w}O+?mqcH-@XC1Q9VGcEJ>MK&h@56+rNkva%mIjl5CVy!PZIK|zdtbYUuD(%s8~vK?Q$%LuCR5WNsV6*t5|B9in-yEGB{- zbsQ@!HpHIZqOAz*=?vM|L4ONnO4L%#hdd(b*`{LX?h^xjtgXYH!9?>oIUb5sR!vb5 z%t^w-Fffz!jZ1)I4I$`b4CFKC;WWVMUVnc8@`s?yLu3myOdse8lTJL5cG{vs6V;3! zmM#D{I#!Wf5OH;7uZj`vE;?9ENyu3AcrV%*mNt&L9T&ob&$$X{4P{yZd#0;1p95c^ zLA)d{rdlUSh`7;fC(c>%at$>@R%BaA$3ydoc#JizwHdKl$R)RZGjE z03Z`7wi;v5R6l7V1?)^A_H9-Sgl5M_H*Me&7NhXyj-nGAOiD;ucWu}GcDo%(g{!}-?yS== zD$xQn*2~bSJcjIKJ3Z3&y#*rt^l;mR(ka($Nah!yjKYWwOvVk;yGCp;tAGaFt!sc` zT(%>~iLx}Pch|{Z7%y!aUa4Vua-zAfFrz};u9JWyv9F>0Z61{^Z~rEr`QXQ)m+iFS zq0T8Tdz$QK3+BDTTQBX8{L3?;yS1&kM$-V+d`00~eQ@GudBLBtHrnuq^`MDUAbh45 zQk5=52yiOZu91xSVP5_qvKELeU&aep|LAozu;M8>UL|>HW%E&wTaH!D8atxF{ky{I z;Q{(-xLG;kN2yQ_)D#K2pZ3rHENoAZR7vGb=2B_@iJbV!&NtYxZ@@o$9#VzC4@VZEezqF>-)$v> z)xQcCwUUz(KZH|6WJEBGNmf!Ehx9ks?AwJ`-{DlN=bjfyvIX1f5}*H0(cFeBLeTz( zBA(rnmTxPB2l+Bq62?S?{WiXgzp`Qey}akIlpul6b#%7P5T{Qz%yEaI2BU`1N(ZBV zM_2mY?+e7wJ&lzf2Rt)GZCdi9<&v08kVhOvWk0jw^} zwd-Vo4y$4;^2Y?d0d(j-L}PjImZD>`a)p|Z>vtLOqU6lS#&cch!RL0KKoq6XAe9Qe zlPe~eZWQG2<5avcpCW|#`>#b) z!Ewa{REK6*7Z0F=`Z|bZQV>I#cCQkfsm4FzC0)BZo(Ok?@8sQ4sC-TW%Fb8xolxaf zK27`dAGrECZlbtNzwUh1VMzHZxjjBVr`rELIsmwts(-z~?!>j*PR<#twRb8c* zsS|kCs&xLH^+L?PjW&Y&{qNC-X~!_-)QQsRSH^yx2p)I1?zGM(aoMoB*4{pGs6HXT z;tKPorm5@^4X_zYj4r?6hR)5MkN_7hwl^=7ZtEe{wU75K3bGuzV-QZ)u@q(FMo{X? z8c}={@gusHjY%v>*qr_|NFVR1&}Kk|Z$#UdiwIp@lnLZ;)xq)YdHB=%)?yu-BlL`; z327kS@*a>YCRVrRU#blj3w^f@+rxYb&#I6jt6$vt>B?SucrZG?aDHBX`?ppH+^ofsFM*Fuzkm3@j!bLY36J7;2jvVBNsvW6hIYa?^Y;%9=At zNW40ZZ^O?=Bn(!4k^?OM_sqVjG6z z*k6`0GS=-1mkx|peC%Uv;GqUD)ELaEh%#zbUMtE(ywUA02cYz~=sR&6eoIgv^~Ko;S9MXC>Jq~m8pr*g5-AF^{zN-=HZczKb?y!I=OT?J`j7DGQ%eNY-NpT{C zaW)8xIrLihRR&`Azn?=-qr#^qwM=|ys4i7QlQxp%SEH}6R~9bUOh#JmHWtXGkl%d7 z#Al;6h)0N}Has}F%5>yl?N8DO-ylO;GRG1PGv{w&y3{Tm8m5OHFJwc^Eqv^oFF?o$ zx8wl1!lE@@c=bTVOR5I{Q#4cE@GH9jcS2Jyw)pVv@e?ik&#%eW$TLSFD{&*=XnBB% z^gKrAeIp+q?sY~#jD@+jj8w6>NFugzJ&Q&OU%=6Xs%uZQf|#Qlka)NrH!oW4!iW&- zAPgawv?i3A&99SAB2cx=!q-{&_BQnespvL|6n}V`TW@7Ynruu$Qa(_eL*P1&WvSq7 zY66~xbo!o$r5~@96axu|rp>wosOp3OAjpBz)A~)m&YRaYBG>}HrW*p*{$^{0f(-j6 z0;n$PMuyZQl+PuYL~6aH+Q!z~htDo`0k5tyyloJr7m9?twoQU5rcfAgOQq+Xb*=Px{d@l`_!-< z?;{!!Nk(bh?&Fc^SHF2p4*X}FI3uhsPft4K5Ms~CL_sDs#q0nU>9RH<&(6*w z$6X?C938bi*{K!hrlqvhqQoHPKoNf@bgE4P(+UNghXLgNR`Id|sxhJ2bo1y@r=|~G zN>wYnkG0nqhl64b&rp$&25fR?EzFHN&5)oiMX3}R6Lz&9shK{13bW@SJ7&w@OL(yRwrIp zsFzaxajKi#rUod-kd@Lyrj!~We2~O~qUJeOQf19G?nEZzEu@~A)YIwXwegOSrED@H z_@h#cKjax|y%A1`tIUL3x4s!@GUal;w<9R!alsOzI`)hqQO~-ncUv0hvr%a!idoAK(>$GC`60SE%z0|ON z@a^JEY8<$#uL_*Z@bzoo1?$QAPRBx@hRMyw>qsO4MchmCTWH?Bf87e=Vewv4Ei02# zOi9o$oTlhZ5A#-hui%4#SyIJrS{9Pq99Dc|oOlOWEg6(3iV>jb$o$w1Kg;g%R%Mr) z$yDpiqFSAkZMBq+@BMUn$pHIP3I{=Zw`KaTO)S~9u}M}JIU8%^>7TduH9g_ha(u7sP!!NelkIAnV;XNh^mU-uPQhVSO`kXSMi5$R6P zxyScl$pBX346*H~#R=C^FFpoxzL>~qI$lCC@pE>19p0Xb`Wt{Kk=&g8SxT3;#5$5c z-J=ruWThqv`y}qc#}tGnfnu&1!@=vNL8rPbWr~2B@D;BlVbPeE9b-h-W=G+CSqU*Z zktJ)f^ep#Xs#w4`21d^R)3i#IVtW2yrnulWxi)@}`;TeGL=QhNz09O*sJ6gS@9$AR*jIdu{p%w!Re zb`u#=WayD`oQ1t8^#O)0AaIkIgHNUI*79FA|~1itd~;B zq0_FSqbON64T&GN?DtZte5vbar^`P8WiOr?u8Jnk8%=lwXkl%>4VGRkL3}v0DCgOa zc0I05ivRTdtOT`(o(+hS*MW3UH9tL2H0f-gUE#q+u^u~aeaO@wa2SGeMmYTQ>Mua? z-H}vz)5ey775W(jJO9I#cPGkHD=7z89SNJA4t&k_nksI%qGxC8j?iI2qa1fug9W9mlRAWmyUFT0hLFC^Bgxae9VLd zivJSp7$)EZaOgz%} z2Ux14NGwWCCsc<3w`&p58v%JK%q*;B6NO_)p^JkQnrM?IaOz@DNlwcdds;TpsQK$? z^|wVnBIgoYf~!P@BKk8+1Wus};Lv|>F96y-TiPb>tKWT+YIKv#;uvNaCsSrvLt%Y< zDaiQI#~0s&Sb-*mdK1(4>HU~Keu)4}hc;0>Z)?s><7+;m7U|V_gF0A6R;&G>BBd4c^u&L-(a|EMR`}hElmK2tGHK!DCRiY9~QOmWlVRz=RviOM_Dlo zy21f`dVqCWvoWPXvZBHfG%C@NTRtUguhQVMsJF%@jy4O!-=GfFev{E8lwqJWA? zSBFD^Tn`p)4|7-`pqz%0_dAO=l}>YWh9Y^?gov<(V&VEO%1o`1rg{h>_Fb|xR%gLc z*4))whaf&~E_(t<5hq=S&#J}A=dwvFS6ZjTn#;st&$i6ss`&P@A9M-5RbgbtQkOOE z6+o7Do9Yay=fWrG(}Tew$+O0g>&*?vx@OkU3-(`H z%gZA!@-#+1bY&+2$#>N5iRMXuX{!?$W6HcGnQvfDwdZ@mfT}2yx=2+>$QzG8Lblg6RBmG(pid~HqasJle_C*Xd{<;g*!tGEk!wbnc9*uIrgJiop~*IB zCM7kErKNZK#J}Zn@k>Qt3rH{Ufb?wE6z9@pX1-Z9EQL~GIYPr}MDHMhl9&mypML*^ z2n^Gs4*fK=kBTW?iz|;Mz;|gmxi78EBakR%S%i2It`}{WgaMG_=sAHeGVV_(G7On}2xGUnY4Mlu;o zlrw_OFegv8OtogEOroD&WtF!9DK*%~VHI(HWg*qKR78nHF0tAAQ*oE!aO8r?2?5y_ zId~yq*q>84%22wam$XNBcV=GHK^&{65t3Ays;y|L8kHC}PY`I+&!`++94##z^I4pT z8eO)}2K|59T3V1MI_@CeLd8`}RJ8+X7?sH?vDdeEd|W(ktCO4#N#(uhSnRYUP{ID$ z+1X%R-n$;6ceFu~+=PIASAw=xq+;1VRS;-7 zeJ%HJ(Ca=*Rtk7yZ{Kk}PYCq*cbg}){K#gW@yrO_%GJ`Dw#7eQv+Z=7rTc$)I>+$1 z+BRIrw$;Wqnlx5pqp@wLv2EM7ZM$h~tFi69`tJSh|H(0P%*>iu&wXFlc`oX*b;+>r zhIt@;H?z#8YiVKv*izLaK#j`=aFY_FO zr)OK}GV=i*eAH)E_}dCBH+dwPN$qCf7L#!~{9o@*5aU=(@$bo?7e6ZHa7=MIdJocN zsTPT<(0AO7cj;hko=ZkHqyz|8f=KrUMMop8^vs#(TDZ8l zD8gdauU3YP_%%SNuLrYTi?L4q-6l#gRRpB!`>-yhb{o9EUNJg!oDJWs1y@X|GGI`*Og z*$B`5Iz0Gur!{#TITaOCo@RL=c9pvGoD7HB^93}aCyK4Q&--M{y2Hc_k>h?6J*-sS zlYdS!gf0?cRdLB@r3Q29=nRc7AIooY(&~SlAjYmc#h8V#SA~!vKZ0VC)N3FY2E33o zo=O%Tbd*`|- zblcx_OEceoHs5uyp(|{uA@jN7ooi~PV&8RQRv;DVeLKljXr~;=kX;Dbjqsp!aw4TbVKv;Ox?LJ9h3F&%-eB7 zN{+YT*LhKeO11m_q>D!cZ@+^cJgqXACjI5=J1?!umb``eQ;9C`{p{(h0=$nxIegK^gBvcJcE_s`ftoaj@QmG0>)^;dSGs^US{g8+ zVy_f0E^ThyCA|8qEO^=V-iON|R>Kf1)p=po&BO4lQE85O&p8+W+JE2*zNAnFfm8!I zI0^-4im8aC+!jI%j0>A_czd$99>F%10I|UF9>wId8~FZHH5C&C2snFl{v-@`fKNE- zae^xF0>1xo#*VC3g=vdm@Vxtscj7sR=3ITh|C*cy60MrW3pI5qh!Z4+omOG=Al=z6wnFv_ z?H=pngrn9xFBi{y_egk5fB09Y^D8Il)eQVq#?~9fjptqz$IXHw_}sK_epQ#%m#-s| zy@=)S;k20ZvvREd(Bo6Nmmn?omrb8q@Wdu*TX#9EowH8mtRiOcC|TK6rd zryWqy$g8G$Up)Z@gV$lp8b8NB*_=Ru_@$@W#_f`l|E15mWrO4$SCRU+5v@w4K!WvF z{c(cJR)hDuJKgpby8DM$kEh+tEM^5m7edtR>o7O#!b0*I1usB`d1hAwXf51&Q%yjnP6)S8&E`|ax&3qaK8s0ELddDW?M)opMF&{ z3zgFW$M!;$&<5n@RHr}kEX9Hg)(n;m;XCZMq{NH12B;N=-{WdUjsCtAX%a0r`aMYZ zjk)O^g?ZDJcGC@lC!?L!>EN|tkNd8Dsl8vYsZNOzQ*!e1dh#Y%_~SPW_|&&FE59PCE+tO9QqK@`1CEsCP)t#&?SJc(z1?)<&O+Vo=T#VsI zhoMAhgZu-Gd5vFVs^uV!n*E|)y$sPS2Rk8z#lr-Nu9w-ofRrUbqxtlxZgIG{&C#Sl z{@l9C7ldeHR|H;ZY><1cIax|%9+ry#1Z9DIBWEMLroVaCDzs8%T~W+*4QPLGaj(JF zL`ALajUbltWd#z){ATi0XsT14ko@*NU0Fo8v8Y?D+Po74-i@jC2g@FLyZ*=2DCd9} zSFjljK@UWfY2FIx5~Lg?k$aM&L9Yxc{w3u&hgSDRG;KBS(`ND||Gl*Ccv?J|_k9!A zEB4wSq_StH6v5!L|IGsCicME+>UMMa;PPjf)+*zdvMuO@IhBtusi4z@d>Hf*mw#rXSEwKvOgN)>i! zIgccVc9HBC==(sP!&R`F+Mu7w9VGIMqO%ftUi2dm{^2(RBHt3Dmg%kjeJT|%lNB%M z<`I;&M|e}%3CCjIKyrO4`bbdGZ(@Aj3~Tw@Dx1mQ^CV?6$-98h`B>}UolY4gZdmG+ zI<%q4lLu(GZ3q`$s(6z7h9RCfm|JKB-CP$(8 z?Y;vkEPeIc{t8B-sgz2sFtl^t)&z19TtTaYha3acrYINQ`*|f~{zoSt;*hkhx;c+6 zug~HP8-E9=gm)$UoDwDWSJrPr;i-??=SPvHh+RP;ylD}X$Nj0YDHb`nW`P$cUs(uW zhC|hcHAM|uXRkGP=-gqu4fbTd*g!&_8PXIFU6&xDbqoGphjL?{f-QSBcpr)PhL8A+}z z)%p%;{HDW@dSbGEK{$SnmA*&bw~_$ON;IEL=M{55T$WXR)IW|e)Hwf=)wgK95-ds? z2f;YFG+g|bMdeqr*VXinL7C@H5Oy)Ey15*!YHznfQJW{|GpGC6Q=Mt{&@3A5bnr06 z{9CJ>9vjE8hR{kFw%YGqMtL+{P-qY$Bjldh;vf4%rVJrrqafX2p%!IlW8geRF>tl! zfU*jr7|^s3H<|zWO|4XdxPS9wic~D7$%SCj2;by)CS(Q~P2sM4>6j4>{b$ZtF@C)` zqOD&yq(oj>EJo>LShme?!y-xC2JWoS&>7MDK}7bhYFa|{vYoM5@a9Nce1UgA=y!)P z7I^s;cg3`_W+9wpd@|1gM)KJpFcqF*ZjTtP4hH*~At{~bu?WAQkkuAjzAJP_*Nf4< z#0511s%Gda$71>ocKK!Hv5G4g@8a!(&rG{Q>+)^Rj4e0o^YuR-Hfr2O3NJvG@oKzR zw)11Lns~)kmF2dFP&{+!7~t7cud=+Zg6aCwQjq~gSO^v|A?hbs;_Q_hnov2S}Wk` zUtMKsc1rLa`>RKV^SYD;wv41>n=PMNoZ2B5Bk~mOCr;k1RKF5iLt{bJR4S6HP)C+{ zf^0kF@8$Y4z?M&`>UgC^LS=O{mEoq314nl7bcidYUUaAEp3m2w9>Yh5R4ouioKo1= zvsPLBoo+?a`aX;zfn+8CPSK?bR;e7-uaF;s?aiIkezNYU4{XkkvPN{Cd$%51)7wrmR zPf=)4;H}AEjLFdi?{`@@L!G_U!;)~Izu7bj<$tv8f6Ok^4+3npK-$~|W%33|%qWNB z%u}(>ZxYC1?nIZ!gNGy==u)f8_=Woh0tVg~Gwv`e>X9P2#ap-mD z$-!icEac%a&lP|j{!R-RLweDD3+D!Hb+uc2c(g}Onpp56_%M4HOu^t}45L*8jHpM8)B3d2y$<*tC?IB)p< zWvM6n$EKSL`W@@(k`9IQBrh*;^Gf32|84OGbAo9+`h0y-{d`7@Fe_s$Pq&KMbpJMq zlF$cD>03(bo%4>Qlr{fEqF0TIkHF6cRx=AaDO533d{yQ}?fPGXgfOjUO!>&wzAC^0 zj6TTVBQNAD&Hhd6KQ^V1?dugdnzcQC?O)5DPY)b4{`X_KA`Usj04)zugCtQ%aVkW{ z?hweOQev=S4JNMkkROqjK6K+M^ty0n!u*RKY#{Yi@Ei8)x#Lfz=&{tLPrsbhYuZuB z6C6ks`h!@#yzS#U9PTZmAGlV>uZV00JnWGlAxEQ(BpoF&A>u`1Mlh90ftKn9AuH}v zu@hg?NJ|ut7*u{YoDp-=L2R@QPUFT1l3^Ee0SXkm%A{+}x;MKIUsiM;xZtY}F!$Qn z*r>e+O^46(gMqv}J{iu(aUuCkwvgY)Emqb;ALnZ-K$n9o7L-A1=xfW&iqa$tbnx3| zKr2(NYIVq(nTOdX$|aQ&r%aNaBbJ*{RCxCl`ibh#!!S#zOvpq>m5xr{CWtlR>^ReJ zEHhDa;atflMT5u^d~Ud)eN8~=Jf8^fSQ?@P^eh;F)2`Se;{Kz*+S#%W5?ui|`EAa9 zMos6@Y>bu%=FKfO@>^?1#gt1zGm}PQ)}AW`X_r>`b7JftT?c|T@)72Xb-R0@y_$vm zHbUt0wt%f;&pg9nRJfFN(<{lwc87rRL(!eYFmk7?*$UoU_z4a89R0`6YUrjkG+@$xWmND)Ot6Z<-`7e%A%1g!VsMxLQ< zA59+n&Lk4|81ICv5mlF}w+S;0MUq&GLL`XpnSz)3DGjOFGdx>o-opR^#pfE1t0HXr zJ}F0`t5jfJqKE5?vR_BD+H-1e;OeBpuMLeM%zG)6;gP&!gk`vb-HVM5&^SH)QO-^H zeaJen&Rs4pkZdry5jmq>8-Wt8unmir#woa(#EBaM&;wiFGLgm98$R}Vqv3aF?}e%P z*=vH(hE#{jlMBXznikbkU%$*8r$i_kql$D0Tr=`@W2LAy9A1|CRop~ma5@o(lC;QK z@HquNwkeHWip+QiMkp1@(>OvhGzorE@L@RH})j<&^z8>sszj-|G#A|eY zWgpsU`Rn!HjkQPQ07E4I%8D0;#zAk3*V2UAEJtPq3-3y@gXGLW%Eu~%r~2^OYAubv?+EwdBb<1W-~$covvs^35gXdG ztbY<2mP^IU6e?fWPt-&c(h)d9)o`AYj;5FAuWUaidq9-}lAhy2z79Ja&*eOkVY#Sk z*+W9@$9Q`(ip$U>P?WHW^Z$Vwz$7-CqdpALmCAqBu6=h_YZ#jr04y zf;b?*;Q|c9rfo%G^1gVt3Hz1fu>Qc}ld|hGwGkrSWitE?UM1QZ@`?npv)LRc5!?gH zoap`Zjb~uE*RF|P!L~=I#YVd>7Cg#0td%?lO8DgZ8Z@m3K*P>}*4hlI;*2kQini*r z>8l=6hQV9p2rU@)B{|9!6IZz0o$z943CPova)6bV!c?9(Das1TBR0^qq6aQ8lyJ2O zrJ8t1gu3j%E6n+QRI;~G%xB7fLlZKo>|ssiYM^SV_=!f;YZL2qP`qXXF4AjJtlqBk zlZIO1I5V!*=KUu&gU;g2jIu{a*utBvRR^~OLJXyyrS{t zhe|dMV~G5CdPH%ZnCe7nBvjVeW*X9IW0-yE71 zX})r{9-ebVR@CZ@0@&Vf&u5YH>G?Tcj>;(s_{Ia{ij0K z^?Jr+gT+B<)Y#_xCx`{j9mlL}zY`6qoov8$NDX?}|Io;1!ez4- zT%VtyLW!KC8I}{bD!c2&j~iHNFcHukU+DU!Q>@BzOta8x=9E{v4A0RPT03>rhMTTS zBY|V`yUq&DGdNpsX_k*zSz-n|wNS@gVXj>P3{yv-l&{Q7_6H8GFP_^m&FRt^EJ^;D zaqu;RUC?kc5^DlWKcegJ7+U|~;bcEQ2WL4wKA-JgW~LQr^XA;maq$_w zXe^a-)Cmf&c|Sd#MOJF|Rp={D$}3qT!|%a*0@K#w{agdnM-glAS`xI>Y?7SzX(*2i z?@XMA*GpSx1J(ZGk<7v1^+}{NFso?Dj?JDc_Vcz>j7HL!2FL$2G!PBgjgpCrRv;(* zw?j%tXi3goZxo&g&=_Y9ogeeaXT?AousK$cFiPMng1QCOeMO5n*3{^)5!Tkeab<{;e#IgFbs|;{Yk{oV z*hH++!W<<^zR}G6^Fo-y+f0OIayWg_vrO`mgvuq;tUHoqp8`t8tNqZU8jK@MBk#a@ zUtvz#8gW7+(gTSm>7iJZGYGUMT3HpSO$cO%Km~?xF9*tP`!0k&uW2QU-ecE!Q_j37 zXl|pmo(X$HlIz!r?Z+jka6J(E)99!Zg=jKp?@WPUYZ$(?LR$fPg{;gWr9+lp*>wF` zBdnTSbCYS3>I};Ow4lAcoxuDZ%|g%+?pTE4{>EE=ygqVaC5SMo=;y~wgRCp>jjFX9 zeDEeAr;hh@R;Thie%XS4PxvVBOix&$a&{`{!pTXgue>!m90>WCbeZ191vx zqBn7~?7c8w!~%Klq#5`_San(W9=IH)^rqAF6ncUZGC4HApBy4Rt|Z~6Xy-KIJ7#}( z&F{&}Td2YS<7Wa_6O`(2B#<~%kU~6&-;XC3wg^w~mN+2u16AEt)safjAH*8wZCcK{8%!cvl!oM#V6MHvu=VOMyH_8gWxuXG=N_d$ z*9qDVL*}FSR;N*=gA+Ooa7EahX61Y(1#AeXZ3;>9p_j%_OBEC%QZt3lIjPQpotS_a zs=FrqH%f&Z*#T;mU5mZ3{n%1^g$9ygGf}}K$k3?{fI8h`OBlsgmkEj+A-S`!K~3P6 z4l&fqt^T7!E_Bp{6*XNVO57J;XX*AdHjEw3O$Dc9d(9N${?B!Z1$m7kf41(#oOK%W z-hR!3CW#z5!US`r(P#QU+rrzS43;f!KR^&`vf_a#m zbev>mI82neFxO5_uego+vi%)63;=Dp-$fO8n#IjcE`h~6zFhLodNEG? zD6=uLZk;c8@gHs&py)rsFqNKfF-mKWyW@pJ<^a~TR^)cUnY$wIf_hOM7 zeyiG3oGD{#UO7SSlRVs(498D}%$ibGx51I1mFA9%CtxQ{>gsnu9s_Etf6p7oRlsP!w0{$N#7I?jwjKKkM1x&#kFZ1VnDijrdIsgYR@E|9>oQnqBa#-#WX>#xRRS z5mrvriJKQ|G$sCoL>R8k|3msVV1HR>naG|3PFRN{9crD}x)Oi3BDkG1!A~!}e8TKys(&3-NcOE`7lKP?uzJP zmCr1$vS7+wsIqH(r7Q=_2>Lj2MN+6Foki&GrT+cdbQkho-z`s-TyH5+!WSDh{F*Ob zdyotX(1oIZOxx(DCZlfpZoxf6h^#6VzsrPyKJuV~R4R4}BdfLSr1hfHO?Sv715o3Iq(mF9`tpuuT8*t1p#+4Vfof^v5y?O4 zurkuqublPta_j0)3GIsV^77O;Ef?+fiIXJrYKU@stOIqcUrr!59y)d2yxKTC0qKi&stVM?b*QSMp zeVuG3D~ikX8`H7cGP2v4L|HvI{5#CdE|n}BzJhm1iJI!Xo>7B3F2_K9{__&OKfd_b z?K96xzDj(kqm(EV&{lYAf8}9H7o0wySv*p;5@fFqE%IhAmdjw-MPBtuAPv;-XGZIE z2JPs#)Z{;9|*B!SI0?jakDM z6d-tDq$#0Fkfe-_g2aOf*=HfGqlSZL^9?NYQ~Q~PwvZwdV5Y}H1$ZrmXy!cs1Sh~m zt>ln#kPy1|6LmwI-AR>-j?5?KuY^wIb#Dk2h+ou*&D%qjRTdqz{Qfl+6U;-LK`L z^%sl~l+9vciS!iW3_V+DCxqPR@q?aed4hSivbC+z5j?d!ZW862`86u432f;oxBM~e zTNf6J?SH)N z=YdUNsHe)9$)Q@|)CRRgD^CQIhYNGR9e})BqlFpXKsxFuCx;x&V3!k)w0%jH?hS%? zBNvPbDYI&4_6V(mFvE_7U3EsWn~PKiwx_!fs>-%UL5x{KjCx{f0f#$ThU``?iu3pF5KorOPbNq&)g@ zh1=qF;g~b9wKozYC2N%3L=d(5cra*gR={WTqXeADM$Cm>Ua{ZpYe7~ zF9iZ|7YtFI8LZ zK&}qpLbd}Ou0@=%HL7Z)5~{vj-q)XAU?mVByp6*%GqR>lJHFhR`3|rWHr@O2 zQt~0AZ#M@MGtj=lPJY|J*$9;Ej33TcDpab3aLsY{rOI@%0{TW_kUw&}jsIkFrY^-0 zaQ263WjdxhOL`9;#?L-C{$RW>)t#-PHo#3t^?TuXgRYkAa-h~v3%-0#s=rzC81`^QviRx-Ldk{l#8v)lzHp z=PvDBM(S|NDb}sU2sR47b&De);j^-LfWKyXEASA?ol&E1p5{O!A$e)b>wc)>%bWlr zgbn03y)fU;S=bP#$Xrq(pa=W`%Gl8TG&Hs0y!1sZ=IhHG|GSU(`{{`3@6>S0CzK0N zVDhdvj)~u-O1;PUA(6tpKjY{I>EZwC$EMR9B5Sc6eF|K#9sOJmSJC-N z#iH>n6)l~y$OzVx?`d}kR%L6F5R1MEYblh^+M-NN_f3Cy7xzSw7LEDOaks6C?Jkn5 zSoJxW`NME)$PnankB_#JE9@|>T8HB#RjtMOR5U@(tBF>B{3|T7P~_17_Zm8|kDxHu zXzS$gXJS5UjmQRy#n4YCr2J0={p+0XjDe2ND1;|!!$jYf8de#8R6xQYtuU0%iIUG> z$F)sI<$PSJeVfx5>M`&Sq52mjKE_F3GNLN+ANXy|{f|$d?~4Tw|BE41$IrErbNjHJo-7->hI$B$zvn1B)=i z1*;EdxZ$b2R3eJ(i(9d3a9&~qo80wzCp4f(pC>5?zRI8HrxdFKBdGY^)xKlSG=azD zhMRHhVIg?-o<1?aWIfoizF;m99QaXz|2t)Uu3=Z4FKUt&08MfVR z)eYcM^L~n;>XYo>@ZxC23`u&;#_t)@ybsd@ zNkTJ>sYpVubYpaEpLRMdp@4PZ^7q*?gymWr|su?j~75B z1#*vGot8lIPC(5pmcw@QZR+!F3P?Sv9{x%HDxLGP^|9vD@i_7*sPJ(z9QC;2qFbhw zoDSFYf<+pHtpG#C9M=Gu5o1>RZI#U<9~Izsh5qe${+ltg8-nzuKhqu{b1QaFCtCL^ znq6eJQSnKJljIrzY)OXJZK2YbSRhi?iE@kX@X-t2Baod!r`70wZ?PX0Dgk!?Fs~#>yy8US_L$`Yq8~AI1NfrW6<2Cnt7Im-c)Mh|NCBsb zC!m;+LQ9nY+PYtbv+yqsC|-Y*IKn;F(`xUlA#27X5m)$H&c9=cVkE~hDbTA3oeClk zMiQ6MvgPfu5`F-HGglj};T_|f~}CHywCdysR^;@^Y~8dPH*|#c)1YIY0QShfGbR7enI#1 zUU%;W8-UHp`Mk^_zwLT6AejjWv&Z@?qn27@`#hNXK)Hg|3unCfd`x|U5|M0oms<2XUz0%Faawqt@p zNQlLt6?z70s(|&I1o+Xo7>=?P681W8S~5@pITKooDA{yBrN_W+0nGwk@!VjY;t4=j z^C3F;XWZk^@_s(Z%F1d*bbdN(m;&=@SP{iwm;X99istK)tA++#AKjyc$T~{*`f!8& zA`y7_8Mln+2wSS1Jul{%+}V%)n@8Xh>sh8Dn+~x z;KcfMxsLQr(3~iz86D_zCtDegJ4D|d7B@D7Yw5YF@z@G#8s0K`Uq@)KHG}&$cQ(L6 zv@vJ+l}`o#opnTShGe)%mO3`-hk1*t>2klj%G2g<*8Md$^u@Xg`hgQMtF=kdy$L@T3#1y9x|Zf24Osv- zu0q@6@%<`pWWG>rY$Za&US&z*2ow{Qe zb_6HERRPP<)Fdwmxd_r9lZUuNx9Kt^!+YtSNyBCwg1%Y-LW$AbUVf`Z`FC9l_;R%< ze!u)NNoZAoQNc55K_2lryWi@9SPoNUqpi>D8cz7C(F8Lc;;qHEC^4oVJ$FTnpwM}% z6_}CE1du25ww`<9km17S zDMus(ieR(XQt(}EZvot2q;?1rA$`&Y5Uqjkmo_a_gd`6N=7^Jg?LW%oI)C8iZ+1In z=ZOyDzkpU-mPNa|28u)4_6t9kfVf7Y`J6Y9q!b(g5nkVm;on@_@)?lfu-~-FV;{6|~bn7Ev>-mpMW+H@^ zog>y+p$k`;htUYV0zL<6h?ykaj(Mk0f}fsZi?1_CE;=OYc)A#)#=0CYS{oBfWCkt) zQUcPKV4OZVD)8d^$Q{cdIs03j4-$K65qXyB7|l!Qw);iRxr`zexG@9w0yzc?&GVM% z$=$k4e#JQ{LEF88HFPNO0&D{utwM7W81Cy~*k@n?d{Ev89MKf5{A@vggGIa7dql_il5&@@IPiqh zbC7~|%^!0dl*{+ag``~cdclGGx)!A}!_gpAw3Mvox!j&dvAgX&u>EtJ@P)lgI*y3B zQ8bVOpTMR&RJYIia55YEuLp2;@q}F24+adWrUqbZO_ta%Aiu-7f1ULrfQ|-_lcz}! z43B<*Sn1XoK%zmfh$+&lRu4jxCCO6iOB84`>yBzWPJZ)Ml~xc(kq}%$vI=@fsp;)t z0?)%1yajIxR}Nk-Y2w(A45Jp^d?Na@x|nl~N*W0>+Er}!r7JMp7(o%;4p)=NTvOu_ zy8hRaw#)lJyi}Rhxz~Q2ShLLr4KMA~_TnZo_%_~MqzQsV9=i_oPrQj*Ba1j2FxnUb zKDtK)2&evgb7piJ-{^H}Q=HruCPiiq64HjYY(Oj%#r-9y9V-&*UY=z2l_oFI7XdRJT<6%ji$?t-P zi8xI}W;fu~&7KC@LC37^#N5g5Ma4)<$Wyb^J5NmFdI2x1m!E=Hf_;|l?jAAD&YEFl z80fnQ?7xqCHD0Nomk{Qk!M=G%NfL>AM5t1JpN}99X52vCXK(C{?Udy7wy%>5s*IK= z*l385n8QK)LxWH!9z@+(q)dW{G5_n_2<+r69zKJTW_UCue0|^?s{6DJs#t%kq7`$1 z1*mLM(WT%&d7|PZuR0s&ZpI2JSw{R$O7Kk{@$Fws#GjDFTx!gMGYMx=zRXVN)T4~; z@Q!O=1v}#^Ys_nw2Y#9*C?Vl;2n_;f`ggNTN*KR^raYJ_*|gt@N9(EjHD900TrOZ{ z+js7E4GY1ZCcuF`k03ZhI)TfNE6HU#!En2=MZ*}PNmwSWvP3)>Ji&j_+pL!s<(Xa^ z!+DP6G9H#$irXk^NJ-lM%Yh_<%d)`J_8bd3YEPM+&zc5zccge9*&_d~vR|+G_T;wH-W_ z>jxTndil_P9960$+IN+ECgyVEyT`KcZ_NocKTkbzKc(V3^)eUl%vfBY27u%fdLqpdc0H&|hb-P^53F zGr75119$;)Ab2{+hv5hlf1U%|w5|cJ_%I9mGYBIjE`jA0aXk4_#VN`dYnfu{5LZDF ze7R~cKhI4=G0qBWS#kIG(wfeuS;BMJp^;-hqJF=s6c5P_3a@-?DX3G}z^dN)FD%NP zC$NJj4RC`>_j5Opa%%{@Rfu17gFp1Oo^HFw?b3@GQWe(PUKFAYD73HdR&XOD4NIAL zm4%BG(@rYwSWYr(9%hvJX=%5}n7I~K`}v-uOawhc_n*c9_1>6f(W!;A({Taj`xSz9 z`+=hjobzU^;ViDq30-!*V|RG^Y&j}gq@8X+G+(u{0Lz(rbCbFvn!e?uW>g-D)wE<$ zp}Ogj6|Jsd5?G%CtGtHn-Ftcq3mDQuO{VUG0ygIAN@H^J#n@_|kfr%Ex~kBAr+~>{ zC7IiV0RyZ_lf6g^Pzs$#V(hOl5tgg*qE`)Xwek%8N+Cm3Y zp~nz?)R4UvFvX`6-Y_o zP1}0);1?_YoU@*WS8n!)eJ2@~ab`I)8Z}niNQsLDTjF6;8p`4Gdb2ngA<3oxj zm!@iv)PMZn3S&B5`ZX1&@+Xrh*Xfz(7p6n;wm%to(Ka?L76e(?6J`G`Fw8Qeg1P4V z27<-sbBL2+lWudf?^j$93i4XqBh*e({w*K!Hj_8?BF%GuU5qyb{h+Ih>^Jo9``;|! zXKO>FJk{tE&W??D*S{}da$wW)BcFy{SmeO~C6ZJuI#kU7w*unCNG|wbA5_ELqXn4c z|F;N1)3o00g`uVmd+Z!>;K~O`#|@g$kdaY!h6%vK(#~|?W+4CSM zcTf%baa7p#FhTl7gVmE! zKds-99(B6`_vtO%=gGIGH8kgG0q5A4Zau(9r)>~_pBS4&d{u=yXMzmfrYu#4{2(Cv z^gD|IM=v7byxZW{4Q)RQV^49iUQjF6S_IuE%s1hB>8Q^)Np)B6aS0s0n}A426CyfL z@(Q5u&m%tRXe~?@=hK4bYWyb5PKRj$Rdeg<IAS44t zMW->zc9uFB^Alkq_oXw&%<2FbHT~l$N}F73V+ZiJFVC1t+YtnZz>MZa_gNvZlHi^! zX94~duRZ*&eV`7sN-X)0-2S1L`0)FUj(!+8J{d*qlMRQ*aFvLd8wnVYT^s|TQn#cjU}VI$0S z0`k@E=rWcybF}A*vq%Fs>~|{j9x!y+XtGqr?1;i49VVICFm6{GVlhd(qk)X9r~ytH zfb)SuVfShegyP1*WO&Q#^}*|PZHv$ItkqkkK2Lr+VLpCLv)k&p2Cx2x%xedhWnuS9Rfle*iND;Rlr( zosIQ%ghB=k2cppv1W}_}aZgk<79J+6tL+%i{TIMg{XX?^Hibm+y;sTNhTM&=&3u(} z2vLMrD3lHhKAPA?n9T(LUrd@G5NiN8pq^)SBPvxolL-!?_BW#h5<6ljU)6_Kg2n)? z(S5uW!%C;|L|*_j?Ey>ccLC3jw`bd~dn_9CAz?R1ulG^@6In&qp?Wu-tB3Qo7VEX( zRS;k=>Dxw!H;RVSyScAV+f4)s5lWP?W9So;#VB8dk?9 z8x0cj^Ty+O5MnW4eOL@VIGZSh){3OkoBn*u`Md>0o+Ahd4}mpL5jlAH_{{Ft*x(+( zw6o`Zt!MJqSPbI=V-)dj3b^YAh!Wz6!Y}^t3`ghZL(n(s0w8=u-#{cOvZB70kLn)4 zwEWJ_&b~igV$|(^i{jXP+ClaS{g31;pko9DGn;G15~DIG$De_kp3%dST-enFLlFuFv_f>t&JjpmB=UATmJ z0do~(Dd>a)Vv{Fd)xw3b6J>i4xN9P02~u0IwINcT_ml*39Y409^iO$hnmF(E;U!{0 zJ56>j$-sI$jxS4{5Q~N9+kz@Ag*7$EtubQjY8hW9IEfOz+9kkJCP}}w*uH%-J=9(e z`p%nLqJuFxt*xzr!cD_&|J69gfOp$+e06Upm}u1-s{e9nJGAw8_zdXt3(7in@lIef zzAWi}up}b1J_9{mpBqXaFzvqaq>7J^%g+zjrLccTa$q+99?|mzzXbkyuGMU$PLbrc zdp!~nB*c|Ox9@n_earq8!mAso2K0`{4e)wA@Z3!cuen^b0%L<}wU)0qb+%jC8yzlN zcJDwQsmAC16zF8$L1I_-cXU6#6M|SukNkBaIYA|ZTt7Agggo-lm#Zx`9W9^fr+g&T zo#rXD4zRj3AQq0v^ppq{!{Zr;A&RDw8(@l1CxYN-%M`H+ZkFS$gxAT*!%%dG3Ol(E zsnr60x^4$aM*YKZxy%W{)t;N{oTY)l#f}<@!%CnijIR$1_7E-+9TJ=WG9|y_ z{rYx01vo>B3ktx?oEw|}HKXXGWTcYm`u0F{sXTM5{T>Rb*X)2ExVwt*VhF;n@3WDbnb54_Mk7(NkfAq3k}B{2yIaYTr|a7-cx;Oxr#a#Wz^ z1m5Qd_RmWT*o5+gLx9}sB?wAhD8vsT$Y($oGL^;c0}vB7x_Esfp})FRTkDr} zyWH$jmNZz9!lY#IerU)M@&0(Q{lrRpdm7>QKFo6Adwp{hzZ%p1gentcgj;TsLAQN7 z?Rlrz{O)qWvmWL!w%}q3&!T?$^%oD473569h!*Xa>(3Y6PxznqKy70S@KyOdtNO@j z&=fYexPQG0J&xV95R$Bs<`MS~Q=nk(sMX%_?MaTUA2teIz$DilxE|y~S`j(^;n7<|7u|pn_%)0ko|{0{9wko@ zCPMis;By!*2aA9eV70(Zm6Fo#yyj1K{6WFHjmDUWCC5NxZZ-3&&&1Lu7c5$<0QEKH zycHV!<059mZG{}0QN0l*pfeBjO8eyeT$b!i)3zHG9KR-3P``e~P%QfG?U4T!SmXH{ z`Fz~w5U%$i+v%-IkRX{?vPAz(SrfQgTwDbD{C2m0WnB0CA#bZYZzNl^PL8?kfziCs z%F|Op445U^U$Bk0+(bq_lDJ_X{aryOrKa_2WNx08%*nzVw`1*X>J;aru%6eA%lzut zfzOYv&sX4>okPgukVpgnEP%L&Mv3fYg^V`vMwT~?OfXlUNBqrmjcFr(Ud*u^{1k%c zasRgC*9F87pZ(i+j=yuI;&WIQ2zWSZQ?XAU@2?7aCME*aYgMqwr$(CZL2XG z+jg3yVPo5BY_qY`u(2AWadJ<-b-y3?&Y#K3nl)=?_C9C7@AEzwq6q%Jn5VJfqV8(O z#JqVaxLBqA%X}eVdn%om&?YZ9yE+NoU^J;>Xwh2TiG3N-OVZPmdkr;0rDQ)vsvXDK zj2GMdrZb$jP(lx@ZrfH3R_F>Y1)* z5Tw#nqrOnd`J)dBAwU4~3v?KL9>Vb9s_6jx;D4_1=-jc4sov@-5^Xxjh*6qtG?SDrJ^FEA&Np4 z>mHy#4;Mv<|KqW4pRX|*?tPdxfBhmuQHM1;N0mY%c09>%Dvk_&~n8U;p#&Yb`;iJ+l2FBah+V zLLx#;vIrb($Xa~vYi`vb`I4j&KU|h|A*?R73t$)=4$1HAgS4cTx!g#Su*UR}w1XP^ z#*-Uzqhx3d^(kr&r?N2%<51QXa-*)e#HcU&@r?jq7ocpPRiNIFHUVYKyJHkr%SLvx z^pm(gi3ISXU2q8{z0-@x7`c)MPG{JVl`BM#l=d~e9ZCV60dtQ)JgtbZa_|%F|G4jcU+MOJaD_#<#g6^}Lg#i20Ot_E zN`wER^YT6TUBK|$V$VbOC1{*>jqZJC?@Q-#X%<&Eyc zz2!8B$X+%BGEYi-WqYM?Ox*jtR3`+~CX2#k{?^Hk4v=B1O8)8cLlqsQX%jM_n%8N8 zPibvnLm&TIdt*7hjCI|zaU>504wvzNkC7FWjWiG*fb~n**Xh)o0`Op%@w7dk57HMp zepqd^JDeR$3YpV$x;h&$rbdZC!%1`*&=}0XIT0)AVgyR&_gylMGaBrszBXcYhO_MS z9b=o&_f4(Bnddml)JFP|J8Sh*pP*$M!8vE1Crf6r@jKcaqnEW6V~PS>RDWGwtEeu5 zTbyVSSu1cPLP0JHNS{5I6FMkp%7h*jEKlxLx7r`_#=WQK@*K(ZrpzFkO-b{LWH||N z7Um!#vvYG$R6=MhO`ZZ4eJYE?-@-i%5ct;M$H85Q7c`9$l9e^Rb}hGh8+#IVIe8JKXzvT4bcNb-M%rqy zfd85}AcFMx{r(-O?%@sS#=}=(lnHp8}n>HpAeLt|G!mBXJk98pTh-iVd@Cce3F8`O?502UI5z4m`ImlQ1NCt+Or|wVpQs6Go6PdNMrgH-cn{@{Ul8~Q zN?!_5+xYlst5YYW*##^oy9p5(F$LCw3y*1o8+WY(nMxKdkDhT$$vJ$xq@aAWh`Xa6 z8aAxQyeJtA)bk7Iltr_oBJ;nKmf=mf;#Pgex%pvQXkq7rg7ri^v{yRMobo8Gu&sWw z4b4f!;JbBASA(u@PX?g1eU#hO^L0S#3Q#d7EB!adq^h zy4$V)VgW*9KVhJBv`6m2iot*AJ9lfa#Wp~Y^{o*%!hlTt%+cTr{hoVS(ukXp!Pok4 z-W7g(OjgDgYOH$BNkZIVY8S0XE0b@eT?t~Pf9Td*0A3FZgPFxIMb$=Q5v1H7Y#j2+ zwt&F~^g{ISV?zKK263J9(!{Kk74u@uObdz&K9j@tky=UE_?=|XGsNhquvG0&)?1PD zI7z7>$cT8jA*0FYF=9BSdl+t4^c=~qw?G9pb6e&j&Jnh+75Gl=r~8$ND)QRY3?;)~ z(3ry71(QYkHnTYvaZJ*El;(aEW!NYWvBa`J_-nRemPbN!q*0@5B9bI&%6|D_j|nG= z1Dn?Yf5RrvSZi%E3f&=HT9}cZsA$^PT?OYw4}xN7>O0n#hzo ziH&L>We&xm90c+v$XHSPT&kPl=yzOIx1V7CUU=UXifest=#0!xAKK}eRa&E*Xh|r> zs8VQ8uD6WsprpNP=wnJN8j&Gk5W<&o3`rCYN$R z3R(SwlK3{53RVREw|=`0m@**TFp|gUm+$vxEMaF%maA}sla<8~f-J>?)L$0YWUgk& zCQ0rwec|A@O=A!k*lZ;)t)OOP<@xOpdXox?5|YAC7ZMNSoN<~aVqbD)VK3jbG>3M4 z8suA^Hy7ux@TIqq!Ji#uNJj}^vN}4Og9o2Z{Dz5$HUq_M&xW+HFy$;te$1Y?V%qE4 z9bLX>l|^XVqj#@sY#LU$G@(vGvDD;=_~j9su$M3e%PBi6Q41c0hz%u6f}%n_rii{# zK0?X+@NSFzr4oY^VU92wU-mjJ4t)||d8VY{M~_7W-;pZK?qoiM!ndex>OwBTY!0h9 zQSIqcQL^H&{Y?ewqio0Go;EGMru(_Xpc51w5V5M}a0@~}at9lfj$Y4;I zX0eH(?9PbG8o2DDib=6f3taY|YdA96MuhV*FMp386_BA(fhkqcqCE$>Q6mQXc(MA5 zQJ`SY=cpHJJS7E45#cydtQdfOzD8xXl#n?+f%=Xt;*^iZ!cqI7qom%JTCxm75!#p; zX`!IjO6-u54pV_`Yi%9ONzg28Ih_q0!D{C+*fi=HqB87~4Cu^jyqTfFZs|-$fVcMu z9Un#RGNThLn)1F`Qay`)yY5|gyX(AFOhraJ_3JBvlaq10zwWMIq<3f6-=(GV|Mi0sf#q0h9GGCw zG+0a^5%TTRom0EROC9%6n`U^;t?4u%S2DBiESa{kZjZRoq1{6wXv|s?_Iw#q>mBl) zoI#%h5B=LyiL7<5imDt|pWUINH;kM;c8@Dlzewrc8LoM5ET`HDlz-vy*tK68I~p5r z+mCYpUR-Di@daqEn5_mJN8nCKz^4(C-9gM&O8|puYnaX7_s>y!F94L9UgFSKf*oh_ z<*gkM1@Y(W{A74ZlqTM6b?oJ9)NIe6I4;*5y$A5h7zu;YI~ag@zkqSB2vc4{Ow<|_ zzblF}L8I0x7fh5B!FO0!R(3R&Nd5@tnxP`}uRt$da%S{5<5>*sc@kfQ2}(qD>|f#3 z1=JCcx%U-_KXc#{!)(!u=gMWs=!?;=f-7_CIS<*ae^4DPx3LVN7UrnYqGwx;9KWNL zk*cnZ&FFXib?Q@X{m|W&Zs|BxSf=b~X^xNEf}dbx(|&e04Uu$2h95}i->V&;ox;BF z$0;FdBbJ5^#L4JtJ9G#2po3_a=Eqqqq_G!13UoPM(kJ zY{K(?)jg6|j-JDh<=%PWNqGCcjl2Oxz9XvhC3?Hf%wf|+JvCSiJlrNV2eA@|6fn>< zaQrvhxkAZDgb4g|^!^M@a+WSq;e0gL_Ux^wx=R54Lh#ovGYcad=sO}4C{cCHtSk}R zS#Nh&JTgJxyC6Y>)`dokhME+(1yX&umT~u1K<`xh=T?*;V{yyDNy0)Zoz409s1iMTu}${kbddSZ>J0x{jn&Gx z*?h$yCHgUfINKaSX@>7?cRLFwm<5%XFFXhGq@P{S5N6!1F)#n9Koy!D)AP53De5r# zWq8gP_b|Pbr3)rhh8SG8sw@?lF~r?bm6?pqp#Hg2%MaYU2N<;j05Y^w`IsA3lsl&Vn^LzHP) zvogO{#Zy2II3E^$t-*%B3)(?74~7fp?5UdW2m>{R@enu;#&GQ7W7-MI)t3o%qc zsDK{8?f<^ADs{iiK9~AZeBIjJZ6HmBe;we@h9dF>+JD7)jzizZ9^4GpI)Z3P*lH6) z8J~3^($iEx0vsg@jF(|X6$lXlA7g`p9EbmX!0JX`DlV8y)sl{rpqH@gs#ul(Eh`tv z-ODQA>wQDS42XCgzSG=A!+B_Brfh^MZHik}ws#-pwZzOeF7Mf~Zqd;`isTMCE9W5_Lp#rR*s4mYsCMaAll0a$ye>>Dv!#ONd=iBwKIg;8|ywU%i+ z_kGg8;U=?S(yj`L3LtexzgUj@%o8$sLB``k*`fZucb*H_*PugKg5;a0eIq9g19_a|m9N zyEgq1QPhkz^E&i`z;Xprw+aJ5um^(sEl{cHYhaG-Mjk)RP^d7&oQ>ynPlsFzOmeWL zSFQTW>yAgWjdA&05Z2wBlvG@4;#{5oNi4{kBZ$YvsKq4Z|0+~SKvYFsRxKjR%*vW# z$q&OFImd8^+v`Z=L=W{Ecd2-*na|*}9Jgxv}37ffsz6oc5TLioR^WES#Mx&k2*HU| z#-bYsJ9$Upm{-LrLb$l({>tfPEqQ+?=9`7(`6OfhW1Z zLV%Z`@oSwyCzf|4*AR}|hSw%w_QoOv@LZz}!w#ho$=`I(!~c42I7{2w()$bm&aA}IIpxSM&1b9Ni-#Bgeff89ku;7&#C9>>__AwDjXsJd61Ar)3+48eOAyARv zIcYAb6qx6EfMw+Mh*f1#$l3}7wqr|cGFvI2dJS=d z$`K(t!y#I$lr1k;k7%QTS+Zzfh03`BK-*7;J8aYRo%Sv~Rzeq0vVplG=_r-8#9AiO z@O?fQ|8TQCy9x|95F>NgRS+@O>PN4dkP6w^snMC@0P7+d-H@kf=K^J(91y2JDGSb$kcA#eGT?;B&5DlAzmP5Ro)TjsS-l@} z_wqg$kXlOW-z=b-j`q0c@TQ5?XJ{bh&NXm$^l*VUvgg``@oU)-Ip{UVY~l*LY_(tgPs$R z^0}-hrD)5|__Y#Cf`Flz7Ksor3d^_beLk(?aQYMQa{dT%8mtt*vI!s^WB=rtyPGT~ zuxR6<`IH6k@rz%hl>NYPM>yi){DAyk)pCH2R&%neYZ*MFLTvjv%}meh4WcMy2x+Jf^5aOXJ5JrVd!EGP@ZPj@~K z99SX6tbd~Wsg%{av&|}ovr7}q?dCwjsf-6OqoPk`;OX#VmGhh#6&@B>3brWMDM$X1 z5wqi)Py2Ctn^%Ol4-hgX8K*LZ-fBB98Wy9{gkN`%9or8go^HP~W(yK3UIARV0=8?9 zF339Zf>b)t0->$VhtG<6f`J386181S+{%)NgY_nKhNj^Rp(k+feq~z}V+U|SML+Np zw=F`~sO`9MaYNq6V!Q#ClT%FI6$^lEqEa?Bm0+xkYP(Uidw$o19L6?tKj2ca*D&e)647#kgvdi)U z(7qTn|1&jaZFt@z{zx}Appj7_3O<2`yN-GO=`asnCwiM-s9K-{U7$8wE22O`tDU$w zogcmx@M5n)3`LXx-|By6Ml4P}A}KNnOy6M8`d2TN-}jY4oVfq^v1cN7<4z!Mgc{y= zU-}~}n~)T&zX5QeC^kf2!5{ENCwxAd2+(Jg*(ZR(PvuF%LH;G5UG3}FAX)_1Z*iY) zP`e$M+upmI#x?ob`*Mk)MP-7Gn%mh}k{jj{n zH+!xI;A2lPehH0-pnjKTiJ8+WN5^OZ23Gdb^Z;S}<1zjN2Exw9c61{&W+#9H;zGb{ z8^v&nppZ9#zCm>n*#^@c#tZUk_!T$}OMBn{_CjG43eA~&F{_FA8UWDV7$zThs{V1T zh_Z{+4>uz7Z%-iSk=Y`aArVp~psaJva!&#IP|0XxENr0?v-QIF70RT9+iZs#i!6Pt zB@l?t+gJ6N^ji55AE$Ni(V0xf^y8Emozmg?gL~jq?ivg(;r%zClu^xKF_RV%?V-Oa z_`;9<$SSbMEN67b#>ahL_cg772;K15!IB^<91wj-tK!dA7P;clA=}+J7+xqzf;doz zEE^HlAb3z+81{foIiBnN<2c6?{Gu;gB$U7jl%g1IC9(E$BtI|2%!1wM57?mB?Vs+HILD*7uaWnCY-it z_&d3YME~8i3vG1SEXi#^;RTm=0Vam3GwH%CVeA1=gTsR$ainyJ-B= zAYF?-KypT0cu=Kjv0wv-vD|7hzzePjZxcowo)F_II6~rlk4s@&uhl`)av;Y_w+XQl zpAfYOn|Rimr31m;i>%CNBM8~bxC?bKbi^Vb*@2u{YD9!D0Ug2E4Jigre~6w1FF3uz zyhGnPoKIOz=mc8t?3JbNbAp$LF|~2Ch|tG!Pkw& z!_S0zcC~`vfGQ0~=Db=@DXI#|}|yPZ0?xL6iW> z0o?(y9is^& z-iW~C!Q%`NQwLG8Jj(@@q=+~~hw1d_a?5Swz*?uj(w87=6Wc9@KTUT`0h(am8$uo< z^%ojVm7;RK;x6CIfFFwHXy}*@gEWKcV=NIrh=Q`?D{`d_OvXX$hKfUabzlory!fNz zrM)6(-G8LB|NN2ElN%C?Z=aUOC`!S8x_ zCjKpM-vyFJX3N(R{%i8qR)9Xhl_0u-9Trhm&fBAK?0%x^g6}q8=+xtpCw1g_&1amK zJuyV1ec~GDjnL0*XBq>JSYz=q4xa5Tk>aINKy(myJ($ zd>=9b9x|I3%tC>Y)-S1R=k3zw!8rWGK&UtW7vbK?q;L!rL^#~sxjGbTq-o52^E8h zdmhfHF~&-yiA=dKr)oiSUK`rfYdhMy0PpT!^y?eU2sh-4LF1P0K$2RxnsQu-vo?rnDhjkBE=)nhu@F}Ch2BKCHhy3SX4o2 zoRQ0%XtOU%vOgRyhV9T_O_-H5l)ZM4}4 zpD47n*8OS7NderNE%iI>crOG33gK6-mpstg5Ca<#V=-6cOXs~jo?|koJ36lIZ1wn& zmo>j_jRTfIsK~nk8?&>&IUL`?eo~;~uv<=o(f&O@`D=AKB<$4Ghi%M2V%ip0*LF0v zQ}jy$t{OUjl1OTk@`d}EvK)>OButmcWrorvcLMv$!^u#^Y#%fu@V2J4uER%M&v&$b zk2)bk@_SnOUKrydcoSggiq{2FM4KWOuiPi#v@5}_bDcb0u^nL?*&ZyAz87AlMShEe zk3%g%c}1SU><4L>PYwo|Kws^5Z;~0ra_k2LZhW7US19}PV*xw@T_s}r_IP<{SBvs^ zBgndd;0Md0X!bRqKEwpbAJzc_b1&3fv5G|KD?Zx?xanb4aXa^IQqWA+R zap)auqoNeiUvonlZdefdOh)4tG)%0I-byq_urOQl&}`d6 zRKEEL>^S56-OHhNIc-_KWS#gk!umrxU*+w$XBGwbe6lKvpS> z@9lRz`l{XDtM_*e`=G6H**GQNHFcPHV*$XS-hMb5e$4SFj1-hk>|Q6n={&o>!pbb} zoGS<;93b6@?$sd_X^+4f{sD3SJyj|+xX^Tda2zrQqzk-~<`qJdL>m{Udx-OVNyH%> z64gNpKYx9WJ!%KfcsD2&8hMwVD7XQk8q0?}hUp4M;E})gmj9RxLh+8hdiah=?$zRG z&}tOAy+buqt0!4N`y`%i5}6dlIP4l$6GVudGgmjlFb)&Np>Li@6Vx8V3(<|_5tGvY zC`VByBP@Iav~Glrm;~xH_Ab#IhakZ_`T8N?^1;R1+!90_{tUq#W)l}KWO~#&+ z{UkpF2KV9p(P-AN_x@yt1Y8E1a(Jp7^g>Ni55@A0WgJwS-HREvXKT2R7YaKOy@|Fd zIvqa&2}bC>@art{HP2gj`nGn@4W>C!4qS(77t%kbMJ~1o1hc{)&{`Fs@h>JS;klpb z0dyTSr&v|!$M)9@v!JpC>_t_9C-O#xXb70$2>EC#=f-~J==Zd#FB#V)WXX{rLfzJ?sbA71dnRz}=SFnchjr;=%XlfikjZ!FLv zwhS0%B<|ZkAmxzFaSZ+*Ck{?R*${;f&?h_sJv@>5!@G5B_?>Uy60`o-_mwr7j3gB%!XR%%+e5FDeSapFz6|e};ox5hs|M}PR-)4VG-Ouhs>wR*6)DL7dk4I&Y+Jl7sTJiy67hmQM|sC=Q% z^0{Liv&yVd)cOJ3#&;Diy92*Kamru+Rfyb)I8ky6?FY92k@keZX^(2q z9?fiRmGa)iFANjO6d*mR)^>zZ-F=C_o6u`s~$#JN0I_ggQ2X;jC7eHUj zcl+vS_%VI5>B?;e1--D7iC7Bru}ME3F|p^6uj%`=rIA#8uLP!bXy8``F-FIz)k-N* zN)GWe?0ROIIm5uw0&hziP@xWtm5Ye$_2|Z*n~DS4&&I70ytf+^!b{P}FLQ8{(!}2S zZKqj96$>t`>Q*9gQ0~muFMmawxQd85R1-HdDnl)GNV%{S{;4RA zf!P6)fky^{^Xv?ai_YVVU*^$QqwWz2Ui&JsN^6KQXt-myp6J z4z-%C`*6SGd2=w)QhWBJN8E9dZlr3UmtjZL7^iK=jO`Fk^_~gW7R$$c4Y|X8QItWc zzGz-rQ)ua_I}KYcdZD}A=^9pareQmxwoX^8nW-JXnsaE`w^bGPUdq<_io>k}Uz_SK?QfvVCo;8Z;? z1QUav`lsqoGjaqRj7>$$2vWT-OOq``()!&6x2_i^>$F++5pnuD5GvS{wc$IV5A&fi zm!smtd(`IfYbF~aDXec7vV|GOOApJbK3i^bT=gYiVWtr^L>dWA+SHq=JFDsiF28cL~@b2yPGw%@6Tro~Dro9&`8aebQYYZ$tX|4Nk((hTmtkD_==G3o~G{W~aCR42Y-iR8! zQuyOY>-jz!cQLKUs0?c{rm4;`oj4u(4-RcC>Vf!#(=QU3hC8acf_9o>feq7{Ux<;i zk&FCKy7O!nK8qmQ!-&dSSka?t2& zQ02vk5TCz|Td#SxCo9zVrGb3tQZ+oAa{>?}GQBHudW)Mq0DBpiV@TV1qAj_!Ag_N{ z#u&C|yH~>UR4}T&Eu$&TM~%tgq)FaLqqgypsgSYGslET<2kkg+b5f1-+YXgzuuAN5lj619RDvH`Hl>;hB2Ue6Sp&Dly!Nn!OUtV*Mt z_XicAQhN1h_w?|%qFpKyCU*EZz|{Hq9bd0)xVKSBRaqW^x9#*1n=M!UutlFZroM%m>~p!%ncV;VLy@wj;5u_fXd@ z6!{~Iins8_@|*o07D2slO8XJh&J#!%e|fkZy;scQI^XO}n^QZkkke$CYQE#xR_EKM z&3U@tazZnq<3MOsS~+Z-%d@$@TWVV4)D4H#QK{6RRK5*pKm6Z_f~*rwN|h70?;dij2Q;L-2)>c@er9)z@uZ{ zkY^*tmYVJUz-SR0yC}7!IiSMC01=2*rs8AM?>>pIiXURhgJ_(7eI#yqs#40Zs)JQ; z&ad;aR$-qy&M7-e!585ac$~cA%nA;5p%o}(Ec6CTz&FOeOx3bMf z+5o4Xcr^C$KUWX)yJ?j?1^T z**;94u$QjJ9r$2wq{{GNw#MAm16C_RYxG)7mf2;cha(rcOedwe$%kw+o{~8Ti^8^s zRh(P=J2B0Myj43w5lbVyo)ME2X;J@f@5vdhvgdQkHvWuos8I zwiY=Fr*9SXo&Vlg4Ew8c=wb^e^l*3A)YLRvAH$lFzZJeFI$G^>m|+R5lY6NYF`Gkp zv6jiJQeO0@w;^{$mJp8ndzRH|r=^jvp0u8AC+VaDU#IJ6t+(sZp4|3#0E)^`vJhBd z-v6Fzy$2_R0Z+N^a^;;bY>B5;a<*GmI`Y-;aK)VLz*nUq>+wvh%R)YF@A<}po^Or+ zdZE5(^t!#IoimSqn?CpL*uIt7uqh0*&*_uMqGMV?nv}aUPzZ@Pks#yy?`#K@4uBK6 z$G$o`UIL>CS4^>=VhdOX&hE1rofjRpz!+sCx2`Dc%9yEP8`#VJ1g*g6(TXC!YB&@K zRoei}c%o(iTE1}`V7(GDrC7ds7qd)9PFFk+ux|iq8%4&QAzXNHKm_rkbNGEm=*B?R z5`0WY-z>CWs_!6978Djc2#04Ht1jjs(Lz$pSMG?MuRqaza!(!?Hf~6YeruRkefiui z4GKQO8wzy8R&0Fxnb<_Q@C4=xv_5!F(zw?T#n{?jESx(jJDbPuRiR<9m}K8nFLAme z9ANpNgl1DsTK9)x|E%H5Gt?_+W!zB<<--^l2qGdX(uokZ)r=kWi!Y=eY?Gy16{vu9 z?3SrjfU&1XJ6N;+5N6ty^c&(EW+~bI~ZVDBZ!C zU>L+lJ>1=Qzy+(0o5#l*AIE1lmMQ=9UZ$#Qt#b^KJoR8YM>BcIh~V+LmSNbyaWaxJ zx}V|RAv?Tt`T4?IjnggbkwzOpt)yM6-|n!<@$vZu#9#_4EjV)eE%RLl+Y|*mt}C^l5ea!Lat}@NHhP|IQ9fXd z`D@2<;~?4+xjCPvR}@xD^A!!y{rLqDVkop7BmW@%$#eX$hTZRt( z14geHzOBKpU^TpYKip1f5gdCc;}DJ4+LFq~gcV-U#>G)QOYo8{ z@8=B`CpUm2=dKoRh%sQdrLhIyC!f&S%TEr9RD#@ic8;}y2SBJE52vZ`6D9=En@? zWD}868Z!Sv+f-cj^u0ToHy&w)852Cdmm~!V<=Y-wU_G<}W{fpc_21zP4V|1RH}@uJ z=S3YO>dfpm2RnD)fI{$7O`Xz(wW5O>2YEGWX04>xhudA32 z18pq^@1@Jx70AmC4IMQ6F63!!&QZ+%b>nKnbw;q&X-5pAJB41`#}}vgKqQ0%kX)^a z6io8D*jJyB%DY6U#SjYS+qTE2^SPf|3csud zyK7SE`u6|4(gRekpQ@km0T#&t zP?$bWvd?^KTSygeeud6!E`5H?ttcUMhtdux8!PKe7WO*@kAuwS%u}EDf9~Hq2bdK8 zKBKwI8)B_;Yl@-8%u6MrxLv z8}B~W`JJ2s*pyJLpUnW&(R_u1ubwTHUN{=|9OoZvFcq<)c`++;;-Tnm2F7n3uuiQp zSCh$6(5l`T; zq^TWCz{cQqXj1>E z_>^N70i$t167}&(6bjg-ph>3-QEOakp6??YtUM*r;?dA6S*iX)Zt~^X`TQ^VVq|;0Qu#w8^*o8vbH2-%iG28bu&q5DiCpp+ZS!ne@Gv#~-rT6S)B?kHxp3E>{ z!@2{4yfi?s1Ne~EcK=)ZcG8C!qJD%=wf6qf;v-Yw&wrZBH`7d7g7!H_Uq)^|$;_X*Fr?RJaY8;D>2puD(}6Fofua4V?$Ai( zIX=HhKmIX)*m3O*mjDc{yUE6BTvqe#3Th(HzDHKZEG`n$UVw@b_~04H{dEK4D;lJ& znifs!4P;~gkgJo^Z~pq3Ok7e%ITj9iy#R{DSAcird%u(hsP$tLro;Sa^F>)mOvwSu zQ3Dk{SJzvBgg=_%f@QL_u)dNZS3*K**MOKAnwrYR0R-CSi5XR7;FJ_zeh zrBQWmQju@-HljGweYJ}!t%NV=v4LxugD8Ip_w{H1Iq-21s8N)i50!Zjl1oKH|737~ zd>FnMEW%Ldxc#_Z%VjQRTXmaDPi}7UM6x1~*=2DQH$yk&*$Z1$J?G`&Iji|?39HS& zyGs+Yc@wY&*M)ncV4@Rw4dhb4PkZ)+c3^qX{iNl zTBK89>GP_m2JQ$tW4iJT=cD)4An@w)dff&hIW%xh%AgJZs+FP2+0`{0D@tl`yj$OP zrZsJsV{teS!;+NR{{curA?3s?%T!%GF_zr5Jacb{%l%rdpR>9={jO6&g~Q2Mv*+PO z`(xkl%vq4eR?c z?ltw+jXN7Vil`-Gt-mgV5xO4NwzjqwrkTD_jm4M%g^rf*dPphfxF;!_D|!6yCTsO& zF<&ws+NlPvT-n>dl2R>G*i#o!$;fMFBN@|7dm5rT2sKJDBdDBRGVwb=~A5dB@IK6!xBrIanF%2$`ty=CEdAzzrX!F5~p`!Tg2h$nUy; z&DV+6U0)m2@DUL=Ln-Cs>r^{Y;7dBlWKkz9t}6V!CpYcXXUSv~8Tu1tII`&&r6Uyc z$z+SS)6MC3Ry}hSMpJ^OwGzo6gQ%jrp)754&F(dj(pW<@dEa_wsrMR*`V4EK89>Zg2zBNmsMw4FCM>Jo5ot-83Eqd(46pNSVtlLQ{2PhPg z-XORoH;Z=2a)JNJJE7HvhK7m@_oM#5=M$#~Fo^4~iVpi-;lK-W*;Jv zo&PLPc`A@4HCK2LJ~~_2{Ofv)Ia~2Nh78uWe?Y+qz3`npH1t)R#_Rf8IR5JEFV+N& z)5BM>+;8$H=(^04R}7L<{5DRzt8*|{&4GS2|PKSp@X^L zEBJ)KZ}to;DA(q)U9;Vsi};t(aic`7f^ELA%gU8xrg7D-1&|B`+dVB>7_Mqp=eyC( zobl0^l@vy8XTc4AI*O;WICN^$rMLS9B)Q6U`#s$NI;n0u#4b(+{cJzO>mW>xf%SRW z3oVsJD5mndI%?;OnyRY5XJ;Dax#xy;`Iynaq~3g&``f$99KS2zsN8C5YHpOrSg>2W zqNrW`EGiO@n>?7yu9Lf(`396{UT(Yo=|h@2r$$@Ln94G^Dv1X;h7YGf>^B3o#$p}L zmd)rT* z6IJ}PF~6tSA+MR#gGxDf@`yZMV19w|bO$4tEXg(9`E;?OuIqixgE@jj64%fh1{Lx_ z!W{0$h^VV8`-+G%P%5WTG-H-`kBmscgbdl**vMqCD=I1y*gg2nlX5~Tv-d~bKJjod zhrA|6M(Qvp*Ew~M%n1{lF71b(E+w^@yxOHcQ_JJRLoUjAVQDQ57Ya8sK?-Yut0(=n z4mzRtg2R+aEze6$#X6`Al=6rE1|e99v6whi84X=D#ww#`aBg3KZK-ZjP{q!KRXMM3 zIe>Yrz;{)}ZY@lA{i{w-wrw4*s}n{R1V6m5fCm7_^qOrn>!D}CG3C_Ic1snrj`IML z{5kDgm_7RHa^nvJn0c1A-hO?*i5$UNrv*g>kTOIOr7SqwXz;y9QMllC!2}8sZwRz^-sxln zNKQxL_dWP^?~qI~76i+QmGOQ#ys7G?U1w-ukh6JlA5E9)M6(EW^lyHLGSV5_y)gaM z$4a?1azR!rc!Fb8n`9!FNL0-LOZKPy^}PqPmiZ*;y*oa)gNA}BWV1rqB2nv18 zBT1>k3yrROPyWN~Ip(YqvfUZvahUTI$x&U2}Y%1P}6 zXnfzow}uF0A<%Z=xJpSie8;1x1%Q^9x%ZU~BZ!Fs_3n{C!0RfV)eJDySBlSMw~X7D z5N>wGvh)Cvjb9SbcCixbeOqk`Q$)4$->3b;r{MQg7gJD@ERMM z;D2~J%cwZIwpk}3xCIaHuEE{i-C=^e2Oiwro#5{74#C|9mq2iL_pdo?z2|obYct)` zz4u*JSK0sh*tyUUkGnwx|rF({N2Q;SLX_3 z1A_g0mUcuQsfEka51VXCbX70i=k?A+sixws=Binn|1uQhsyELm<0cp$nW8DYh;kDPA*C@=vb?eD?01F!2WOKR^as# z@&2#VA`tL^9YVxqmmTv3>q!n8i*KEhQE4dB?;7$Ju`_gB2=j@lV}@T&E~1c%*VuA7 zY>B2yQEAkf5<`A`!(gdQD;^xH8nf5=i_0IRkMU(F!~C1PcbVGWsaw{VA6L#ECl2# zKWm~dEZAEN+DM=TNWSF|awE^)mG#L_VJt?m6dFdKV)h~v?D3z_`0m;Y?8;Y<6YidX z)BwFsQzVkpoRWl)fi~YpjX}V|!ZcY;d=WW1HPx$)3-@iz0v)lUmu2NfBJIKEp?54J zM!>Idg?zP85dn-l``TPz*-^$FZXC<0pX1p-Yb|)04slIm)q;}RP5v53iK*4 z5&+47xg((LVz#iVX1YgD^)}`0$_Zc!5y3yo{_(k*O($L;N@_Y52vDSmB;VOR*T%Lxs?_RJ)PS5$h?Aps0}i&{l*7N z?w8;#hQ`Z4BDD$?V~o`>RAQWf=+7!*j|@r=;7mf8C(HH~$gMc9j1=o$)xw{3A7^=- zw;#XMPj%jaWzM_b-*n#Xd7M4&xc2pd7H_LXyOx8zh#~^-uZQ|NwwJ?DDp#p+_RIYP-h0Wv>NjZf;T<|^ydP5x;7!r7M z&L#`A~Ao%LLGnypG9m5)R;-XoA};RVt3q}LEkt;~T(qb{xx zIo2+MrhJgv9?y@x;r=RQbF1+X6~qyl>=72!7!HJgq!@+>Jm|P|yF9sMzpnBF1Tf%n z_yo+VPPLA!bgNiSp*v;)8lX%9(s$@fdhL!+r<4h}rRKNmmC@~K3Si1|MRsbULH@fX zql*&>ATk9BkGTe%izVer&srR|U0FqNkn#E4S*0909Ja*?Zj!3sFd$pcvplfFbBxOH zvy!4i{f<6})|!rjxjmF-{Ljl%d4%mi$S;;aF;0c0qx60wv)UmJK!V06e2fP^z8N1! z&4CE41UgvnbB~Q}u|GAjJm-lT5LyX{G}-P(%tDiHPk^qCEea&ER4pT!>*DEXE!e(K zi1CKJBJ)Kzj4T8Px-|Cc=&7u-+AE$srl;wI7gB+!n*RHxuD1AV_o~w7^ksD8k5E9L zDz}c>-{nT9isO61f?n29SUGPMgCZIoG&ctwiRZEEF81dnjcl*8$EN7X9+40>B)nh! zakJ_b+Fq}S99@rh8KC#O|6WwXv4dYGb+e|TtJY!-`iulhO3Uy4W7~1kprW%mEsUJT z@O?V0dh!Mo_^wad5OG@_$6GF6Cek^O#XVl5I2J1H_Qd09;t?53%1U*b4ArbWpkW#G zn>sWP*4YF{^&Y=4<`-6a^%g*sSpi?O&4FE7jkqbc;{}B*N7teet?}U!FrvWQ zKlk|8^LXA_4aYkkS|0VtTb?q|Xth|WSKn3Z@Y7jM&P!!>l+7v)3Ymb%MORMlG@g7c z7@2Tn!yhuD<@N79R;*){BJWKNb@@U?A=HCzo%LfLxlG@$;IiMYfBathNeO(esG&Z= zi8=f>V0u{tG(31r23xChYg>!w*UDy*Is^h;2%f(5?zh|OkD18ne|rr2ZIQ-S$I!Bw z?3ujRjv$|F`t>Z%$ROeUQOyn< zhe0bFLBGVKEONuzV`CaF!#tcY>ypJHO>kxmh*6T#$h4{i02*B!-lFwVth@$CbCZ3Y zA~TK@3bclF5J_X5>}Uf5r~N-cs(6sVed`o);w6zq$a(uYzdm-|_u2R2Ecc`2jSVRz z;ufX^lb$G!=-I@CuM7>&0JYPR z9L!41q(fN_(^24yE=6I%MHcj+u%!VES%9Rb2}2Q`?1h-x;7?MJAcxo1IDp^FcE1_{ zSXkJjW(=B+)YNL3=KP}5-#WZI3kbe{CGkZ=sViZ9;xa_>LJcnD zpOJJ#b*7(x8$C(!zDmeeou5l{pG+TMEkdzZ?=K*Q;o5|}_(|_?i&x}C&R@5Dw6cVp zuCsbtU8>`Kn=V1z|N!WECa6J4ed@MgE^>K~Xt_P&2hYvhXEmGjqpb+;QxN{6+ zBjSpVanpV;UvPMCeMLo9#s;6|Fu;*#4O0%ZKCeHY`&<~HV_nRVr|3uj>~cSKAB`c4 zmgKd+P;^vL;mBdp$RT=}@UiRZhd?s4j5!li$1^>4iql32;2g%tzsID@;4<1H4w1F6 zI(GM%TvL(fvza@%RGYtb+MCQr-?6-y-b~kCp<0YJAO)T(Zg|+F9+6VKaVM7}0s5Yo zCX{qTP;;bnfeg}^Ye$MB*;KhULarf?U9VmX=Q znWcb69}h>IAh0)OjlgOA$24@f=@|(=c(J$B^LU4cJAjFznF$46rJ^`Dnr!MonV4;z zlZ3b#&tn{c`lc{a{7D4fuMGW1axXJsF=xS4)VC<}M3zXZir;ZxFoIT8pR8`OYFI#0 zA$2u-gTia0Y`9zt>a60VX_)>@%T29}^&4VVQN0mr;PEGN7toLttvCbaqZZ|47C1 zW5#FWK!YUcDdz>mtWw(O(sybJd9$8aRAO5d7n|6)$EN+7_goHGj#N4i6A)9Kd|^GY z(+otRNGw@iR57YWV`{OrTGxLuJK*fjl7>90 zZ%RA4OcPi#2R2Ia^6Biaz=XC)BmeUbrE04Arwst5siE&-1Q-lJU3=9BV5YIt@-H9SI?@pZ1d-N9MD>YRE6@s~>j%@2?ZbS827}wey3MwnsC8kQ08F zLla(;^_NFQmWabBkSXi&?vzRf$8XOuH;0OEuoxSG%<0F$A~k&+sVL zDRg>a%y$#bd+5@#-O?Y(OKfVYF)=LA7s&S)tZvN~^B-**DlDHzSFIU9KMVbEwjbW0 z39QYn4QsTz49RZ;eksW8RSjjiS{`0ubPzRcnj6IkJd(~0cHXZ)15`SE&*9wJB0}dw zlN6DgaT?3xBkD0=g8-Zx2&XeVchjoD4>R%|58#u}h*1c*KKB!L4!ap{*QrMqmL>Eq zjy9WICn*;a2!w5a3F9-{^_RsynZ-68S(Tl)?i0*dF)K!xHL9R(3bXS`lOeIMrVjE| z%sgTgAtZgp(s&syVCG^hUdf<;EQR2AVRQ4iUwB8@B4c_HU8=YQ*NDb1Zf4{wM_tDV0inyzTaUsca+iT!1mJ^0D| zGKZ?Nl`cFgG{t?%%;H;xm;F+<>k(zfTp0iU`B0&eR^#qd7y`UTTB@kVJpq?(X(jW5 zol+^4!|G1)+^K{xV_XRMT}MafRxt@ne0Daf$L^|p(oO2^?rIJlltw=1K@bfMa z&K0#??4xk>%W$lEnUq$?RcQZe>Rr-sCj@DHil$TwVrOA%(Z98WWj!bHfSEZ_5`&cr z#9zOfuxHxy`F3+ftCHy$S&$Q;%fH7N$XcUO+U;zpDlKp8Z4Ju0%<{tX(apj~D-Bz( zvudJ3xRJVxodu#Z|*+ur0auq`i79 zz~-LsI|g)SB3m*BZL%95(Xy@}<2<`b(KvwbSf&vewW29F|B?3lGYQS|8(M;}wPru^ zbO{Mmo$f9)1&G2bQuE~`_4-EaP1Bz>TgW`Q5dr_tSOth>GW9y^)>Nx5csy>i;%tft z!K7fQHd`7Owt3BYB8N(?imMNv`H>hpBXm3qEnA@lwUaS>4r>xXtGo-yh7S%MRigwYPuAs9tJyVh0 zI^ivkGA>s#TFB&-VKX3EBWcAmAx-&T1fnSjGk61!kw&+_vM7cPcSU!S;fZq21uQ$u zJFyxk=^EBY$;m(Uvlm}QSJi3w`UYMP5LOJ3MeWvmn^yE;n}u5rK5O9_WpZ5d#&g!i zYxF&zcW0}SpxXa`UVuecua@pq;NmL26ZlqNaX(qmM)98yhjdMPpOnTIe1q*93o(A^|*MU-DEYb367AH|LF$v5t6qSR* zq}wk~M`|J!%E~}hiur6B$c2ljPqu1srST47s8DJy!CkMX*J(8}5%CWrO}1s_9rS8& zmzZ1|8D_+euMYdYUH?sOsL5211Y6`sQ{n7Fv9R!SO~KI1@ZWS<;*Qu7L5JXr#Gu-O zYeb8{$`%q@?Lm0$l5Uh6!27r6j{F^GSnKj$)i^HPRgdt!GAk* zS9#1JM(k>xoN%}>V{X=b#8^Axiukhc@Wc%N4ezE%S+a>&a;VxFw(`#~j8tW8Q7RqX zv}dEUS~Pq^&>HYrC7QUDXFwr4X@)ild{UjqIhNf1S)@3}4AVIc?{zNnyHTnP(PeeG zP6y@Q;j*~8&T`n6XM46dHlbv7ZADu{Z-53eFW|B)fpI$6BtfSxyj0eG zKk&t2NnnO_Gu$}gCuRJ%&Z}gWuqYue<$|qW?VVpwjtH&S(<<;0o6zZc?d}ch zd2PIi-Cb(pPH7;epsNB-#{};S5sB*R1pRRP;}$&RjB4_$*PQc;nD?Ly`D__u`t$<{ zfVZ;y^KPiOzFW85);h>T+~kyTjJTSl$at%IY*p@p)=-y%(gO#=IEk3YElBKu;AePe z6t)R{ea{(qUEMY$;w9708i?kdx1+j`LZ_5p>3OHQO}-Pv6|YkpjO7K5I#2EM zCVR6;$$nfe@t8nbujC4$fpj5kCG0Hn#uB_k?MjvB>R3n@L%K73Ul7Ww(!iyNRRs=E z9EDYulwzw@JPJv_uhLbYvX(+D^7rfjd12PSABH||#CyRtnX3Btz;p4|umNSR1iKXP zVrVO>mF{I6Xj77oOVU{X5c?^_hK2lkG3^pAS3~XO4erW&95i}e@4#`5`CXvGfX1iL zFawU|z&t-53(8{hBFSjd3@nS=`A6Zhoa@kzzU^sOpskc2EsTHjzW?m+bIw1=Fz{gc z#q>gi#+7TjK*7q6T}0yc`rK$5HD$iVl{}liWxi-LVTLksba)d^(*v!B#9VRrQrX~a zDIJ^aE#_565+@VXoa7Oe&zDZDso$K%Q3EzRA^OdSFpVN|K}~5LnoTq4sdl>Gj+PD* z-Ei-2wf2W{vr4X4-wIpiBOVHVdoTMr?v9U-yDER~zLMf|^$J|rqO7CPZjPq>5m#4jAiBP_SgGd(Mo1*Ce*>0zkg4g=E8=H2u)dZpA(SARpbs%^= z?+w|3EZ6SCzrzi2%W?ZL6cUpG=VN&4Z|0yEmsM6y9FxX(TGFTbEx4)A9EgnT&LR!NLLEkj1yRoV=To>KCRvR3$D^BXGj5l~SeR;2eNW zkLLqgLq;@`V|>z(q3B%%Pi40fUe34!|LTz%1WCFHmyWe)8$#F6f<5t zOP~C<*srJ3LUiE~9b08(*3B!l414gcOETvSlZ9L(um!`z)}l>Fl+P>8yYM3kj^m@y z9XP2_ZmZuN?&2pW!5y=bR1sffknuPbkHfQewOSG8&RlL`MmoHtL9fDSCa3WCtf^;4 zZz8x58m(&hG-qt{CG>}m_PJ7S0(4jREsg&z{@k}a#di!{UTL>}yG|W0r_myH+0ey= z45oTr!XbY+N)Bc|@K)^#{y|bI%9HMhp_HSsk}#Ase3Ea>>?XMzRW(WP;VPu zi}tIOD+LbK%Pss|a`&RjzCQ#bQakDv7EIT*dvL~W3n41!sLRXC z_sQfDT#SCL8!O4PWjs`0KEWu(q$TL4Ut795=m#BJ>b34FHk1=ZWkk9ehgCs}?7;+0~vF)98J%+p5qnPQs*7(vm z@j8r?f?wBd{R1yWU(3Fn{c*1Ysn0yQxCw$#Xq+>~VPD=>+$tbHjRd3Ors4`2qq<@v zknu|YTKXK8jycRE)%UH~3aS<2RhZlB)?LgY%BBFr;(I}(BL3C#+}zH`pFaMY69^t-U<6o+VXWUS3zr_TPqWRzecT zXSM}ku>Na7%WNXUZM?xkg21EV(b~$YF&U-eoe6Z;Y-ac^eLShL`6#vPum0LBdJER_ z!p7TeTxCq0tszAF_hmQTJS!2y1=R@<9 zN);X%2gqlczC59O>Kz=I+gV$4p45zl5c2N=HcwI`XXnP9WK1#J7|yK=x9dHRcGTy; zdCP#;ysY7g>P!Q&}I&%!~69K&>c1$-0CxcvE5xK=JwqWFkC)mJIiHRH+J<$Ee-$i_N~$)O6dnu(#`*S%n0f z*3!b<{L>XJZO93qB)aWcAdcPk>rgp!xxoSrTM)_(P=!$k{Eg9I|1l>by*8-vTmPU) zD%5%Jg=cUD22PlCnmLs*BY39JXsWhqD%BV1hep{M6$xulOVmHOac( zvy{qZm%PbN$^&O}5=kC6pd(`)=z*4_Go47g1x8EY2QE9^_a#kSuS_!HK<^z=LN{RH zl3I0@6#j=fcDvx@MPomutTYQ})Z{`|qr5+h03>W({>p`({H&e^vQkwtI+jGrasdK~ z)3;eN2A|8(xUQg_Ar}&pA~$WkEIVXDumLBoO!FTR%}#x3tb(}qr2RPMqH3W^p=WeJ zi)LAMDWB(+!IZ!=r9imI@jIKz-!1h*mH|AD!9q{sJ~%IQT$M1+E20Eltn31Dl14Qx zdDC9OnCbd&YY$0dzmL;>jj#iS6^`dKSW^)+&3-Zy*vCU?r)jO-lSobAC>0pqjnX=& z^;#*BEDz$RWD7fdrd5`zxHiW*vc?o7VL8)A(V|<0T3;xpPEh7ybgX(4 z1J(epSgb>fRb9&YNe+x^dt4m68#lYpj+R|=cLUqm?yISaMOKx-dc~!?PPl9Ld}_sI zhe1pfMJIZk$n|LNAMQ1_`Ciay_~z4g?o$%;x}{=#VNKRnR0BfjJ{!unuG`r5R## zj&w3BZVZ7tk06hbgF(CH0nikc@R+JXiWGQG8-Sx9;p;XmWk!w5skS^tG!|K2p3YBA z{aVAIJZ(MK&7geos4bKVnhy<6drGWDB(Fe=Xd^DI0WS6pFcnX%rS5y5Ic0D2=1mV^ zfyQrdNXTGB1-LN+1olUmQpp-2DCGek$RxmXysnM$iiExt-DwBh#^0qSCEU6fP)&M z+yAdgs%<)xK`-z~2{RsIlXSzo zhH+$G`r<&~_Y_WB^^KJG;a`9(k}F7o_ws8P2=ES&ibwwZBJ`?)%o|6S2{=vzppnT} z8M}CO{9%vu)*n8ifkF`J{6H1DW3B9R3ExqwG%2pGVBD0zyQe;ho5#!LP+Sn&H7V*o zW!;2^KH(RfbAMjaZ$Ch}jvqxomxC4X9Wwoe?NcDVlFP}T#|vM3YErx|&r!{Lu|Y#%Um3P{T^DA{=>yMjJa zR|nm`ax(l;l2v=0W03+)clIyo$&1VCv;S8MotKU@v8x@QCS zZz`HpoSbA=p@IsS+@0i%ST*hkpqE;w&V9)sB+kZCzaGu89SDiEp4~k8dnMbq_jMJO zd-Z*>5&tT=c(ql?;Y(EViw6Bj>3X-mPkg>m=1=giPp-+MoiBAUB8VMIu7U6es9lIR z6RSaVKYvtrh~|&{1*{0JU-_hy1zC01w|w63eVmp7M}wqK&W}qAlK8*gJd_sEHC$7u z>C^TjusA=w3;zmoba>!=F8#pnH8fFXd524k#YW7umvx2riycohkO{XJ%*0@`>}3MR z?yhU3cucpV%s8Ug@Vbv`mj(^x;CS?wbZZrTnCP3_vt@`E0suik`8JHythbJT-#$G|kFND4I58E-6$nIXg_cGhLs8l@NS5GBWG!nwB? zMEw(?Voy66>{9tpbH)4vdJSK31XP0tBY736^wF?HrqL^P!pvwh{6e-mUhh`t0?c+P z|Cpry3cn0{8*nls@EGsBUz5|wYpr_`d`@*-+G&4trMwO37j!#iSF~$CkJF&TMV8E1 zmoO@d8ODry3Q5C|j653|+x4yL`8^>hzhV5H6f%fT(xkkj>t{B(u3UJ8cP&MNi6ccL zo$yfm^+sM=i3(LPd+~Rgv{ag^cDm*b09VKmU}Zk~>$^VF1Wwkj#?BXa$mZEEL~F(- z*~vYSAq4JJ`PuC2p(LXncfM{^;N3zv-}+F6s(N|48df#JE9pr>jiuU7?cD1A{F` z87uJwzZGp0n=pMF#i|q+VsPD=k!Y-Y2gs^3LnVCf__tFz=0W!e&Tn^X|4D+5xcD^i zq_N%PctgE~ySEauOKcwW;I-1EojzlPA_Ub~Zxt`s*fC3jUj(m_OSk3BWq6oo2TP!j zK<@Te;;$t*hZig8g8pkTM&MMm$_CY1ca``eVk#X zJ(r53V(sKpWM8^xIY%(0ejxuu&;31JMUy;Q;8%JoRMBy%0dh+n7o^fID7-6?RlcZj z4|&R^zM|C=AwF5C&>Kp!q%2UV`X^VFt7z=&KTAraNF7vwv?WF~WZoqykmqX|8_8Xe z^CFWky*|t|KX40nq$=_gp1KrwWo;(25oeBS=;O`&56(m;LU@~aiZ^I00f`M39@i#- z(E6TF`tyKBUC4LZ*Z4Llv7f3%lOtrO606(~(zLsj%BDB*hqX$LZeD#|70UnkoEtE& zvZ|94M;4~zOf$U)m1biwMdlag=yhwT5+?J6m^WQy9Ed@p0s#au0lFGl=&Z%T%yZm_ zVys@0flcYOBB*eBiR5u6n7XpK@tj1T6&v(hD|Omf&hjeFhoaMhRHwp{D^bI!ap9;f zm>PV9Ow}Yw8VK@3U`m-Vscdrc=q> zi7$=9GU{+1;PeiUUjlx$AM-=@^wLR!#ieMk$y&tp>A{ozfjB8GexW_(h40sf(}x#b zh3E@brk_IMln^WqlP{B3xfG65b{R>aIKX8s5eX{-eV!nEDTwN(pJ8+@Sgojzi-DoE zBT}gS8c`zF<-tg`(&k$({p8A|%`btfl3KqaBd2}{#Ocs8hUz@R!ig+xl10fL%@y>O zbKbC?E}|oY;ZhYzClgE!F-KLt$x@X*g$3fEtuVkyW_%qfI8cbB2-DxZ`UgX1*k%i+ zAAxXYFoBm+vTyr*&+KhJTU>#Gi@|1==6@EUEz)VJq_$i_Z()=*5V5Ah*b?)U#0o|RbVYpdY#s2jxR=g6b||_1Va?1cwOqAU;^-s@anRK;ZHw2b8uyAisBf78JF6f6{BSUIz9G zQck(8*S*GefwARtH~gZOB~j*|HGD4NaflnMu9miA>XLh<(vVoN+Mvq-{o4B*+cC)N zw0vzi4-Xtjk=`MoU$1NEa~S~=b=+}RNB(eTUYuDdm>vzKHG<+rzHQt5IU6dhIhbs@ z0vKv)w#6YegTm@s*#;HF2}Lm&SIGSK0%hw8x|a^jQ+Np!(My`cxPBbj5tdeEI%yo2 zQlKs4;guidQ*_GDz>aB>P!V)Lb3HjP8fks;t1YV0;^O1UQfgIdcVV6dzpo6J7#z#Y z=+7^8XFkE(+i(~?`R6*{@NfrBf&1p4NRCA?S|x2>zHd)!k=u6B5P=)I9t%b}dZeEQ z4Vl*s?2Q`1kc`k^ZWE98s3_5I-I4^K8@*+utj zy4?kxI||zxctt#`^m8Jwxnx!A9*#H3>Pz77u!doUxsDTZ1e1nlc0_B|q8`7L%281V zi|K!Ub{&sTHJc*UFLRXSw7HO5hlo)S(n`&ziQ+;Qyl+>G@A2@8YHltKq$c6Pd#aYB zknkJDm9}dQ2J=Trh}8(3_Z?2*11txtJ7$2#U_6mF0ZwH&^K;?W@5Lv8NEg26ey3%2 zb(9NXgKzv})cg=r4%)8UX!>YXNu~jM(t_;Z6q^P4@K1RN{k|O=lcG|%%;a`INcytM#eAY zeu9+?4e7wrO2MoGOO(;*^r7v3hm4yvjG*hUZ*`n5v)zB5L>~GsVvz}o0cIf}#J3S% zRpHb)-7@AQ=aDy()0kMgBF!2cg4?~{U}?29b0xHd3h8v|LPo5nOsSN`%EdP@Y-CQg+ z`3UBMMjT~h0GX&Zl8s=!9UIH8=qQN_i#MKnOP>0&nxobGMm6`sn-;HGlJ*PPV}Ns`}IUFTXuNF#58-n(I@@Qs9&ZAi{v zCzd#K-Wqom?vTM#t`7GUu3C7Oy>Xn%l4U=Bn23lf>IIn~4@eOd?5M3K_kKmZ>K%w^ zdM4m2w~dEVc#LD{wI->pmU3?z1r<`py>g=Qh?{KF(I2J9M0=C3AqQlNwG2#Gygw;9 zo3q#d*2fxf5ilV%vK;UUUMS4CK7-9UED_7!hVMOFF0oLXVb~Zrt|9ba7`VyU?cq6V z$@eI!(O$_sz%)`25$;OF^7`V)T8~*o?IkTrOB-fTr{QvdlhV1Lv$dT7Tez_G)F$K6 zy=u|aPNW1M)c*BbYSQwMBRJ%5`{mr;hLdPe4SDXF#TLL?*}{K#GAW?@(; z(DX||!|khAeb0aiv^ZEOcR(Di($FX%O{Ck#IpV`vH|{HJPbY?DYT zkv4q$>DqUx76%Z%z=&${_Wx!9=Xjab3;8P4^+ZH!X_&hizQ;ARIlK7ylzR?5CrF-C zA<2g{SWJ!NZPf($2|r4eqsoP3#CHw2G=+8{2?^wTPbr6cm4ZQ8HqcilyFk$Ki+M=I z91PCi|EfUSe2Cs$IhAJf)HH`kOCuENksWpX98@7Vk{!n*o!rjt5cw&yn`g$>7F$h^ zziZ<(OmyS0H(C}}MmRQq@(&y(i|f!-Y>-U zC++JCevRKXZ4L{ntFyQRNdvU94qqpK-Vm0e0arKILIXC9%s^SgM2k-NO&NQ&70wNsQP6WUJnoVJgYE|*9fzX zn;J!I@;?_c@}y_^v!dY_>ru)d-Ang%Z7PneSg$3zhNl%e=4?C4I+`Nt*A+@X3o_w{ih{6CJF?}+gFx~ z^ZMSZ(186!KJpfI@iR^o->UQn5a1Q6^N^ElHC&pkF7>r^;gcK>CwYTYYEv6U5v4Z4 zyh*#&WJOMWsVe)%%%KjJjUx(Q$;bm1sKfOV7?Sf?KGf7t@p}MZgYlb@({#J8$6k2G zNPM2VVbYj2fF{u&hDN;z9QB`ovJQNgC4<>wg~bO7pRnQ#$M8EIpdZ6Wx7qeD(0cL; zfZZ5@<`R^rj_XOChxK+|FTfH^AuPlXFu?BPi0Z#|XEjQfKQ%aK!^9yOE-M!H_dudR$^fXdS8F8Gx(8}?mG!Qk99|q)Hje=xwzS81;r$Pp!PX8V z9bmn1z4oPPubxhA=NmigS>x%7WXBg;I* zp8pXd9gHFLIhj$RhNSTav?8KaKxFE=*@CAsN@3J#`!%xFwvr~xJ>Oxmt)js1XXvuN z_FvA}VDM+WYEbjt>;1ZzhW&*Qbl2Sxt>-SoB%Z@VVy%%lqwdAWw3pBNAQl#y0AbY; z`^&ACS*8gdn;JHUSXPqRE}l98cZuNc^ha)7V44({LO(5D&3S3l7Xs-wyN!0;7BwUl zFVD|Ep9ao_Yxu^6vjSbV%S!6#o5da1xh>~PNTWHo0JaFga_H_h=!4?Yl%Y#4v=)<2 z>Jy2^_!3c#z!Ww*-~5)fizJ;@W&EWR=sf8X-UXVGbsH_`f$?!{3byOV94a?aGFh=v zQ5-Iel5DD{$Dms%2DJ*a2i1p**;0jxlVT4}kOT;_lGNz#I}q?uHw5v|)n7judN(g? zCu9!}8Vppeg=2hJB`aH`fE^tL(!W@t^KPE%*ke2{&x7e62px8tlB&_UMfGkVg5=!T zm`fOg%R;lbEbq2C4S)quC)FGtM0LfYeA_S^E703(=+!Qtj;jd)UoZaSR-RZyFd{or zOkCo1D}y+7WkD(ojB_K}U<}W{KLLtg_c?4=LJ((w*h=S)98eTqDvL)^cMjwrF=|1KJ5T$3iIY8!Erp|ca+eSNNyU7P$ zn*nT3z_2+wh=^>NjHD<75dU1_^o3M}#;5$e0>=XeWev;Bt+Y0Yla1^N%(cEcQ(XHQz#!fXNCMU+1VKk--7gu< z@RD7%12OtOd7*6QP^oE3F*g-g&Qf;+P2<%wL0FUSr*($lapDfghi>C;5rxI{P@IKO z%^z4h{ShpVkl7WtBcn@)n!so5Lh{tH$eB6nTI(|h+&S(Sn*eJFsl<+{R*;tv$!dMh z@I%69%{@`Tzp|Cr1f&I1YFJ4BEv<=E7HD#6 zC#R{ZTx!!Y*p!Bd3HyW=SqBeYD!`zP1g3a1&xJPmB&`$H9D7oxRt`v@pKan|!KvFE z>#h*=^p;v;uue#wKv>@e6QKC4;Ol@uG3uWu-2pX%99h^nJh{SmP}w&P)|>FuKA-=I z#r-Izo1@p_I(S9(_dNe!&)RRKTE!hpRDnj_I=xBf42c9Q)0;^m+!1wLu$?qbdZ+{1 z4hX;l6gni+4_N5V=q`hLH25*JO>RPfpgy|NhmW)snuE?7AyY>h2tCcz_F_=958gd8~JzQY)IT zYbqboPc2!pOF1vLr|Sx8BSV$j*zZp3G6{1>5G$iZx=wy_IvkS=@T@!)(mSmzE4408 z0-%J=DT!?Imb5gS$2vdRxNixumT+*4y-5+t{e%|`VxUTNvUQrRgctfyO?2pmHFWT4&NROi{E1NEMuSxU6P3?&*Sqv2xh9AE1Go-&y-#f`r*A}BYG{^n zwQ-*}r+=+jZzhrbuBkNE;n!LN0fkK&TuwXB^9k?* zP|2~R8>J>6wDOHI!St1(4ZEkT@Ns~L)E4<1sg(A{^JH1EfhBtXCrrlS@yelv_`}h8gVEM z(NmD%C>nVzcYUs{BidEqr#Mgg0MlkpAsK907(A|)Z)yv2X`*4!q2WmH3J=k$+K*d# z*!($ovyixDg+cOGRo@ytI8XjQPPp$h(;My%BidWyR1SP~sDu1vP-e~_AF;=DzSi$V zDCGg^)bxH!1-iocKPK`17?VV>uGHs-^1~k#if`^@x>D6!Yh<>C8tRL{KtD0THB<}t zm@X`tDmpncpt(NI6}(?$mP4jBVCxQH-YHz1DL*#AS*}d6%tvEcN;P?1lMZlNt=;W zqoW%d1*a>k3rR@ea$AaH^gsOhIwTt2OdPI)ExI%5+0|CWPGdvBLen@?1T~sY7vIJ- zzZ>L9jUI0B)201VhemeHE7i>8x>6bo7xwRYUp66aUVGDv)Mh?)5O8zWm>E@{7hZXP zIyYyECDa-Dw;E(kS@6BIx_Xf&+jC*qCch;T1dZ^$255lF0x!GZfool06LLyoS>Uh$ zj)J*Yyyu={>&l9DRK%6-Ch+@0@+DyZoAPU@y~Mn#<6}?9>D86P2U}EX3`;nqgW!6t zyABHL4{H)5UX|(MnC0EPW07aJNEjrN3nJ^+r(2k>cO5#qs;bKC>uW83dU){o{{Y*n zhFg|d<(WTw6D08Ui}&c6f~*$fj*gD##0HikR#sP;Q(2`39PXJ(zg(#M5E`3xu!R?X zxyfuXR%wX>`jdcFQ5sdJ*pp9%|EJk9JFcCDN5d%7MKUk_P5mnoJ*=ZQu<2rBV+(Bv zjbawuqlA3@%YZr`{!PudUrR>xD3QnMbm-azRZ^>$Go$>V_fOClNBbq(8V#A27sBzD zgR35+!RAWsK-Fc8p+~ChiG}Z43&+CVbdciZM+4ZljDZw!lXAFmToF`S@IhtPP&Vcx z=48U6N`YEkB+pMmz70UQ^KbiH38Y9+{35ndy3+W(s#(ONFmVbzJ?(zPV;YY6qHf3X zs)!clsz&SF9!oq}eeAaSbD2NmWT7BWu44V%euhmu=$sHN+#OHOj zH#6J+F@)y?P?1=chG_xt1}>r7PMlem+aR)Vm#Nh_QGs)J7P~Fk*AzN3OX4aTm4xp^ zV;iKX<}xxeYHCr&oE<9l=y$Xj6}x zO;3sk2S~4!Zpsw?+!j%;q%fEfNgkd*YQE- zs?uui%FX@UGza&)Imt`7+4Yo?6-z8w(~Y7m{4Uz1J~^pr0ZB~_pqt#Lww2J}x{(}A zcoVe6JhxmU8YF*)kP8z3!a6x!HSE>C2z|M5$aBvJoIv3{I;C^pa!7NU7Vb9~lCOl! zE78Lp*kvEdk1_SuP<8qY>YH}oPZ!_I%JZ+IdCq?Gd9b_d6b#%RFVgF^-DLi^C!fXp z2uPFOfKNwLrhWk_4o|{5J@-nY*>&tG-GRgaqm(ks^`*J%wsMTI+Y@j!?St$;OK$=h z4IhOdF5QlK)(GuU7o=zL7{(o`@tSS=#t(OT*;;4omsbP;tC zyQvpyBvd6`9#o>HO0J8GS!dmahH3S?^-qWG^(DM+tvAc$|8+182&r}egAj<2zZV0U zeO$Ya%hipyJD|{We=_s=dE?!Ct;GR|?EOMzg_-~A?`UkiBIum--EU-vmIkBuPfK;+ zSF59AhPI1dMqrfsf4!YmR8~>5Sih9$|~=O&shz;r3Go zkSVJ$R&9zpGL*@e%4}rGG8pK{#019^rF&%GvZdk2%5kw0Xbhgz3t!w^?D*9 z2K3*$n4aKu*aqsGA!sy0F|bv(&+9Kw%S_}p|C0+?-y8zk1OK4=r8=_=j~i7&dB|ix z3pd$NavKr0MJFc^^I!wh(b3USySEguwTqDZSWa^GZ@Ex zvhwg~op}dS(|0Y>57Q#F6+WppkTU{prl9P+*5Srl$waXEj8QR4dvyh!RBhOjp2MJ26z4U+?->N-mq#4Re5Ml zl|U~Z>`KQETY~MFlT6W%Af@TK`N$T*{Rs6#X>8r*-)Ri71UiTg@IK=FiHb-CHlgl2 zhXol=YqxE;QSwp-gO5}}N7o-m0a|4zJxrSo+QaMVSo<3w%gm<& zolIdIhEW@6S}^{X(j(og9@BucqqM`_qtX_R%@(TYd565U zT>xw!F}36a8G85!l*N2cmo|wx((AlJ?HLt+QLEzf7rO7pDHHYqKzq1BlTl9~0-^ZU z0o_1EHYDH>N0Z>oXuIsjRTiXkTP)SS_5@?C-wEmK=g1Kk8CjW}N=}`g%R#e(3&DkzarLKd)TomGJZ%6YokUxqr#X(pGD=JydSDy>56u ztMGE14r~9tYa~_AT=Am)@`vZF{q{^@!$PGY;Nq*(Nhm=?;?&~WgIC2uUrHPsUi7hVv_1UUw^6|JM21M(w6y~an|pf)dS8v30o8Dr z@7uoUx78ANooMcN%_}u{N(9_77U7dJSR7mC@dYxDh*_bWP}ly9#zdY`d&iu1c&{p@|Sq>^(o=cW2kn>)jn|cI& z)ol-PG+tl{eMqVBIt4hx)rNKV?W6X`M+crePqRzn@(h;|xK%}E`LJ+yoDVCA3Bkma zMhaWtK~2kOE60gSWAlVpXyTkcBBQ|GmrLz_31Urw*VU~-%MlrLY>UwYWA<|ocgb)} zcwOYV0QyM7ey+a9RuD;evgg+8+vSzW2)fmbYz{#&3Wv>{74e`0&-c~dl|ZmMI(|$6 z4-TIeldWM!|6%SZbNNlYF`hU#z$tC_hb6JvY`rR-{?e1Z;%8OcJ)Z!+1eIEY)!|41 zbu?7f@(b=SdZAzZ_=6pHI zlB530ExKPE_l!@vt<)u0VsGZYY#M(VZr5lw7_8QQd6*Z%QXeVcW9;m0RQXwS$1tR8 z2DORxQm3nvx`xT}sVady{tIpitZX91gO~fCD6gl8m!knRmiqdA0xN!TtPJCHx6Ys5 z{26!CuqDil4QTk!>F#HOH1e&^yUCfwH{s3S8gD!MgSD2V=Xb>3dKDEvL}vtblS^GV zjYC9mKdqcJ>{BKFTidd~{#hQK5#r+xg6CER2d<3ymmT9_r3xCzr0k5n`4r3h(dqH= zu^DDYr=1+yl#p(pj5ETR#U;}3Ij0|!$hpHPbd9q&HYVB+s3aaNz3*ykdjlx-JCKD^ z7PAQRp&p|XlI@=r1KmQ-+aQyuQ<(6`gY&582BwH|J`P~a2NohFmtD;ppc+}Qbk*_T0Z813t4IXJ2#XN&sTC`z>|+Pe?>0?^0dk067mRQ z%p$sxev=)VxZFhKBVCss%uIYwKk}y1Z>)+D3%*AB1$xKkG>btkby|}NTvf=9veblT zjPbJxf5kcsUOX&h<8%hv>XuxRvB@~(EAnZ&#pNHjeqUh*gL4E&9|@o6c^ptid`IHh z#GA$JmVLkqa|LnpH_b@hg9+ZS%NneN(I2@en7f+PI)5!?5>};`OJgIOQ+&4Eg=SF| z@}(C2s27*k@!R3}i-@lJ*dNNTxd(8;O=KA@OICeM?zXUq)bpez*-JiuuM?-oSjvl9 zD2(ym#vh{uNX@~W$?0h&&S_{yOSLa?8;_|J;rXT zb@?u(z$Qh18vCA1Plg0bApMb8O$}_{$LLk`x4$z^t|)7-PfSkEE+%a!!rnpi1$d)u z2t&Z-(o`+IW>aw%`k`5(B#`XXdL*Erlx7t)`-;;Y>N6Rp$V~#)Vu+S^UU8M zGw?~lC8wki<>CABZP6ALGU(&cgdpFQ)+{f4b9(lnV>X~NV{JDJo`;>_)LaCd(Z+tNAZmFlD(^KE|F zgCROZs-CSYjGq+UZ&s@t=i_S?Fr_L5#Vq)z5RdwK3ny6--j3S2TnCc(qGXDBTRR5w z@-c895R0tUMcg7y5Xr~+(;}Vm3B;}Eq=T&9H_?NJ5)^Sn3SVza(W{o~q}c!#=rUV2 zVunov$j}~_;1%B>>%9B8b&*5T*jRhmu>>FAZcE+>9O+^D^lNYYv&`=4yoNB`NR0}? zuNH-ZItE4-xy71Ry64N4`^odi9U-k{&b0TG$OJo*3ebOu67m=no7|%qQiUHW1;1vK zCis)p=*|;YJv|O14%76{{~bcka5lRdicQuyiF1G-GQMxghUzb78CPnQiz)Igj~(=u z%vF!bx|Bn6o;$&FalM#`j$8AaR<@1&lNHYyvkh2wmbY@_pNO`HH<8N_qh?lPib zkv(!V4{&_cX1lNLD!_po0Pzv5*tSpqE{G-lG43Km0;ATI4fqn* zxYwSlOMSFbEj)F_+JOZR2>C+M>E2~E=H%#0$Mm~y&7}=Tf742uh?y0ZCcU2QO^`PR zNiep9C~Km%AzS%}_oV0!ywx-mO%fkrW=PTARy$ajnK7U>e?14uEuE+fJ@GUphQ_*3 z;}Jp0g;V>DluTXOBK9;sl9b9ax}(}T9Y)3#6cm?N{0O-u1xZwfcr`n zMRN3ii}u74_r2(UIWp+XoDM6;1`aie3nhe2Y6oQvS}a6M;ks+N^fg-rh^#KtYhf4y zc!VLJ@N)Osh`*`hRDJuX8yo#d4$TH*E=DGgx>lqe?7oPVW39b;<0efO#0*3 zp4Go2&D}c&Q%3*3lZ7MB+HL7o;WwmQwiH-+D^iN{=Le9mBrwL&k!NNn6kK@FNH8q9 zv^lmduD0}T=1TLHJ=K~9QWq!j^YFnZ&U~U6L@UeT3?4Wyy!khf05vq|UQW6;^L}X} z9PRiW6=hvRLqc%hwO#cud2WfFRD;jrcX#pemG^kZ4ZCba2e`~%SF?|)wRPcR-XyM9@)k>pm>ANK6 zxzFFjOidW!O6dDKG7il=G$DBCLdwhNT29=G416h^21AN=_y&gjCe~smjJsyby~0Qa zZyt9NizfpV#x2>FskU@?wU!$xYcY#fSP0%*jRYwFVbn?Hodx~ml8bRLNLJ&^%)}2g zpCOdwD%bgzt?lykBFl^|?Ec(A{P^%WXu8g(1DQ%*KJ6>F!T0`1UbD5d<@%OU))z@L zo{%Y8wZQK~MEf&+x@h0A=30X%N>*>A=01HNB|9|wpIm@GKLp|#*r6U#at<>@d)<@c zRj4~)e5fpYOf4*#O55dAWB(}XnM?d_!flEA2KXl^4E&3ljK~djM(^$QiERmdG&P~f z*nTGnahW5hI46Mp$C2oSbCKqLPP;M88C7Ui3tlW<&bdbLSkpWB*6jG{A!-q`<|Rzo zXNj3{>|?00uYF|`IeFfaNd$pLiG{KbTyIxkhNmRvLcJhq>Rn59Zyuo0K;{e=dSZ}Y0TT2 z+*nEf`!V>M|X*liYkgNh#ELo#A<0`a`0oZQTINZ*v^V*vrlacmJ^M4Rd=6Xwp0Mt z8p?PB#+AsPS6bn7Uhl;;D0>3-g4M9%o0j`q(D_iJQ~?;Ao5tnzowaTEqgGQaFPq<< zbwN_itL4~o3M8VfEG!gRFGDy64wP92bjFsj5g#_ z11#mGG=aH$-K~UrAR2(!^_a1M$v0{4&2G(4F?qC@y1Mz^v-(V8L3divvlbdot`Z`ZGHQN1z5F`%`T81Brn4eVc$c z);SfshN@L1oDpiz35I__>rS*d>G-QxRhhc*CpmJ(7$I8tLY!j$kN_jPq2te_4W2sY z@OOTy!3MZ#!KG9`OxOrhM(@03gX|qpcX0KZ|8+i6ZL`MSR3c1u>T2_CDXaZfE@?P* zd~ux;CF!iGXt@Z!DfIz$HHVuJ8e7ezN~JF$L1V@0_#q2Hm%;&#g@$*m3&hopEml32#cAO7C8Q4c;U{!xVd z+uupw31JuZUSTejj?ygIQ1AGzWn$LaduJON1dXtNTQqOvlw?Ubh@?s;%MCF%5zuav5cP&$ch zDl^&RniBWVm&l5%elx{G8`5KOUT^r0wUQ(lw9aikHn;6|b($sx}JB4ms6;mg05 z=NOfL#U?Q8(@w&q630RbP+*S1piUsyvISneVr31vsJn3_!MYp|P zk=nq%>URksd?xkb078aHSc6OC;5v&?o9yz;}E=uzV z1vQS7T^R!&40G47$cctw=HaN{bK>ZkX-+m2J{+A;tkV&l|iT%o>g_+jv-7 za^nwA^?)x90A~Z&H8b8V>l)uyV4N z&2{q)cBK}kd@)9eB&wdmCKl%ABN(?-kc)q8JAb}~*wDTYm?c(GI*GC{y$srZYbE^} zA^4cqL=*Ny730dkS>GoKC;JNP6IYKp*y`zDlc>o>BUXOYZYrzbA)kA(Y7hZZgVkgDw_Y4d)b3hD=96{cZI zH0HN0VS?K&edvLLvUBVe(Bi#(Z9B#u$5awnZaMZ<3KrWGPA5?ze(-J_xS!g)TqOD6 z)j2}QV`%2pSr|*dqLh@3zAgDOT6TJ+d)$)$+wB=AC6D1Waf5Sbd1j`E1QV|8@|+3l z8**%^!if4){-M&{S)GQw3$dH|~8shNLqnTEcnaH}!G&&3^HwsR* zbfNv-(*4vC2+SxN0-_L>bn(Z9qH0s3OEt~1Ps{C18!b8=CGsYe?fu~_dD#<0(MqP~ z_HoaVT{uo8erd7)@_DNVZAVOEW1(B;NPkkm);KNE@ja(XsF50Li*l1%l z9uwb!vtU}!lFj++Z`r9@X9;Z{DZ|MgMJrVr(d`VS>u<9XGuO$&t8SAWP}vsNZO7H% zEmg0^)FSxM9~5eON|$Xps6f7ESzb$7w%q*71V?$qFZ$SFC}P*e6IOfgMj~6yhVyu% zGD9zeXk{qLEs28S-F_^~wGw`mF$K}e8q)dUd?WU$e)GIlNe+-rEPSif7HM2nGcqGP z5tP-l!E@%SS#zv=A7^UmX4NvgAD@ruY1qj4@t4J<@U6Ygw|()p%TLwnRS`&*d5Mc< zRg(1`ijU;O^;%PlN{j7rq5%!9it{@|L)ZKTza6X>tg6NlE%Ri^y6bid$|&Eqri)rr zjQ-qrS(e*Z8m{1i?p;nl_pE)DDzxip6R-Fk{{B3K&_Vv>=VC~HGU#K_ycAG&=em5% zBa`k>{3>YtqU)hq)zRLtcYEMK*L8c%!U!~08OyYhOKrHli=X`R}?kGSKg zYwD0MD^e6=AI;0S?JTz__NhQ)g_aI4|n3{6$r`Ck@cKvoR6DLBtA2Emj zGr<-s5m;|eo^U*rj2>!QKDcl9n9C|*dp5vSRz`&#fy0qsRu*@ufzi9_cDa*}*adbO zO&Vhq=a!TziL2U5j_|FGzsc3fQA4Ny{fr3Q4npeFc7DF6h^I0$Gaby8kAgPCOc_Y9 z>0#3E59K}{VTh+vjXpmjM}c8dRP=YJPLXn(t6^7VTz2P=S%~c>)&|~^AElCOoj3WW zi2U8lDfBfuTsZw9)`e)5V36s=pF?`>$#-J@?H2gt-VL(+)8?ceaB#2B$7RGbZ6{G%?~CRh4G#}@GenDx=Ds>MS_tVJU;a|-h1LEHTqHV=oe zYi{FhVcBGA*im#`$yoAzka^=F;h`aUXN+Vsy=Ypj?h6w{A!s%peU0ab*+zOb`?Px$ zkee~;19&LnH}A%e*FsFDS(<{yVu+b}HyIra4 zoJJ;vwQc_jf@%fV&W3NmCyZ+QLA^_valc%aq}sggpq>84XDD}+)R@N~wpz4WtE?I0 zyM=ENcU0;$mDRhIk0Hm=bCb={E>^NvrZ`H8Tyjyx33jGUd@R)E_QI6SQZmUzT$+{h z@`vxj96I^`LAr5m!gJn*21A=%9qc(xw*Mr(|#Qlj8W`4?BMr-w`cW`x=qM~JLYKmT`<0mM6 z{>q&zQ!jWTUg_lr%yrSRI6AUS7K6krpt47mvhIS()H zU=*ImrEFl{JF4V!vAVxVX9|Rooc171w%s4$_3yMHPNCWKg@q9J~e0vpPJC3xB-^=ycx|Id#WLhfD+H|mTVM;_A1}pRw zEk4G*Agx<=O3%?oFDBLpxxzPp{kK$!nh?cE0I8l6G8G=CKgb70V1;%~eJl-nML?1{ zI~2fdKwx3A#X!qz$i$8P!EohPwyiE{C77QaBr(1-Tb&t!WLhNOp6<8wU#xUo{e#Ef zl-ZVF-v;lJYc|o*XHRZoy4I-sv{X!)tv$0;4V^_hKigSBAPiShR&;b?vMv48S)+mb zA55VJ$3+q+1obH5r;o83ckwKv<^JVIDd+6S z$`-e{EHJXqVZJMY3jLNl(h3BRn-W09Rwv?t48z8aAvbMWEueZ)S2yc!`}Qy@q2rE? z_e)S@27tGOT|3;5h0AgGCp{$pcuwq{F<_WYVr)mX(}XD~OE`#|XKn#g=#o3sL*p04 zOQJnGMX>-P+aX@!R05WJPwq0a{5+DRg{^Ah9;|VYU)@%!!bk#c+XKT%RFrXMp!1?lWS3BeD~wzJRk!qyOptKDP+^1Hx-5%=TLE|>X2 z<#q&5dMt383^DSR7C4#A5zerGgvNd~c!|C?8c%-$Mh((Q^t+Ya@NS^$EE;AO0FM(q z(PL0D}MvRz=EEi{m&$rJzaE*zJVkXiQnabx|<&DyWPYh zXkidvr1^b-ukzCvkCF#y{eifFS`Wwm60`wugV?%Q=t3GFNE^JfnP^n2{W3r{{Egp( z_Tv^>Y=Tb=W%dC;PxV}9fYNT$PyAQ!29Xu)$Ryw@p(%SV;hs}Y{k5|bT&PRX>No! zg2zvefGr9)a78?8xsCIj2r+m968e%4JH{m( zkD1-&{aV_?Tw&wM>~ZefQOLR#?y(h0UR0hobUMn;$XDsLAus0a2o2u{gOvW*O3A zZh9}3l_8J!is&h=S_-(qWvay>6kj9Vd-cz#RSco%`(?aq7@pKS{Zd5H7|k$)C14HA z66M&_dl$YV6e4{f_slD?L*#1$_JpFrKKwwf=A zVv_=69Jtlmod|VKYEk%B4T>i1X!leet7YQVZO2VCgIw>;#DO3Jx^G3}7EE=|8*5O@ zHof`Y=M2m9xcS*-n3mpLWX$8ZE4bwl(x#dCi-ttb)* z%O-QVaUtu@gl|)8li@UtmqW;hN^jrf56n#2Wr9wjVz(Q<@H-AHaD~Qt4rgpYRMU0I z88t%dx(2%pR5vGXVfMn zBa?f@wM2jx6MNaO0zA1n$zSQMGm(3yR(OeIPy_;K{Ufv4D2qgeDQCY%L`Ie`(n%*| zBQ*t?;hNF=?(h-cgUR1sxD*-Ldn(6jy$j4p39|)qeULYh%Lx&rqTl|;Mnu)rtmFOa z?3c6N3s8q<5CN;i3( zlaQTN;hZyozs+C(jNqvFsy8x^(MTfDezYs`M&1=lA4F{Oy1psW=H!r0h*rbL0$Hu` z3XKt8XGVQQGJ+>rXa)EkiUJat2mIX+w-=&-bWDp|@ss4jkrbJX79lG5r|n;RF+8tQ zg|=E2Ihn{zrFSN9Z4SmmBssXBC}n$qOJAJdn<@t11AjEFz~B%p3~}^g7nriZ)WV;D z-tueMSsqSjCrrrg>MDm-I)Ds;N0g2a1H;VJoG>I7x4<8Jy12Jq&cnnsp<)Qo;g736 zi#4jb%ubXA$sIUUKu=(qnKV~gb8BlW_m{3SnDs+_r2IPfcTthtrh`e*OnfW;XJjd9X_J{CmwMZwNSxU9X5ibv938KbSD8Dk>4;(2{h$g32 zvP*1*pi-l=8_;T6f=;MNiO-xmQ$T>14*2bJ?gyWzL?(7~KLibr?dGn>x*|Z+;X#%8 zx)@?HrFYpOBpK6|L>-fprjQ(-P&LVXp8?jfz;-d<=>Aw|*o375~{M-v_xc&Pp` zIb)JN_V}j6SG=V&l`D!JgE{WgGx(Er?4g4yu(_AjUf(l2ROC1{i(+WE%A8?%W<_rL{dnrk3Ix$ z1M{wuYCon+X8z>cJ5LUp;Qf1F&YP9h%T-5LhVer~dP|Xlsm$Vsid-O-J!ZqIBNk*7 zUC>gZ5_cK;1XpG>OVAqqw;4EoUkt&$chRmuq8XVc+hr|ryv4~h0vXDW9N8Hg<($5b7&Y% z4zD#g?}tggzU0JY@?f8=#YFmfaF}MXc18_Sp3i1@;g?V6q+-FgP&PS!l9(8cN;%*#<@)L(-GshgKq}5(n*j` zA&h=QrBYS3(ALF@wt(>S{b+S!VAz@Um9fiz z%hWiP41x)@XU^(}R_od9W{!}y`=Md=pWQ>K77eAqEqlf5*3X=Qh<~uwA5rJ|14*S@ zY2zs38*xVr@ame+o4>hShG;hhFeV8wWEhTFQbv{(YkO=tHj&<3t}w9Yv*$Xr0e`6JUr_1sX0s z7G2Fu8)vEI#mjhbUY}&>1mkrJYdH3j^uWqN$}kX(&oDzEV#?(NOXrbNvVYsrRw~3L zdv83KmWfsTB(D8{xEpO!bnk88QiRrsHpI{I_tiGhJ(DrI%v9lytN`PUsvdi3irEej24(ao8d&&~lkI{&Iw2OKRTY$#19rZ#UzP5ann5AXM67vfd7w zm{#PF<6dx7m<9cAplOS6uuz@+c&cipISNCrAWiF%Rv=(yPS6_kbnTXK1h4r<@QjLW zGkIM~l6&|0?k$baImSxrZBcP~-&r=hcy)fGb2rJbT$uG!$Ec-S%EvHA2=1fo$k_NpV5t%98J^A*!7_@?t zJmRgv0Feia;CG+=L{0=YI`ZbXVkduQlIk>)c7AcnEJsr?Wk}YRN3WxN5oDst(jtc~ zry~!f{WHWYL7t#o&lVHDP;*2uNk=w3p^_6$8Hg0357{1BhYf2II7n&N>5+^sx)t-b zqL}Z4V=Av-Y#yc}$+8OWzouNG0b~j7Jo8CWj6ZVs(ON{d(L}2FW^~`#T}7KsFk`(i z?uq6aT~mS#YmMG0k>3(_xGH7Dpg$7vHK--m(qRU3{#yOTZRH*)`Q4xU(Z$2hGVt-U zqc0&QCd=spEjhK@Q`}Ku;@{D>Oc1k6DZ|OH+H^<~3>S=ema#T0N+`mv$o(d=jr^^l z*FO}NjpZJPnD;-q0PvYVwOl+Z4PBXX!t}gfXtcgfgYul7tnIwG{O@UaZgx}r6dzh$LS ztAcZS$LQOYeaIWH*p@!wVIoSCc_1RJlAunjp~M<>hqBbaW2z4dvTwdR4AS@7B@Bu# zn=f!_RW`~d#7DmRxE#%094b*S##v&I$hWVWJYW_j-(c1qXuQ7>r?0NVkNpEZawD}+ zHCIvQ&|d3YL{bXPS_s*E`cT0}pma)4ajyPMEIRwGm|?DYOdwo&ot2;!@40Mu1i{K` zNULsvsx~e(p{18W_=T=;os>c-{Q5aW-k3k_6Oqj~9C+9UdO}M2t zvr3s69UP%Yr2p^)mV&o&; zh;x=~-kxyv0$~+sT-*aNzd=G+o4&%~xm*z$2h!D&i+FS0iSKf%?3$TRw&{61pJJ9+ z3(_#5Jwl3@!emM&IwGM8hJJd?XO%{X3UoFz{u%bsV;*eoP zwVYMrdL4`<$c{Aiie%XA$9%~%sr}zRH?wcMW1W_UU4O8Ldb?#%{QFDh13mZmCq3b% z+Uv{(N%f;(8yDdwg9d?O$=qlIr@-@+Az=QV^ zxB4qLBZh~RfYV~?cpf(!i`XF;GPP_U5nE(=BRxYim3M$*QWCNwu$t#DtSFw1D$@5^ zF-k4LK#MCaX0V(=QB%$>j;g1;(@{h+*DTjoRARuvt?OBfjX1rUT#?_^$TPajZy9b2qgD zB)H|VBPkLng6xP?hUBq<`q?N58G8fSIzguC*^mkQGeMZj`Qk@#$=*ujpB$=wdqj&w zE6^hj4Ase9i0wshz1zVZrD(l)R8v06ivFp<{#URXlNvRqEH059!y8eOk8is8rLtvQ zdwb+^4N7aqCQ6jr=cuS;XB1aOiD!_a&!99 zA3CI;p~+?yyCTRP@Kq^npj(vAb%zcVS#drM6XD|&Eg|*#=r6B^w}x6j4e=~@@Y6`4 zG$+gP5{Ig2Zz>oEU6*%=HEN-&OIAl&i&uSv?Aw)VXbu0Jca<{u$bv^-^lpYC+7KJK zK7(Sxq!mA*d%Bnn=_U6)of{j$g4fy%76hcVHpN zFU3STM%2=L_2K;-f8-sJY6Of3aoQlDhLFlJs6LAk&uQocR(CA5Dr?Gze2xDb$6_F) z+RU#OM>(xF8D^|12mh_-#1;Q`fZdwnuTq7C1eO2yU3ZO^404WR8U88KE&@F>Nz!im zQJo#8E{bugmW$NylK8R#Dq(M9pq)`|(itbwE^+;okdVe%;_3FdVhEZGe#QO#5!M+L zz@9{1_+(;~({K7G@TTQ^{Xdi&`Zzu!LK)zwm*C@O|=63Yll8_~5HAYmU zzUnTTJ${M^WM4l^0e_oCWunAB8OJmsdPT95o~>wjUQ`Kt|uB zd|eTx7?ag#{*-J|)mr`6N&#M{c*Z_ND{oCXyR3Ys&(%=Ur~Y14zhp@q6(T#hjBYUg zThZ=obAsu{WP61=Hmi98`D)3zv+aRJQ+b03-Q|fwWQlzmNG1BP zRa7C+WU}hZ{n=@2&ft(gAa#&XHm9|RTCx;$Oo6|Uw&hJ!Scs#eY`LlsqDlK=@?l|> z%CmPZti|O+fG`heSM3-J*?mPsN3l7cEnIN~)&2bd59`}|sqq$q;zxBFR6K5+Gn zD3|rMo7c@e+rgKhBLCX1{!l6xX%{9MLu}fcgd$ga4FDZ2Tfr2Z&1A>Z8PAM6DdwUV zju<}9m)slK-xAw9DB@xLB1bcfU&P*O%T*aazh2g_RX=W|NUMf7gDZae@gBcEVL6V_ z^#gIuBS1MLj7z1m+JMAoHTvzdIrKabHtVi`&wy?yo9&4L(%erFucnYd>;zk;-c&9} zmr;|>YW_!=d-4=hi~97j%r6e!Qf!VboI8(E#HIIa)v%AAS2^hFx_1%pOfv8vEA-{< z%`Mig&D3G@O$$rbxRGvB2gm(R3`*W>6CAK4f7$8{`2~kz3o_QAIj&rVGF!S4c#lNz?6Kr%ulW!n_tl{GGqd=nj)e0GI&GRPQ`j-5v(Imet zvifwrORhDR2NckVzqyLwWi)S(@sz7nWgDbDm#H>~C#=Am^qEPym`);-hsC{#~iK_bySQDivzDQQL%y;T7r=OoMZyfJz)}OI& z$gc{4dC|UEjbwEVH%hPG0ziaYtTfX7ooTS%>>?76@8M0>5w4dl^Ij%8j^%F4_0rSR(0{U8tBe3u=<-fRn1 z0}wyTti+@&HXE99Di_rhsQ1IKeF#9)jknTsErDo*>EZ~6VAEK*_VYyoDC_kBBY;qy zX7fe*arQ#gsy;)Wl^`0@_1*%|GhtnM_Xek2`DQ~EBjEikZ+)?Acb{aD{RhZ$eAV6H zJic0gGY&zR|NcHDAS^ru>o8ozP|eRXgeP-@ycx(!8(bYsg3P*xxH#+)B+>;g6jJ}} zpqx75pI6>QXVy5@H{!5wEWnlg3Jw;HTBFt^%H}@R#&QSD0&H${52x>6g+*K9Eh{eC zU?GoyRQylpK@E*RD-?(AZlN~ulAIGG8t5|tzodMXW__BSM7ScLdE8|2pL_HTjDJhS zbM_$BvTefj5`Yfz?RK0r?ovz?8F$4`kn~Z8pLzYwjR{ys!axH<19M|5fY#XfgI7g> z=eUz1RE}bQl70D#b8yE6Gg1V#KUZjCUK6t!%yBSXeonW(es_h0z4`z5`0!PrIs*ID zjk+=S^`g9i4Li79572A|xqT<8O)B&Os=@%K+OvRsGIrOQ1ua6J+D#@DRa0Zl5Uu#PW4XCDLF!!pr{C`1MBt-&_vBQpxI!F zql~|QaX5nfdPDrU)yc4JdJwFSSDNg^^APnYgVmhleHBZTxIjxqCDjEDJq^j^j&0a0 z9c4pj5^EE`qbqTs@=IZ<<;PE$j7C?5VOVq0=sfVNeAsaBuIbyt=!`}4_xZS8By)|R(W($#>pmN6n*!!Q^4>ITG=IZO~ z%gf85k%%?i|MtokNa4`wy>G}IOk=UqqE09&Dk5WNfc($9ZtZcCudZ*T;}*f;9-t3c zz(fVh7#EQ89au=SALfEu{Kr;aJG;w)D1!a*jF%aC>8yq{CbKyZuK;tMI;<|(hZEcX zyfHEaBFG_~l^)(BP@k}YNj$~_xb|2qmOCQ=pfo_@2a8ZJeF$I-0cL7yYFeK6hL+ge z?yT>s&n5nI8;5{a6TvD=Totn;_W(&})||QIsksm~QVT)<6~#R_)c8I5BlU8nuJ7Xc z7s1phlatrmxp8fY`ayGu>r;jd73MN1ea_7)5cGBRG8m2gRLSssFhzGum7#=Fz*GIDOHPY}-MHdnY*KuTmhL;W-pUQi5=%|+*pI`L9?$5OaI2gG&p8uY(Tx8I;Wuf* z8m~_kmgIl0K@XIh|L122U%&e0=|k}U=GgV}`OTY`7yi-m6mT*hUQY(%P4|t{ClBm; R6Y$9!Q9&tzay}iO{{_MyA*%oY diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-2-.png b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-2-.png deleted file mode 100644 index 9a5bd90bd730f3d1aab14aa17125a1ad9b1bf31a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 87935 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

rHqV28HfKfQ_7 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

+ +
+ {}} + /> +
+
) diff --git a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx index a61a968a68..5940f6368c 100644 --- a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx +++ b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx @@ -8,34 +8,33 @@ import { } from "./AutoApproveSettings.visual.fixture" test("matches provided manual snapshot (1)", async ({ mount, page }) => { - const component = await mount() + await mount() await page.evaluate(async () => { await document.fonts.ready await new Promise((resolve) => requestAnimationFrame(() => resolve())) }) - - await expect(component).toHaveScreenshot("screenshot-1-.png") + await expect(page.getByTestId("auto-approve-settings-visual")).toHaveScreenshot("screenshot-1-.png") }) test("matches provided manual snapshot (2)", async ({ mount, page }) => { - const component = await mount() + await mount() await page.evaluate(async () => { await document.fonts.ready await new Promise((resolve) => requestAnimationFrame(() => resolve())) }) - await expect(component).toHaveScreenshot("screenshot-2-.png") + await expect(page.getByTestId("auto-approve-settings-visual")).toHaveScreenshot("screenshot-2-.png") }) test("matches provided manual snapshot (3)", async ({ mount, page }) => { - const component = await mount() + await mount() await page.evaluate(async () => { await document.fonts.ready await new Promise((resolve) => requestAnimationFrame(() => resolve())) }) - await expect(component).toHaveScreenshot("screenshot-3-.png") + await expect(page.getByTestId("auto-approve-settings-visual")).toHaveScreenshot("screenshot-3-.png") }) diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-1-.png b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-1-.png new file mode 100644 index 0000000000000000000000000000000000000000..346f214dbe7e895ce058412183794c33e78cdb2a GIT binary patch literal 93655 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

)HSOjVM`(&bK3kBJt;p#l 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 R09wor>^uB%*&B1OBNYmIy)t149Or z6cJSM$UFlf=qRgqUB)mboCTBpWRDF7h`_*nAtR~fed=zQb&8ZbPI!1+I^NDqp5$9) zZ3LEX-ZFN6Sj)@v0kvP-n%(@2&5I^&EvF>3`HHoMW=pvnmNCkS=u5(de!`@}kbQ9@ z;vrs|Hm0y61FJZx^V=6u-1bjrg9v?y|xzRfUS(W-1Zz+s3e2B!d z`q>O(lX1YTqsOl2Q9Tz%rraR2Kr&CypO2O};R9a|1RQ&#{{_L?SjW@T(a-7j%0AeKBwy_#pyterjKs0$I5hMeLKNTa|8oyz6(J{2am6^9LP8 z%zR_O=bLUeiW1|!;qX1#sBDl z15^|vb$(pr-U@2Q6$msPKM!Gy!B|WCF67$xTQ~C;^_J>`QiSopscnrfSQ7&M9a*Xf zWwCiCYwyc1jldm`@vG5B9Y$?GoJx{hdqrU%t3d;0nI=gxXSo&l_{Bib-CVU+P)HaG z!Heqg-U>Af^Nqsboc@KUe}TtCgMJc!QWg>F?Mijmv(HB^YRa(c+UAogoPUApqW$J_ zllt2_F5_YBe5tM}4@887MEw$f^ZS=YmtkRTo|BK46h8gNx+2sw_c-Z2Uf8k)LgrZ*Xpl zU^SBVsDJc*`PBYRC}iA!?foSCc2d#WL+kyfI!EH;c%c^mZppU#!q)XGw{zb~2#wOX z+QaN|8Sw4k_SQI9H@?;Jl@@9Eud_ejKHZyWQ)<}*D~q z-iFOuOeX`?e?`@A7bS@7(RQ=el}j?`-2~{$Y=_>&Z2Ru_QT2#azi08Jee(MFppjCo zpY`*6>)pP^TyzA9@3DLcqaLF>=v3*HBd4SJ0~(if)aL@BNqs`Ui@*k}z5k{+8Z#xK z#j^T+Ed?J27qoPGiG-Eal+ANJ^6I_J{TXKKY%LqYOG$oi!l1nUMs59f*BzsHJHC5g zkf&5)eErM7#3}0vRW+6G`IsqiSS|dFzE~a?o8=(jXq0_NqwD@oeXC*mY=ywscVVjx zXVUj|qEtHIti*Xs9Umu~O(y`h|Ml51WD5ACfoI&v9j8(IgvrS74orjzp5w3u4H#9R zs|=ABS2)Z?maDwYB#@;6X}k|Gk?7ErkK}#*%lfFbTi&iGGL|UhQMxHm)ND7Jj*lYu zYI^-XK%Nm28ahwwi$~z6*CM?ql^=UcNCm@Kd&hJ1ZgDh6n2f*{?f|Uk6VEsFx-6cJ zT{2a!7<-03b5AYc^8+6G@QT+<22gcDA7_cCA|yk9>*dJ^$~x!8SxqSUrn|bi^G&11 zuID5&fzaP?4#ZNtAay(7IOgB@tbSJZg;-au?R;R!NhwVF2>3ye!CY`zjh8(T~CD`hpT)n*6c5 zU|X1`-uoOMd;nhylyCNXwFQMcKe@2@YDU~iVR|ipkbm|(FtuggYw~0#p$z&;0rrP` zOJn3xl|DsnHjg_j;2YYfY4_@nl2yw>iFICmd+?%i#R*vrh1FY4=dB0JCyUO-a?MO8 z>$^kEU2T?Wi4INK+_nQF=#iL1P;1nZBWC%M*^8*fjLh+8v+B+Kp;2~x0Qx`^czAs} z+K}_lys|zwZdH;KTgWKWy=gV}o@MXnNxiMNl~ZZJuyQrjayA5C3#q(y>E){4i66Oe zh@at%QLV+m<5+SMYqV0Ah}Lz#o{|IE!2-cy>?wyQ>F#qY`P|ID2+AyA;-9&>C~ucr zu9>&@1+@;CyxfGu+n&U)(LM0@&83Pa#!S?DYz z`+cq{%Le<)lG~0j61l&!pXCnC11%Dw_}f~p+EL9?MyJ(tu0PM+lD%^>J=uVY^ui|J zy_;IVV1rnE*Fz~@g?P$)6X|xE5vI=?@STMGptd;K_hV6=G`eBg*=y+GacWr;8l>-^ z8&5wehrHlk0xo3+I^4j&%r?xr-#0}n2&>pTlD6q5N0c`nr(didb@yEngv^J5%N%;Y ztyFd|Tkke@8L+|Hn0_IuI_aDZudo-GE zJ4VN8_JE9mlv2X~+sd&VK<)?-K+)Qq`Ya zvo=I6DEN(5H-Ta%PSxqP>729QAI9vb3@$OOZCDl+V;b4EPgowLD^qx%E;^Ysoq}-h zOBY|9E5exO$!RmliAe@XScsu$c@{I~j=%%#&iLG?)lbA%&X(uUj%-$&Z0BA8$>fn0 zlx1Dqj++=QBRuU|Q<+@OU2IR7!iqLk5ksR*wktI+?*p(hryKxa<)uMJ9cPFM?X)Ac zLg?+R=UD=Yrc;CrN^`0zx(S~@!?et6+6LqM?y>$`9}sfE!AiuDt3rJM;~uL|T|Z$62t#{L-6dPNt_JxtQ4ag5Ko?o%1jB2%CIoMuO z;|T7(TNo#3`D1lijqZ1QHs9~hwBU|e-`+Z<27Cn3+_d(hv6w#ZQID+%6P%Xv*>}Fu zlcLl<+VE0(oNoEM9zb@93~q+bAaqaP)zmQ)sC9$Ch=v7@{#*k*en8)Qdklfi-B0L0 zklAYib;z}!x{aR*wFUM#F2ANER}cF6edxc_cwbzH6wtgLJrR2U<_3*aZ4tJSA!6it z*u3f!;5vtL%8@jD1sYKu-E;kh-5$jHh7JCr;@3*cnyaiu3 za56a$pE2C>6-Kf%?A^O^A3q(}RjyfiIm&jtU;Rc#1&sv73#^%)33+@HgM`*_F|K!( zFpDBKWixU}ncatj<`XApB?7kZo|%DJNj}!Pc=I6CvwkLGk37z!0Ri8e-K2+biL}(8 zZVu01z*;!c4s=1|g{TMB*~_%D5_&D1-kuM;cW7yJ=I6$gCm$#pkq7zGs+Yb_qh1Hu zCmsEvW;2z6*vTZd!3#)lX~>a-UiOpG)oz_P=dZJnI-O^k;{(Su9Sv`h3tQQKA8${? zoI&QyA8J7Tz>GR3?-iDHG^p06+QzXHcLV_y3(z~G|MTJ*wzJUbFEYxKp)dGA!~+A1 zqpNUEFqF*Tups9z6{Q4UbuIf$(pIMkSD*d;sl#REVCP+SgrL%HZW}|kvNw6yr+68uI_>n4r>UrJi1sdeV3=9 zaYw5^M1J|PnD)m0S_?ko%}jKl?etVs1OQY05j8Qf;?nNB#Zu<~5 zOxaBsED7>1V&JlB7Q16HLUHq%*P4)RBd2;OR8|J8XW~;XTL3vhx#IOJm9R(h-xyI` zu~yu+)fA7wgJuU~l&P;Wdtlp;z`8rf&b;14dh2=*sNc>Y2f}aFLUny)cSujhIf~Ea zUYh}Oyfya$EzsF(B%@R%3F!aD1vKrt&JWO_@Js*&e2dVb%~m{k3ETfh6v*fJ_fZ<0f{XG#f)6FZ47#JgH^lD_bHj|C(|4u z$DHpU<&_zjZZ$87Bztq577G5GZZB84&MQEz60eT4`$RRZ(8!^$oFMX76#_wMHT?d_ zCA-y*E0+aI%0abtHK6~;@tr<>^sDCzE_E>vmg=DpcDwA&n7o|J@0RX_z8d=>Y8?h) z_`P^}=w>21$`ypCvpr-HuZNQ%b=qlimzRD$>r?V6r}%0u(E1=JZL0&Zq#|e4PcwnW zom_c-TR!)Zdd`q)uL>J&AzIXwpDZp8;lVH>lS8i4xu9YUyU{rMtu|q|wvf18EQsvK zRN%@OzaG^H;tBsleKp-5ro~%It>X~*fsr$UaeMLT$hn-ghw3q&OvmFMdc-Y1&x_F? zfSek)HQY$;bCVk(x4qEDcUm_D|2+E4O2C6U{iarl#@l-IQvK8lIrZ6cZ;?amLNlHpO8VVP^RP%d%w34X5uy}oCDt?H z+&5-bKL6c_k-uyC?)0c=2w$(9-(NtIKBxO?EBq=-!Odgdr9qb=kC^>jWN5Jy^h{Gb z<@HjYu2#%R4s@vfeR@_>`jQKXLJ?xPHSpTyyK7?tp3Dw&jbRpo{A~6!*2=p-UgK6`)+Y>&z-Xb+Nwg}TusS%<0w&(7n zzlNGL)Re^!A|%Wjbd^vIAw6x)zkIj5O!M>q(jNs`|XaHFHp2LF>u(Xd#2B~Ln z-x&6n7D^&9;Sb@3ggDTy;Bfmy3N2y5&>Hq}8 zE&tX>Mt!$md;bW)ai~MBlK(J^eoE^bmnZ)?MX>E?@c$b$pK|9+sJX(dv2G*_Sm#=FV8hrNfb%7~c zAkg5q8C7Ul(d*MopkiLSpfKz}Up4SmE&Qd}1oe~g;~A7!cna@d-`&*-!K!W3SJ5e; zs5Rn5K-cEz^qL?4!_$*WBMXqwjTKx{IT`UemzVm4lVHEv0iX5)?L^7~T~7%Xho50Q zsf6#l_{0(9M26K8ZS+zwIW4NFw;JW;_w9TPv&6#p*LoMc3q>x8b|XLyG~U2`@TZ*0Z$zA8T;9#b6Q3LJFzlK{jFr}X3)aa z?{6dyyLIUI?MOrXxE1lK>y5W1nq7G=d)&5vCPAV3=m$w&G}A&#uYXoGn@_`FO)JLa z-&Vuc0Js`8rmx(!x%kv*PEB2G=$C3g{=9`lpHg{Vv#Cte}H%?emRIkgK4v#|XBcR);BUZo2r5?2)HY9)q19OOMG3WJDYPZV@En99v zzdbx^C?b*<3}abLO0uFyUt_ml?dU`~uwPA;R~n*ySkRPVJ6QWLAIN?zUwh3!I$M7i z%<}y~iiAR|QsQO45}DC-!A=FYxQ*N)0Wvwp2{C+Jl+DoJSgIb8H(^5t97!)yxwMZt zgjZjb?Hr+7Nc5*#yI=Yg*KLfv99gs5DQNSrscE%&s%KHT_i@v6X-_u6 zC%@kG%pz!An?R536kVUX*=@G9f1grdx1VfONwnQ;upF!UT4ymAsw1Xv`!oFcq+aXll`8Y!c^Y1XHTM1|K;} zqA-xV#`iRG*-T|HL4FqpIU+BLTx)8EgCoUm(=o9}H<=M$qDiAlaW2W;Zd0Ra=qCo0 zHP1L%78NOs=6jJ6edFbVETi3qV}HJa9<9c|{iN|&Z_4?pX^Ct_oy2ky*s@xqqYEom z#6L&zhxs{d8rXEhY|vJG;m_&VPoV^nU21?S!G;xso^&z{Q8J2%SKKmJv_6HX9K$5U z3K$QpbcI7qOjBx+-}g@!S%fuqG{$Tv2xg0srs_!S9ZzzNad{Ol+z`rs9#-RC83osO7DcNGq%xC4b22Eb*&!r)bo2-rFy^H0 z64|BioZ|4EGSN1)!j)CEeeoZZEQ@JIrHSe_E}1bTt#yWrV^PO78v-84ptt`Nkor{=DKCgf4GIb2=U@L{C|TWfCu!SkeeLs4$@wRLhQMYf=1f z_H>YLF&6@b^>eE2p7-7wKbj>eUj8K`=#y zB#~gwqvme;(k*;HM-ZR%bfQ~5D=LqX)YZiRu6cFR+x~h|VayI|P^qV`r4*ZMV!Zv- zacJct`(%`vS_FtRf)_PHnZgtahl0W>RI2CkKXs5wA5ophXRAjaJU*s9hUMzXr{I$K z#xa3ff}1^MU`im@F4TTEXZ|RU}s{qM+aKhSvDX34k*roGOys4GnbI&oUfo3+I2#Lq&SL#|DL>{Y?K#7I9 zMr#iz<#i<0AJ{*?(iSA|Ll>Yjii?K@)rDjpwoPr8zJ3cwqm|O%RB4kd_AYibnfzH2 z!EQI7?ry)KD9#+*W->H}-P2KJB7Ftn89gBU=&g{4CCzslfokM7Xjq7)r29uy|B}kr z+~Yh$0WHOLY>B39;zx$mxLO!JXY8hsHzm*TZ~AOQQGI&M7!@*bO3Py2u-;Rc?1^VB z`oizc>P8#lWTKj@0$Z);5JApLb4+NW+FhHf50lHLo+2fbl93R1g&7g4zSVXm?5r)Y zYkG`W&t?&;b?8|Ys3YiTeS};g$YW3cGH?sqdaVL*>_AFdI)mcNJ4P|~bEJa6^NY4N z+%mfHpw)E7YwaBGwBFKmwMPqQBmysV5yVuL!nerB8l@Wky~Y$knqPiEJaqB`EKB|$ zDpKSy3{&3ML0nwtmGLZ$piP{+IoLEB;Y#G%u|+Gc#hHh0v4(YkGrAGKn=$sNktqoZ z`dI`-bdmXRkaO4!4VPmUwW#2i_TO^DKah^%lex1(#;InBgtH7)w6LXxD>e0E34gbW zmk^GthA-X)%0$09W55Ue|=k1e+GFu7-=+&GV-+S_yNzyZs(Kxn|u+$`6=U zDZxA3)s?bXY$Qyw2-x=;YXMW+tOPfb458nY!YxEXMZOy4zu5k5G-~(b-#*3QaVe>& zBxYstf!bfh5x1eXB1ms2Ic#Z(B)LW|tJmu51Dsf1-I7ym7&fjM2iB2 zA8!IV(yRh}P1}?#Ay{uAZzr!fGp@C@`v}+P z<|0nPYb>R9DHYlhs+`d=ZnQWawHwv)_U5nE--c;s>z9dz>V`5iuo=%RX)U5-mH^qd zr^F)LT)Z6(AU>ARp=+!ea^AMFu#69?Hg;vndE9LK5B?lZZIyj%yPJI2L%7Sg?q_?w z`@;5REBL>-07Beqi?dB?h7FA->nLcRC72xZL3CnNc=kjQyy@eK#WtshS4=mI+DQ(U zrNoSD6G|f%R-9-xoEvtVt$U{I6l~mRpN+1ao~R6lw;a|m=Hs;mT=y#DCBkp&ON*sB z1*q6Xhuuq1rWx)jDH<;bjb0GeV!LGy{|Xiygx71`@3%U`SlBO?WiD|2{+`Q`(t3El zCd^lL?*+{feqsTzU)B%;V`Dx_#lmR*!DazLqWS-KXCLPNzaK~cPa*vOw4Px-q<1QbZdfAL z;hIu#K2RkDi%^lb;hH0c5&6%Galzlx9Vv{Dn*)E(=afhY)lS@4lZw{~fql`9z!Mp3 z2SFDrs~_)DHQU!)ypOR)?B4%o%ofWF{+*-vk(CuoG9>@_q62eU;nrdEcdJLjcdwo( zv#6Q8V(GX_5n+k6EQ(I;#E)d=tRAS*v$u*=WCkbwr&Gesk5S&p&VNaMotO7VMi{zh z2rV14i3ALi>k=Wa$NKL)OiT<0)zBM{VZ#amox(j+Ow6KEh4B|pfjf!{g@HfC*+Mx> zAyx0577N}<>=Q5X6}fhd;YU!L#He!BmjlrkWt4Dp64gOnx{D9#NP`O4jdoHpeJ4+o2lb5fR{A ztYwX;-WWeHwXY0K3mzDu`xIYTB>(tV$XTs&K6cqcxM|TC5Tjf3DkeJ`1@}W>{?tJM zk-&Z*i@l7-L5O2*5Ya2|pmR64uw2b_;HpD7v9zm93UHI-DRt~{B~-r=WEtX#4SvUaPZugQO3`Pu;L?uj3ac6 z=)dgI6PHT!`^ZT2W-Z9?KMI+5-lkk`9ZpGOA!ggG_C z&WR=m={2r~%jhm^Biz%^skp26OMB_&j-n{^4AUD1ZQP_2aY}{N52SQ7E3EjQHjz5{ z?a(IOlZtld=16B5j{& z=mfYN&`c;S0Q_5+$mHmCk_xTt@p>2B@!lP_pl|>$pUcM^nH;|sU<$z5E03x0ULYpx z$6&$n0|75zfznrRHtU5^ti2w00hacG(wLMAtrcCx1JQsEnuk5BgQN=m^!51w>wlBe zx~G})lW$_}Ov#A@|$%MCe#nUehP%0)uJ(o*ThOOxbn@| zz8wTugq?UP>beD&xhI~o#!?>rpxAcpV&@92dzF%r9abgNa)r|#wbdg#+aFarNlA2Fe;(^5 zD{B`9C&6sQ@=3L+5iH?UmiN1h=Qb+Y6Jt`4v>aIy;$#QORhfC$B$a;-*bXk{+L->X zuAK>kV^b1r7A_>VjgqYjD;&itv;q|s+Jt!IlI2NkhFw8t_|q->C@ViA+xbcSmZFx8 zrhcA~Vi$#xAAhm0lKmE)8HTw6LAuRBRhZU{%PD?53 zsUMRf#LOf63f9&fYc{L%R(tdV7%a86HY~NC2wb5G5>!ZxfTw?aio;Oaf&#Ew{bK;g zA&F+WBCTGf-_~$_3q&$xt6b4mT=N!1gM?lBq?NK9OxCw9qW4}m%VX3m>rya2xPk3f z_Jw{LR8SFblxmWvkA7ZlOO%>#(y9+Fte&j3(9t^Eu8`E1X?1aPfV%kn^mK4+88>kI zJAaS99Lgrc25OJh*$6euMCPU+vqh|{z8;#ri!M)nrz?9*!THZN21et#+2wTpSM`g` z=Gtk%D}feoukAn=ytW=WZD?V1&JYkl836q8Pqlnd=g95K)ZglF7}xungxO)$%@ za?K5gXVQvv{jgod>#!~Bss|^M+as@fFMHI6(iFP5sANmaGX-vZ8Mx{02^5XMylsI{ zVp(^xaL4M$v@o{f+jVlxcSN@s40^q*=~Z!-A`ebtk@O0aS7;9EP=GYNoaUele6)oE zaoJCt&!wAW=f(!w)5E9t-0ACaPnr=1c<)cQFu17zeTF=qGUlzpG}gntyXJMvsqK~5 z4uufXRpD^-eka(QJ0HBJP7?6aQbI`hIji0U8PN-5n3w|f-w_No>$p7hE@PwMsC7Ps z-jPKWg`*dZRVg}(uEw?xyB1$w8hR=HDh=H`7jn+@8eJBY_Wap*k!W*PS|W}bS4xPR z=rYx7{s!d`@c7g@9H5d*ufPUY7S(OC1DR?%>~R%2+}(XUCF_6CzTjpWg^lZf;9>XP zD&4C_@pU05xexb9(=v=8AqWZ=87Ec#P>L??xL)2F?0qYKHza3pD#88u4&%G5l`%cq z8#@SROoXzf<*K38;skQ`Fbz6lA}H@KhYSo(I*k-A<6qxeA7%Gf{qxK&{^y3@dvAxv za;Gf58&*YGmHYr34%_@$uNX6>iRPp92u>1(kwYcB;kAyUzItg#6+PKxhXTPhhj-oN zk%-rriq6N(cQ}_Yuyb|I<0-YFrbVQ$sK{Z3^M_+)3Btb-SDcDTNEmZr2{}_bQc&55 zU9C+^K%+Upqvp6jc}9c@nT?3G8A}*Ec44Eupnlda?%q@zgKmObtrzjHBJ{%2?9s7n z4Wd-@zQ0UpR7{b5V~57W?%U@pu%i9V$N!X#f~7KFRsH{1FZ#cZ^8Tx8HIOz=VtNBg zz0Sb!H*o5ri!Mwn7Vr2N|Bja6Wk}yt$vpkl*CH8 z*QLxJ2Wiyy(W~bBV~L4*=XL$BwjEg`^mH^@RIo?)hyk_l4oT4|x;m*vLd>T}py`Yn zA@rbZFF0R4%(j=KT-8g})gPzQb)jvYWEhZ_v9QHUk0g?V|961m_!*=Ka{dS$8-DqZ zqRP?P{vQw9LExEFWz%*vB2w|W!z#+2HH&EJ>PmS%=!gSD9??Z*L4bS21JWrpX=-ta zu=C|&{nP@_a=2Q8-SyJN^gh)}lWW%J`JRaCWhFA~Q>o;1{*8S23C%_&VWWJ66|ES2 zezzX}vvlYD3tEQx5}~Bi&cAa&cWM974)UPQ%FjKhS9I7gc?~)hbGB7GAEC0>!j+f!6SjQ+UjFUbX1Y@IdqJQ4$K|((ju%}y=g+E{85{at zHsFV&{;(t_ezTY;vr)O-v3rOH{-49kUIY}Xl*4kHB*F{UcBmO_980RHr45z)Qp@2( z;lOERDfg$oL3lSbSN)Nfr1YZBHdu7mriJ+iiWoG|_-yP;=Vj&~>+b>iq>9nY_bb|Z z`QP{;*^b^HmQgEb$y97gfU41?mO70E zud7Z%FW+^l%u5>Cf#Twz*~?Sgin1xVsM3{JQC3Fd^D-0d18+jt>A>K;_+3@Y4QPC6 z__@&N&d2CYf{6P&>TFo(={dL*Dc77XXFPSM0oExhz~EgBSviw{O0#?OW;A33Kq>;h zGy=%ZfnPpFqxlgyI&bx3MW!;U4ZicjKt7loM_|3&J@&CuKd0LA2m1h8bai)e6R{1- z&<@h0?wHp#a9M#gVFPpCUwwafZkbkkT2&8i`VKkcN3eAU1Jb2}dwE=M z8OOeZhp>=vOMy~^4ckVAyhJ0r>yb6Gll!Slv}$=a92>T_YgCjM4yF5J>ahWSn{C-y z(g031W*p}YGK+6)CN2&tst{Y+GD=+EywpMQK(NzPJ81_i<7Ea-BTbz zbB{E(wrz#N%5O38CMBF%w33>U9`3RKKvLt4O3t*AVT!%@GOXQS1|8}0}OYdrat-=vKt+&&+i?Yt77sFgMs+$}Q^2)8(<72%XlWRuRmA%RRiGBi3 zr+}sJ1s&$2VseC|Qqfjca3)MEupKiWI|%;S%b_zx+m_O_T7`;(%d-+0h|;ur$u(^F z?+$7YoZoh!u-Nk)4`9@ZU_}wV<)Po*1wZ;miW-4>NtL{gEE+4=%zY+(-DUiryS%oh z>>Q7d`IrKC3RWe36(1+t#cb?KTfKl(ZT4N?>T`)HCy>wAG;|+1UjG4hc&l=p57L+E- z85`K$5-M2tevOtgyV2#SgxbQrym&{lp5-<3dQZuu#0kBM{#>{w-DSOwRIJ5aowFYO zMp}oGHHi=^)qu_jkH(K&083trk*eWHwKSY^kf~$7iX}5IV1hY3SzhVONm=PAdIFBP z42{A*-}{sAj1J=@QzAl_1No?lTVJ1qJMm|nY-6yt=lZQFj4K1*ZF7U1IPsbihFp@R zOX@=D==>-mqgvN+kkq+r_)|-!cZ;)k@ZYDDDF6*M1!Q;A*QHrvZO0n2PL9{CxHHJ6 zbt`zh)$YS$A!t?p#QtGa&idBAzFIq|z{Q%3r4xC#YOOY_(rW?S zYe3SJjn2UBs?9vIHpV2a#$Av6XQtC^xe1RiJcH~}Q`WT4(8to)Y>uL8X>ae^EYM6x z2O-EYiyT(_M}OP#EPW{(B+w5V<=NjZL{HfVg#IC(s~uItiGr<~8#D%d(ik}}fTWh; zT)Q`MqPqa&D+^OY3FDBssJOXGRX||~?UDdMo!tX*uT~1L7?Z3*M;}k=e&^jxycwaA z&d*GDxHv~ubzs}%qx+)L`3HWLRb9K{MD5~kZ+ujUhhuJr(>8W=wYqzSUgJr)zWL5# zYK^alI-XNb=e0vpgM+H%AF{I2viO^sPJjTPP74cgKSY(cV;uS9+>Y1h$|OcUoi~^A zOcs^qSAlw0w!y6VjqnIE;NnU!V~AO0u545v=tz$Ac|3;1EtG}jTUEdHzprwz3xW>OlU zl`&ywH}89zqp)}hvZhrkC>4^C#XRG`4isNxY*f9dJpZEmNeHI0zM%z{7MLxdmcvow zimtc-$_+4|&^xHeDz8da%N_pq8TKJ^MRPnscBGzBMyMm~Y=`E*?(cXh_8Up~x9JFjX>g8#t8UUN*XD$~>>m~q`p-uw%#j~uMV;ZT<2 zv#AH>@~P`vC~$^HFAPi%qgJU(%@!s;QZ_a&Vty?gDUV~p^wwhqYH?)Z$nCbw@s1s& z6jF>sQ_*jFC$3WlJ&$HPaZc1bMSRL^L8O`0x~)3+?9&^xj3j*Ow9am8I)2ei zB+SOwc?|`@9-=zGfBfFV!E%sa#L_d-(o@?{OgzEP3a(0%-aU-^gAZYCbBc4C@Ef`U@I)0e$iAq{V=QSS`Lz|JDkF<416 zb%||1gX1j#H=&h8*5I^>wb_3@T8~8;eE?Qkr;UXp{4eWT=*4K`H@*EUwhQe}bOcG2GG*Lu;BpGYsf*rj+}$5+FWE){ls&Rb&M&P8EY7tY;U@ zB4lyuwh;;63vMaqX4e064rxm_57g3gtr=N=L5d^axNdg&7Vn}3aa)^ij51Y&;5I9lXvN6j); z?N+3Tqlq{0+|EZh%l!%GD0pNysmm+_#IS7r#rrjYr?&#`qXT>BnM7Q=|hSN^9XY%WR3P3K~Ui2AytS4*J6@HK0dbf`0aqCS;wY#ITj2tmpi zJ+fEE$z*E*b?L2S+^?bQRmRL2-Mc{(bJ~h10hj4uovcfbz%rRk5fA)*d~hX!Dw*Cyv`M;w)M z4@l03^e$)7vV*<{!##&}xm=uu@XM{opFIyBpu-45T3q#NZiqH#^6iQRm*-!1@X=B8 z(PIoHf-btEo#}&SG;svAL7I`cv`W446(v=KxVFT%bMZ+#K2=-R9N3fYcQNbJwJDkT zuiQsrdl}yo2 zxRzX~OC0q^3+$uDr6WjX->)iU(v}9k!^KYVIn*9>te{gR;x;;@t!}BT&0mV*g}?Ae z{n?w>9K(v*2{WFnpN|VB)J|q^%;tF5G460kauf9m`?Ys&J9o^8=mqs1R-MfXdBVX& z4u3qy9TcgIXDIVk4V29)fEB3b`j|EWQEQbK$+w%ei|6Td0-lz-?TBp4y|HX}q_>eA zxw(7?H50c!O&4vdC$k;&sH48zt8oGteE&f&kEv3O0IBb(E~fKf>gZ9E~dqs z`Q&{FgM@q-+IPI1u|>Bo(|9gyMiOdk!;aJ-Kzn=hUgi!8Pk~48@^4=BHHLOY|E|iI z??Xj8Nipyf$Q~+?Eu`aBLjrS(46ziH!5UMbUm>xiVVODU*(j*dUl|*J82UPCYPl3( zY!Owc!}cW!^+)t;_z#s{(h&rR5Mv^DFj-nvG@s8mKQUk=rzWJ4lrJ^vssu;y;7qPU zN}>?IPtRkvF~R1H>pk-FpFCd&uaL{NFtQTYjqPOT&=Fcy@+=$-UbkmH>-EQ|lnPav zTh&&C9XOH+616oypZ&qyV&mkkDwkGwhds@AF_eoSshHyJ@+0V&wI7#F=CLcvUrdOAG;&nwQ|mAq+WH%bT?$$G(3&W z3>g*N=97dzI;z1`g?fk z->+G?Z$cNl;?h!HWv9~j4YXr95Awo%sttrz(Ra5J*;`5VUj*-6XJSE0g~UVCL_W5v zvOVj&l@Ub~ydoWHK2UMicGpx_==d)#01qk4+NP*a5fani!hM7V!u*v|V__Kk7|q}0 zW`V5nrI2iQ`<>x>l7=NPU5YN7ifH2l72yFQB2HcRLgz%^usX z!yH7~#X|9(*tPtbqm7O|cq+7GXfaI>gL(7f6YucD!BGNvLYObAm|-?^IE1sb8kpZH zp3LMRX8tfpmp;Xs!#@*JEE6$Ke(VS#kUl6W03h;NOjZ`qvf#y^&?_OKH@ECRxJs*f z*`^oDK(lr9#{4~2JQHm;$h&+Cxej}gtbf!F7eL0ozUCX6HF2A-%&HnFZ7!E7$P7P+ zS=4?aue~0m%eN_mOGAfC2^i`npsgd!FldQn8V;HcTxVU$D=eo%_bZsX)PJ zMxy3agp2Zn1MptLj~T25v8b;gM}@L`-oGSDzT!d1Klaavc8 ziPa`KA>Da}Q87nPV1-|L(4UF#=XvpkD+o~`f`0L$sS8J9u85Neb`jy6V-S_L4ulS(>Piq0WL zxj~K@!VGo7!-Uq9#63HA7yas-TDRcW+&L8OD-ykSa1_tW09TgpzCBCsUPPiK(YpV= zq}sBZr%U}Sui|Y2=ENguK&trkS@(VGtF4V%*oFHOX`hhD+jZ3LRGmPGs(`O!M2YmH z@LI{qUg}3+Y&L6g(ak-C2Q(dDcEfzdw^1v$G+7U|B&OP+qHz7+^)x-kJOfyN6Te6^ zUL=kYlto6!&(g&!u={Ab)aFm}V9is0kTqr1g#^|(WS{0`@on*iQMO3wFh|5vlXvOi zA3VHFY*bZXmDarG`S&7|pS6sgHT|p%)TP+=0_lnCZ%bi{1;3QQ2ly42exYC&Ib z)gH=u1j=}#(KALah<-%VUZ*waufQjnR2dPUlYR$OBrhA2&k9TaF(x}8yNO!%i6 z9;{ptcHKh4uX$~J_*v2Yz&#Kp zj{91=+&wI*(b1H=X8a!uYhG)D$#hh9{R9$bwrpnOM-qA+XHdPTpGl?+9R{7}PcEOI zCEtJ^hGp}a%pVA969OX$h|gD*8;cV!ZzzD@SbrP5m;KzeGfw=^(v6tiT;P~CT>_T} z;P*CUizgpmLmYc;1_~(Kzv{mK4P)Akx90SYCgN54i~ncCo@V9WH_X<#JZ#BO$J z?uXw81S1JKY24CcNpp+G&3IS=t!#U`V^r@Lh6RPrgFKgV+VLNR3TDFvOs$%eHF1(@ zW^7GrV!k%QB2`}ud;hhVMhc}W8HwpZS{|25RGu*RC_(T4hqSkhi!0dHyh-pta1HJn zAh>sc5F7#|NN{&|YXZUDB}j*0!5tcR8gDeXyG!HxcFsBXopa|mXFlBdUVGQxy{oHg z{nxXeBE(OLd32q*#n-6f)hLpOYP{xs{!OJVoiSM7$w++2qFkKQa9BFhl2I)Bo_Q`zpS9zP+el(MyZ(18yQ+rO8*BDjE3`;-hb~ieP43F`T zzfohX_G@0fXJ!kApfE+ngwWuD4SYHw<^3OIAznr>^~5|RyS*up{T`F!CUp8>d*cRy zX*I5B+R13c{^R7rw;ZdF??Z48^{DagH^cC0Rpiwp(t$M+g$EZwA0uQeR77)RS92)> zkR!CxkUe^LzQ8UOg?Q4(BF7PKT-M9Nm8i1lV*oL`Uh!hA<$<<5%n#Hld89% zTlrbUKC1E4Wa&X{02L`HoBB+B$K|2d1P=uuV(0nCxsSWISmH9dU#qIyb8l9w=KzUQ zG5KSu($mBZ@W94Bg6-od7(FjRE;t6dp2!@+NyIJMQ8vV4Tyo+(o9A2Fo)KsWeLT&S z?JFLw4Bp;9pr`7SJgILDXKtWb4Z1GPmBgqbW~7a0MU<%vN4$0Jb4O3Gqnx52qJ#z= zXIeVYH4!w2j!vbCO?KhJ19YIJb;kbHF$Hh^rCEV#h3uK&-4aIy^q`X`ASn~X(4;42 z4}GswGeQ?dw!ApwF_8C}Q@?6>=a;aE9lXd(&HExt>^!N|ES$U|@d^p)o0H(Fnym(r za4wIoqS7CBh1HwZ^6YK%2x32w=kF4)9+!?1qK`UiA9aH$yjpd&y_H2%BpdP@t;V3Z z_YeBC{4Uyfu^TRKBu!TB4-w^zvB52{X88(>Cjjh*|RS@^74STg=ZSHQhJeseYDih+cw{lq$kb z`B^+Fs+btv2C6;#%=j{x)zbM_#)rU5G=ujk1*hQU7bc0*TbIg~Qo6sj5gzhd za-$Emar{~BzwY)F)R46efXFTRME<&ta{8QFRotyPq?cRFw(Xa?qHdfdK+9lT) zMDlBQCEOh*ZdlynRKAj}JB5!pIN!1E~c*ccm2}#K*1_PnGBNWZvb|p%gO^xBYfNLF~lflvjM-|i@ojo%BhP? z!9bat-&X~ZS}Sz;JbXRDiFd1D7*-l5R$d{yLHs%;R|bcdT0+A51>y}+NA!qR3O!o= zki4szv8J#Tj<&n6c=+omKvk>)Z`6(M z{<)%D-ni3WV;_p4B@g?JM+Z@QO!;cYA!Fd?kpXx18f{e{$3J3 zNAxt5${E?+b;4Ijbu$py$}#`Wal~|e%<<-n+$s@w_up3E=YW1aEncvYOy$|3SBtM# zopzmt%@ZcJ@{Gn_HbiuEBZ9V0G?f7z!{&0S54NoO_@<)bcTETTgR ziaBvhO9aCM3S~}+1jZt!fGGS+|8a%{Q6V$7M?pr~@REmu4T@fxzbIXlk{YF%i9X>D zfHy=C_{%$qoOe8CHWrwlAieek606U~2G;rrNC*NWTL?GxkxT5H8)r+uAO-NZm~_cN zp+s23J5GV@pKiUtT%jU?79LrYqhX*&pG< zxR$>)2Q3JXzA#kV?u9^dMP7C8U?53)-U@Mv-Hh(KW51&mXc97PdEvp+V4aEB!TVQw zy&=cZhK$jhb0d!VMC7P+N=<_nD05onu?f2^_ZaT*L_9{fcZN4s1e@dluQ=EVx+_u2 zF*s5qLti&VIexxqQVu#pS(I8l6-51(?r8BcTQm?SLUN4*a}mLF)(}F0os$lFx$zpj z0}gP)Lg3kibL!A;W%D&k%tbEG(^Z-v)ConrZg@AUqch8q#PI0+n7(+4;0vCUp|$pmOSZbLIQ&_$->xg?C&pDP=tc zl|b7~5HgHV6-Mj2J?9sP52(kYJfu4aj(WpaWlA`-P30HlSO)Y2)gFdeD$E4vo{pR- z<@pNI^g9;j{lQ#|-h8 zG^|sh^*Ce5^W&*(W0K<}Fg7<~bWOVn)5lVgk7Pn&f0P2c z=0?Rd43X!2Cfas;?POA7v0w0CEPz`x58ZajeftU<4BGWHDQOk;%FeeK^YKdH++um7 z^z|1j5ZEHA>`ZDsCN!<|ol0bpIF%uhEP@lN6_0Cu@QZPe-ALDcInb;Axbuv25d+h3 zZ89sHqR2D)V%0l+dgrFX!Kav-ReW&eL2p|6ZqThCm(3-G+3aQH zT(CWgzNxNpP;&LS<)+k1BR&&645Tx`Ge$*y`(3>y1AnE)xH~SDEGG(QzDZAjL%=1_ z3T1j2LdL0<%<57%m7!H8qd#x_OQ!AoLT@bnWJoc=gHOL{t&N1jLEq?ei@aw}#mchV z_5uel+i>q$Uur>~^hBWz*&NoE+?4h{^2Msx!e&J`4D%XUMYuKRn7Oin3LFd%si4ir z*Lip5uDjNb{Tj(BBxIvZg8kEzi({s+P?pKb9T_x1@sRp@{)R@{iRr5NK-sscrnHDu z53s1rJo=MHb>d#_IoM;Z0rTb!=?p`6Bi0~i5=XycEIw`Q&=wI|tCHJ}?nKhmEq(Jw zhfTZVM~`u`#H_MP{--esd}p`qu3el>h{eL!(T3SiiwUK&E|2LP0y3fiHU)P%iwG?e zDjHMn$0weV^4}M=NV@Mz`BLFczs@#uFo|*~3(mS{$0)@lzIyAq{Cz1fpG6dv4vp{} z*Kcoe4#O`K%rFOwA7aA^K^t2Qu4#(27xL+eM$?qp@bb}8^Zr_z_Wj|1gU~8jcqyjR zZjZB;80nytQp_EfNB!mj$F|%R9$Ua+(WYgWp1madri-rF5>`B~{IJoTueQsf%)#`i@!idN95$(Eu4x0~gg2jgno}Z^ZZkcBJ6|s7&rap5xrL8$s%kXYxKRDU0;zntJs8(46w}= zis}NfdX!4i(Zq%2E!OC zk}n$K<}Pn6Ob(s@BRtk1`M<*BWoA#`DcA;jjY6iQfw`nDmWr?-hJ%s+3$@*)13vaRE8xqr#Y!r*)Qa7J|x#+BPo`yHq7 zFFtAslPTCVrT@4v>KcvFr&t+YHXRE_k`VBJ&h1rMuOaI9<~*%9&fV>F;b~z~&OPR# za3GgtUI#aa6gXczU>=>K%h6ber!vGG^vD8A2VE?xHH_kMHt5$Tt}gFl zjg#WO!Lh2auXcN(WI7Z`OJbxmn(XC!LU@*P&zDqA+;zfQHv(; z`DViFEx_-?g9Eakcbw_XN5>Kwk;G&itDar7LQ=CyT0m7#dI^I!7m&)3rv0wWSdOQg zvbndP^B83m$gwy=LrX1G+%VBjTeKP4rv!|c9nq#1{&*JHjB&<5wG)_Yb{EM-FZNQt z`d0N5n{j@UzG`s%j3H@fq0Bo0tVbm3!_Id9Ny?24)O!hbTYTF-DnRPlri=z@ZHN$C z1@V*Yd1yD2pChM7(%rEyG4iB5r(JN#d49}h|GocGB`r>1X=^*b%y0G*R>NkE1Y%na z#^Yey>XSjazuVQKai?zbR<-_UZV4)bEZP;!!BzT%V=V1H9lhZye|l)C0;I4Wdt8Z2 zsG|rxUz*WC4WAL@>4QZvXbHKM{axCJhP0Y?k&xT)vDZsmImmi72F1n>Xnyqweq4oN zq1bFyt4FEPZeDKuxPA>r)S2uae~)pG+xS~w#W-nf()i50zYCdPGcQTNaNiBXc%YKG ziqW7`BZ!G$%;=>u$fKunmZDSD3UKbdSRNoge{>C71jeM{_s@-Uf73ZUau8X7mjAh5 zbYGx8XdQpV@;6QUHnY|A^?fV8-Fn}$UHiyrc|HpC6$UnFOa=}yT`^WGp9~OV^@rLrY|ZZ2(`g)@IkTgD)K)dKrlgIXuprT%4aZZn zjs1p7H;7nx*;_1J3|Ve9@0AE70#A8#6+vVkVjvPiLzFfl@Of)!FGxKp1P!11vw z_f971!~4Du>yhq;UzJX=ekjklh01NLfBBIQvuiRJ!Q!ZYxam$468_73$sZ(MlfZc| z>vgl8QsG??ZWU~&kX`OmEnhYtw#5i~Mul8_+8bz^(|hi}yw}C`Kk?q^ECMBFLYp^s z2j+gjaH)@&uJdBH?agIMmjHJq3;B9g@#pDCwwbaR_4&%hyo-hlL6&m^p#1y z9TlzK39WoqF&)0Khumen(xHou=x^`#Dt z52u;KW1mazlC|8Sr-S&{q6_v1+st)dkxB8AFAT`v`Hv?s$dBgND_pqFopx;(GRmRP zPZR-`CRBn#X*4S`IOz~iUUsle?Sm_wt}FKJI>vbEsJqeJacTaq43`5SgG0)O?+h-* zyB89rY(q40&}JlxS`^V<6jbbp#I#tE>%o@^qLl$<#Iex-A2IIgC!Um_pAw*gl`{cg zQ72PD9ku|$D8~f|cy5;P&HEf&+d9F(Q|7jeu05-aWb{~-u#MNQmyKtOW{w?fN%FHy zL8tR!!ohyVSxf|xh5i<=N9W#U@~9-#GD`($x;4HG=VjOG{uE<_qp&l5t5}OZ1g=3r zWjx6xP;q&h30YBX!nA5b;Sf)$Y~WjtqR0Cj0Q&V?lcf`6~{?xr(t4 zuX~zOv(k_Vux0Hz`b%NYE8Y6Yk!a7V_vG*1yiXgh*C)?d!_{?Hlun?Fr9tV_`8g>? z*EJh~YZNbe^36nlieSTTefN$3ro5?9^;yUU_3TdUXL#||3ioc7YfBZPwBTc;P)j)w zRe*gAGbRp`N%!gnC~7$}w|o$%%w_=-CM9KhW*xhT^czcnxH{3Og|0oeI7R#* z^D*_&FH|equM)H(ZeJQ=^wR=6f(LN>3OF?sn0(@5x-Dz~=QEDLnd8b z0n2^3)s8F~AvlSW?cWQm2LC~NYdrC;_}wT@=$hLym=F~II>P~1+>&>XnjMRA&CGwp zD7C_#O?B%>Kl<6MT=>|x3L3Kx^+&5*f*0)zi|U5#uR#vjO4FM~H=cgbd2cKTffpi{ zeFCG!xR9R8sg(M{=hS46vDrVV=?Sg0y&Jn8%`M^;s4MB}&cKvi_t%YLh;}3Vv0V0^ zE(R+MiE6E$z1*P4{li*mhPSeN;~rQ2>eVR>&MnIG_`iiW99J(FOW9pNT7c7jlxnAR zocZX9jf@a*-ie=m(yZ|V2YXI;St<;MMOM;Pq_QbM!yy6!e;F+fWXTW6iJQ^L9u7Hc z6vkYteU3O-t*WbwE3#5J7o1IZs|E4YkR9vtM*4DSM7+3KFy2&7Gg&*x(x-God} z|MIxMok+S@TP(EUR5V#!%dAO7M-uf=arr(}aq&(({=5wy0hN1n%$m9xF>M$7isIYR z+Bxyqd-SK(WPZ2wrJ}(b3G4XROr!!D-_=S;A(8>TR%WZ({pgHh`+d2?#Hea_V(z%8 zAVYr!he-?uOonWoH&GDlc$0sxcdEa<``D*rlCktwD=qm5;E?@`6~B+{{{C>8%kCJe zCMsp$P|{F_T){}cg~ES*saR>Zxi|X10BaZi2Y0lns0N;+kn&nn-FH~xme$yGs03yc=-WK0U*G%?2#jc^BW|%9LL3Ig6=b|2y^@nI<|i&ug2rNE(mN7 zwYEMku=>?Yp8g}b@Vt>CyQ3cS`KQ;z>e-!++sJ;>)FI&;%9z5n&nYwi#R6P(iKL{+ zVjj-!$TNGGA>R-URNOxb8jP8AGyz1fPgTHNiIPE?ohcs&>7pnNcw#;^TB2K(KUZ;{ z?wDypd&RZYt{&w)X-xHob^nMO2;dB3(>Xwm_^J>PtEf`c3;Ia$rS z=p9Zh=Po?%69qi21rBai*an@D*xg6JnbOPKEGmb@sPbmhmXR<2qB_-(lj~dGndjpR zkw_}^JeEi`H8Cj;Vl&(0g0=l-n^UjW$;HBDMJHq7d`aJYdPC+gwg4@t>%d3Pe^nzhJ&=Rf9kXi|wQt>ZLcfnkDUj@q zgDCssSBA-p4KIuqada>ScpFZ|4vaMn<{~>eNbXTC4}2Iet0BuvX4f6%8iwq%86Ma| zg(@ym8zU!GI<~x&?#d0=C=`yN=>vZ+T*qo5=#mrR=+0&77zqf)p_Jv3^Mbckxz;|k zcf1Y|86JiRAq;1VP(OH94Q}O0+y;=LU{kuIjo41Zhpl6*v)%?dg868c*Xz8QA#leD zsy&*h?dfV`xdH2UI2&|X?0|Pe%DrIokbCn8J5_Oh#JOporO6;hc;S*U^x`FSeZ#X5_5S^?1_J!XC154^0~V~=-@1v5?$VSa z55M7Bh6|)?I=q?w^4H=2!MPJ)o$QUBbFNcK!c`)d%LUamo%=&^{Pg}04EOXALxEfX zgD6j5I1c_c(|tAuTl}uu99~(6_xKUM2TS~SMe*`atl^iQD69X3v*;XjF*@;E%HFHa zvLr9R>5R1GbjH;?+-&!Gp#f8|!EYDetwDe!Y_~L$9HEg2hD2w#zV;1~XP)H(m9C^T zDz1HFfyt@8s%QxIOfbug)2?^F?#Vv@0(3?x?&B!~SK-b-ju!!QsIkH=<(t@!dQ9Bo z7<#0!bP~)jzb(8r=#f?TtPMUml!m(!HS%;p>Ckcn35d=EM35K$`>~N%(U2l zqd&j!8So8Zwdpi;@QfPs-E$biss`6W7bgxHJd>cb`c5eN)L{F3X#m;sj(ofDPz&^} zt!Pl(+}=s)M-ZEeytkR&)k5s+@-i+R90Xk|Pn=gxZZKcCC7HlT=_^3&D%6s!{e6?= z9^Tdk4^rxFXrlL!l346(1olHl|G*P7#`b*g&Arsy^*xuk4+HC26r4&$cO;N&W~}~k=kha{Cr^e2*v_I|=x%E**8rGXGx6ATQalUY zc=B^mFNWfN=+8GEO~!8N4<1S>VyH2}qGU-8RWf-M|h0E0ocm%sf3-(ZH5#AKABL*6Sr{J=;OUe~hEQc>7Tg0{n}@$^q=*bkxd z*}uOM^RUHkof4ZdY=x?{%0e*oV6p9$&uzPNX`orj<+?X9Ytn63gYy7$rS+nI7me(@ zonh%otoIU%^G`?8D$ovlakcQjzjjF%w9$q#cwM@WVX(J_jjF|OM>&&g)?!OqTa=rT zhTnHT%a}YzlpoWp5qA)6trhm;yK3Tcq#_UZBMlFshMd~=(+Y<_{XYL|=civ=Rw@uQ zWKD6;wqijoaK%E5JwS3`KAB~1f~B2U)?|j!iG`q1gRW7hutcDz?u~fH&4<%@=G8x3 zB?9|i0;f%s5<%M*!9T(wdy#caqt{AA+*@dQ#kD=Nj^dpX@T_nMV+KGmJzE?g*>U!+ zwyv&mgfPB5CYs=bbt64K>CGz0Vw0Z13!2r$JUW%)K*l zymUDl-tXEKi|iy6mv^9Cf(gcV-4}0pp!!N4qd7yH74%QP7JsJVafR_j10FtrVn;inRijEb%=ex z%~*ju6p_`xbEC{g(&S`gZM)8%>Jb% z-YJD^i6NI^G$bW!>*YV%nR!O1U7Nm>dAOxUV>iQS6RL@fQK>BUkBL|+)o)Hs9AWgV=$fNPl!pL>|W31OMw9eo{ zKh*`ATv%}A$!?}9Xz(6vjpcVgaqTXrHg97y>0DW{SL=Vag-sY_4vCocwCe=nqw;9< zjLs0XL|bDqY&{EXZx+PhJ17gY&Ms>CTI(D3N_kD5YpST8 zbM7|uYkyas#ugDj&o-=TN0SE=gV~g)df0&`b==wSkM$=Pd=3C@VfPUwfAZL?8(K7o zFV&PMer@<&a*#*g+{S2WVsrB957zPWincfOmgzP6*Zstw;gM(Fwe!huX^W7(y%Dgo zM36hYd%mw2eLg74wgWcwRQyH3YXsAJJbJse>m3%PyaG>CdU(X@5m zkN$XXIi-R_2z!{%tb^UsMC}|FQ4Lv(ssKEmp+DN+K2Bs;H?67^=|NA#CrL&A%$hU4zO&pmspR!Jfy(TV_`!D~jN@pWCjWa%Tx^jQ-<8dbOfHw&M5cq*!>HJKY(%-*md+bL$RD_PWdUf%3z* zUWYy=$NvP1wHmtcT)5RuFPrKkBR)CFbZci&%hC2w{kW4PW?W00Gyad9m?9-9k!L0H zCZ6@n?@L8H2sPf&hHT(_R|nXf1ZO#YD8$WeZ=YjMmwc})lR#PvpoZEXaCoP z1jC}%-JSEBsK&Dosbn+i8RRA+Cy?+oxJ3j9u|ak`p4@@*(=4PiF}hYTD+k)l^|h-( zt7ZK+NvEL&l@z0;>Gu%)!Xu#m2XFVUgR3llj&FK#KQgg|m4CE-p{%87%j|zX@aCV& zU$|m8DKiRLwVtP&(XKj2*6hD4kNa?a++vYjHc#{SYXvcwT{PR)b7<{h0P%{G_c z-+|s_;YXEhpRBaevxDuAc7nyLg_YDalb@r-=vk0`V0bjodl0one?Y?IZdX81tUM8D z&Tl(*Y%^(w}tvj-bZN<*sJG>8fiS;_ zf-~A*o!n*L=24TSjfZf0YcwfVGw}-*dC%=;1&gnb-9(YckFR0cc|&fR~(!_v|9f>}9cU`$uHdDZByHQ{SbU+1 z*SSIjrE@mR6P2CVL>}PLWK7A9Fb zNFAIv=3aaQUAl5a<~U9srK_N@zSSN`usG5K3`tOZ;hmFNZ%T4r~FpS4{XPzp?dHyG4A6eR4c~&nfTq^K_$*rSSA&)fys2{l;OyFtPo9 z)uA23bwnYUqOc8}tyvf}`7AW)^PhzO4x4w<7!f(`j=HlO zRu0T?I(J@q<^&DNH=f0JwuuXCgtc6i>nHt)C!M!Ac;}H}b+u2G_p&W?MQnAwhsnk` zKDOh@2JlWVObX}YE75@JIEzYu1cn63Y~=V?q=oH`D_dsldai*l*`BFK=MSn?ZSxlq zTPbPfqfC&*PYf$HI7E7x86@=qoo7BKrL=|`O*Q+O2RdCWY@HBlRKBFKi<2kp2_`?#v2Sdn%O#cVT^RUUwq^jVS~E1 zcTCwLLx>g4=x@K5~*VdCfduSoZ9TO}duJE$~@9v~Ij|=H%jq zChkjW#jou0)Y@n?1V2w-^s#I`y-v5lrnvq2dIhE5iBa#33J03Um$ixblf&zkWLo=& z^I&xWQFGN6=Wz#6M-B4_w2gT6w~}u)0qJ}7u?_T~PJzhs_cNFRLUQlKK?F1{$=GRj z=3j0eQ#oBKX7)g=Q-I5I;K|QDS3Qq3UJm_yZQ+#yoB9ny_n}ymZj{VQSzbM{?|=xt z1m70V`=$B?AM2OBx#ECrDrhr=pnoH3 zz?~au-0I)8%w+m-;|^bAv|BI zijv_DX+6J4zY8uVcJh(1A@z1}>P8MHRB%3a=hJQMTR(kEZ#xy49XH#h>pI`(CA!z~ z!E6)qGepVTe*iuNuZ7ASo^Sg>95GtyOkP)OMLeh8izak^_yTdB6b6U)I!cPeKTvti z+U0!ihV~~M0{OQ&2KDZK)F0e>SXaUQr5$qB`alD(B_`>H^|RwxUf(aZi@};#U--z6 zrus>tMP~~h6+b6E9lzIUcC|$6r$iuyu#K^ED+?lnNebpzzXdH^O74hCuBl zQTI9j$BdoDndTA@F+YG$PJS#!`Ef4=NGpoj=)L4i%Cd@7Kk^S@^M$iF85i#eT0d7{ zGD!9?kxn^Gltqcf{B8s#t9%mwjhC4WnF=%BjU}pk0&;v6H%;geYZa(_!>F+b2v%e# z8Mh`9z`{SJ?Vf92Q=E8JUIU& zPhs%c&!DNjn}ROVNwp9q=vFT0r3OiYzD{aAbESpvXZb>66AuT2*f3rCwd(RpMm!nY zoAEQjL;{~{)cazCyFNk?fiPa*n*26KeDuC6jhC7vkX?ipXTt^GH#}@EN2-W+kQFe=`Y?^+vK%g{r4u)jE=1 zNVRR0gE-q>J}rChn6x!CG}9BbZp2RT3XMK)5Mu`>6Gd+6*)UBV@oF}d3>1I+(I_g@FN()mm4Hgg zWB^^so+lP66Jq`f!n2WshA_$f4d)k1Y&sBShf(QjeQuI#QDz*7$o=S?BXaU=pRDMXV@;jW#XhAW!Utmnk_G0M3Ae zM|Uxa)f4%K@C1Ps@G9E$b?Fr*%6)4}C+)N1;PI3sTw)^`eNN4kZ2VXY_?qA{`4dEU zb=&&EcDtIM60)<;vy-DF(&`%rj*5nn?Nn<&uvopE#3smS{x{il z*73i~rinBE8w58S+qlxN9l%Rj1PvQmrixfH_Z?xWE;sN7LoTsMGDRVWe1}WkNGANG$o*_^Z8=(~!5Tn?~6(Nonp^8IOIK;~P-|gc) zI((g|#msIa2(G`)xeg>IBoQnHwCWP10}Wcf5!Z&#h|Mk%rToaompMhFnqGFrUFjVk zKD{k)g?hzMLWe1HyVxL{RwyesQg34b3Tm+8C+%EH*xP)OwyPTgizf0c#7!#y<|~Hg zT#Jq`u&p9>Klg56>s{4-yXQAfCS3zRuWFYuhP`vMinr`c*2`qKl@<{XD8dWN_F;ZU z0xC(uM;6T#?zrceg2H)1RL?r*u_H!QKc8HGFHk1d11cL&zMo`_mJi(;-{al)*2nJa zR+Nr%EH8a3SMc1MW6EaoecOs9@_k#VNWFZl+MoRcl`m{QHNK+k`SvU2n>Up$RnNaH zB!K)T-bG$L)0Dd$4vxt?eFOKt?u`4%E8;Xvaji@s)=ut=$ry)H zcVph9uKK%@x=6s&PA}Nt^$N)Q{$=wILreZSs-c+j$t>gV`+s5~b4Uud%I>$;GYZco z^#%J=Pjw1|&qDYWMIQW_tgwE4Z^b$FFPG98C2jI&<3EN^o<4~@U9`0UD6PF;Q)x#_ z9s4=>8@3w4{Azi3j-J~zx&%kBydB57#0u6#9J^pJaA$3s+;rV0)#VBb>9f;0N^T+|mGWrlxkH-5YYi)L$)yHhZsZAPYA z^eVk!&h*xNE(`fzi3H;;Qqf7vUlvqUKdUNf=L+oTSnrG8lwQu`aTf=YFeFJt|pyr1;?h_y~wuKR!#Tfb? zK@^ssTrk?6QK&V)Gq}Ul@|h%(qyAzz-AJm({cl;evY|QJN(# z19W;zy&uB-kRoxy*Q`FTa=?=VvrK{oeRK+L=4Dco@4Bh>gkTf;Vh^&|j)-AzuFuLw z-~br;AKnrMM4`b3p_AAM4fu!0lQA~3XJ#!#an}Zg9(ONRuL71HPZRy&F-Tx(Wa8_c;07+3*GjVNvZk>NNM;l@Dpi z(1w$s2lYO}u-R$eq?|~Bm%BeJcvL^TEIC~Ey)Q1Dmk)@}6Wwh+gAokNxnt|mImzjopq)C!FA&lwj%O=iUcZQ&xG7}XC6*+%Y&Fib}D9sbt#JT+x)spFzMzv{vis1XqQx)?G^RaPuP}FK{pQE=Q*{||RpY5x7-5m&rhD_|CHmhK0{pIIHLMRn z4u4CD&f$sk8Y-=)E0e02Ot18K4W9ZVqGF#Ja`(s1G~24?aSU3V8*c33L-&P8j!|yVGncE@+TqjXZDh)G>3*62uGhghfFm}E z+Muv)4Rn>ZS(2JE+J4q>kN%6mrh0aV^rQGG6|2`TYrWx8(Y20bCI+ztUZt%@7Hk5y zmg~s#%ug?x5M{Ru{c1OeEr1#6Z^@sNMJ=|9{6}>O@NVbXY@X8?J~WV10(@@I2aldX zJR*Oxy)VZfpVJ;?hexi@%l35tl>&e`GWm9IKQGmtQ}HihO4|O-2mI@&dx}e6^a;Mj z&g(G{g}Eah9AIo0w$uxkRzDa5y)+;8GYfY%7RoEsJ+_bP$0oW+gqq%g$K_b^zlN_4 zqCzzZQ8BLFpo8ZxvIq0TDCjcPrh*e>oay2dGeBfyeoT~}Nj=Qdt#<~;;_4@oH5h>V zb^>4ve=+c6N675nmw3?HwHAI&|Y4P^C2;ypk!ah!~CFn>IaHnu^?lavMvx(yy~t>D0=Bzi%}E*ic5` z%A?s^bPxE?uLu!$!zd}jPd^8ghj2;0T`*NB3@MJ+#nZ_ z?;Y8>O1m8CzVz9eZbM|T=;!-pa}{5WE2rsf!rGsf!rh_%$pVbEFK#9@wML{;_#bUhi)6BO z-srjIT_ho*)A`>^N+|11!-S3Y{+%~J+1Ddsa-@N-`b=KA*(!P!o!qvkt^12Jf?AbA zoa(pb{*+QAu43#=Li5R3iz_Lz{nmCWeul^_TUGa10Bbo80S7^x?EBt#6n+@5^whs< z&0if&3g4n?3aoi#CDaKej20I+TynVMLTmtzyPMF2SMq$g775kj1FicPbr9d+*sYel zUaZ!N!m_=(N2SXs(-9M)=OotnNbvD-{j)><<4k})<p!x$wE3LGNOgGd-V!m6BRFNAKRU$q7k0*aY5QkNJ11jZncQsO;WXqU%>ZB zfVZ1;OOVYtADrdq2gi##yIl&8M{(kdw@kl+|Hb>^avk3@zDYECBj>K^i39ZVl?BfF zmUAq$RC(+cXI2b-eq;e{BEbCa?8;AbGc z#llmUU&%JRMXe)qgXa-ZW0H`u>xa*fB~Bj@yegmGtC9wAnp8CCCS zvb_y`N~t+=sBm-MLRyz*e%gC+-t6Z;#3FJt#MvAYYJLJJ%e4bNafTyc^b<$xCYCNoIKOL~$^W+Llfl6UwRbATmzG`3Q zX>nUW&yOXX^&WK3^IW%2r}}ly@5y8&n?NZqGZg6`pjEntsm4(*=jiiU{i9I({djgV zOn%>Sae3s;qOGMp^U{*392|oZ#;;w=3QMG%gxUi~eRDqGCDXaO;>BCzYKj|h z>>XKMDgK#(kDoTj#hh|=yDPTx+iw)to)`4vxTC&G+X_{BoNM||GsVtH^|_z;0W2H& z^gA}~3!q!Tlg6J_JfRRDuUZ%6cXAbFj3wfNY1;0m`52oDHi>GdEvZaV?)6De(C@vd z-qYB5>}aDMXvB!SxdQhZbbm#|E9vFYmTflIa4#}rQkFQ1+Zr98SE5%l}LXPNp)j4qULJo-65uem4$uUsx-IDXk6 z|FTM+af{42IPfRPFF5=*&ggNH3C&7q$D5Ibb(t~p*uI3`*u_{%HK9^{#zv|*oQPy4 z2#3d*@!ixIJp>F>--=XA-g-_Tsx-Bfh?TowA-da-Z{hgl6|LO(_i>CZEs!>&$G_(2AvX~7ig`H_*!C;|xH{?KhHFkZ< z?SXYCMwY8%?5i*B7tw6uEUvuSoMEq$1&eCCQZc*&l&PiCXE)})}DZgz@L?#4X zl}nUhLk1XvVNRHtWB>qb&$P!`1dDH$9YGiAD{ZN@3o*OTP{S3?*V)o+yuDq^ob%*b z%cJhz>*`yF+Y*1NT=m>**RC;X7(`qKUa9}5gz;-4y(ORa=&#vAb-0AxU25m&hs30A zEyq&h{yk~QoNpaAug|+~AASbK+DKX$tOT$sTp%hK45Ia1d38MyMq;3=dv$ko+)Vlr zFL=-WnnP&fYUes>&|Vvi8g9^pVCq@=lszl}+-vmu+M8TZz00zGeIuPKk9xIt#4iZ( zxTen$3?XQT!0s0c`H(ECM+(z=sMbdXRVrXU)WCR{jCv1MW6>cUc?$hLS-Nt5e z6y*Uc{@pbuXbl0^@Rx?FFkWq9GJb)v$S=V@n+8;X2hQo z$+!G>>lK}wpvE${2UKEpf6Pc7-Li!rofHJ-D>MP_&&1fLTR{gUoGR{3zJcWuwcfWf z`HTKfG&ea<&zMSIC~Ulvw~inY%3|B^bjc5$?smm}LTgty{D%&!gbop>Kv-@ICKFev z{MU~~jeEI^nSjUZIw?dwDu0tf?N-x+^popdJbllr@Evpmg^KP`>VTQ)iLD`h9WCY0 z?Y_VF+G_~AV+u;P#|BPr#HyyU#hb&px}?{_M4$XX}+!{TeQ6yWoTESN*Fu~{`s1vB}?zBWJe@|ucc;T_jr&#h^rwrzm) z7AHUDc#m)LRMv%9Tf3iwOLEMAyADET=WmyCh`R_bJ`U!bbuT!W4L$#^TNhx&{HWwM zYmM5F?0`7Grhombq#k10%+)#lXFc6nZNH7Rsq@x!$NJc>D>+VoBQ^g6caIr~;qXNQSZfD*s%T}i65 zGd+>Uw^Z{%VY+{~&c8#!4V++hDcmG&_itg5*ZjT!Hr9*HVv{0VDix1{)o+jQb66{~ zt23ZpQUByP6`?qLPwyp|yqs(&`>=Kv2px;pheM}5_)JeS>w+9w)fDgu>Dae#c}Lr4 zUN@(pS#JOK(wc*U-)nx4qP7z-8P-Abom2Ih|5(|c8mfQu?Q`|#__K>1+o>)xwOD>s zlD=!7Dwwf8e>;5{^BBoOUhwC4WrL)8VU?VST4=d`dMD)eA&y}$S^3nOThiR#{^2!6 zQ~iZ6{QTrn#eQnaV>>6O=0N^ix8J=|e=Cf6F0m>(G)f$WvKfL{W^j6=T}U|nvs7$n zu`s&O%!lV7Os=zS?SC)F*0?G7?aGw1A5Yovh{^45$bpPg+X}6SH+meP17$CF%sSy>0cVJHEBbHOeqglhQZ|&w=~MqW zQ|8%=_K8^>ic$C5s#Rb$oy+>Of$5)B)I0{?(>D(+FoX^LRmji#B|ZNMnM|+K^JZJ& zn_iqe00qA-t9dL&1Eb8*Y4|$ZGO$j20^Sk`mF+uEFmQz{Q|#v&(^M z!jY8{-&?II7|^p^=g!zS@niD z+Obl)ib8Tpk17 z?KG*X__)^Ae_hP1MsYIoI}kG@mZ(t6fCYbaQH`s;Z$L8Y-!MgqZ*AB0EX`0u?URX{ zZ5WH1&jqZyCY&rH3mqK0~hcQ|v)$2cmK&)Dr~m4GC?l?rQF@AN(Su zTD2-BAncMyX7##|FZ{+;{91g8-UKp!4a!r#R8q-bF%QS*mvf)pd3((;H?sHSKMIvi zs{Cn#mnoLR(a^qJ%~AZO*~C|CHdK8?DEmRId}|^z5*tJo8w#~1WdQQp#S68bn!4QF z@>EnUM6S1V;`luKjSI0(DBxD;OAJgpif(1d9be%Zd1rD!>ga2lxkQRtUJK42|HA^5 zy{yLWE^~A=a+A3>@;`zSmz#EHPaAY7=^tKPyw*Mm$y@8YcZ%6HVL7J%78@L0Z5QMS zi)^-KG8iX|-@iv_@4DTwW$;mE+TUJTjy+j?X{>KKfdfsS@-H@p&CxFF#c6asR`WGC zG%&=|AcnA$lracdIm9#}cyZEZ{v9VEXE6aKw6s44EE`wc`5YbK9v zJ*&s(2vR(*DZ({+e`maEz6*786`LO<%^dbIwI|E*T%%JqvEabk#WZ4eGz+Zm?QwOs zi^t=Fy|KNI1umO_;`zChfO$)3T7qZ7I5H6v@rURA3 z#@|iQm}tUzI4+4?YdT$i!_(CbjPLtd6(GO{j)f2-dM9xoS`kOf3#c)Te#iSNf;p}4 zw$mbBIb+4;$fk{E%g%W)0d>{}eu0pH5i)Q}NvAJvey((CdJxL6OCu{isx<)qmPU_7;frL$1+xB`M;kvRQ#COi z%2g9;_1i?m^7zBC$*L}PpSh9ADmZt;}UM`{;5EN#AkItr{?k>goNw`6#91eZFrW~4wwwAIqQnrJTvyfKjzgYEzsV<2pOLJArk7!DWkMA+4&asytR8`IOPyTF|Cz%4)ZyWv33* zPW|C25JpbPO}@}|1Cm>g#S*85V|?%7z#_oKukTY|_id{e^%w{B+-9-C^18{#S=dtA zN?(q&Xc%mODV{%oOXw{sSKm?E@XN5?{StJVTxzl1hBCbXkEyEr&@_>$x6)Q0!>pHD zK|#mj>}Wkawkji)<3CScFXOZ^ETLznL_!@iTaE< z<78sKxL4;`e9<&3>4 zrTyk8K@JY7&$86p+&tKKDfgFp<}eS0jL#ugOL7dHA?A2x;yzeleLjSx;k05vtJ>;e zHF)7-YPuUwM6GOft(tG>Re@95y}ISBHQoToBRP|V|B;cVa99ybR`pDTA2^1B(~obA zS_P7fog+}pmmnSv7T!Ya)AA}zz;&{%4uSUVUN|4y++=_ys9{m+dKZb^;4@}+peM5g zGWFOnWYiMM2ZI>cST$U3YVgahIb}>L`5a+17N{X63?WQWF4KU>3YS8>spkeFkaH>l zrOL)3n{5%H>mjYa9Km7+Y1t_~SF4o{Wruf4g;}(wM?+gLqge^lxGIOsZT@^13##OM zI-G4w95R?70a5A_mjw#R*m(j1sPAnQ*HfeU%e_(U99dOmCHDrml@!OTcj2JeFxa>a zY-#gH$=T1#b^;fS0AmouzkO+(^KM;b>;}Fo1yG_EMs$c6&D}R+lLBOrdT#4;h_+77 zi!#$vX|P02kv!?YnxG+ z=PzsW3=mw%VwhTdDd6JGs4!kl4smT#Hw(;rGi(%54z+i~^PxzWO{P5NIgmSnsNW_T zxfB+)4Q9k9cNeQ?S4f0J?0J-L4Tyn?Ashl>;PUpzBd4Rt^qTp|H=jC5 z)=M?d?dwD&wZ*Jt+)kNLUpLvnswZo@#-;;I4OYQ)KbOxTwV@zKzM_~&aU>H#1Cva< zX`Zyhl@S&iNGUdW2bur9{x$Uli4@zplnbhwR^1I;puE0@Q&6;CoP~t@V|1m;M3_ZH zouUo#LTGLcWK5DL7z3i5H@R>%-{0RTX2w14Kj9RO9UIH*0jPM2Px&qU8*j`uXh@Yf z4mHGz=eDA8A(8tl;rpSx_@bCok3pNlIV)OA0=>r`v`X49?|x=PzYwuxn{GZ(=6|Z7 zO^Yler5}=9 zys#|ztVmt5_zRnHhpOOmw2_^tdx%_4-CJyiyL!g%o~0$jQjsBTPyg__EYJk|=1 zuR`8>*g|hZh`xOmFYLpsnS-}B1BohzJ8=^1y0fei=w$Vy)|GOpWPJJ4@EUS!u;dyD zr=Yki_JRMnm$AxVX(CBY-`rFsVtTwc1$iN{NfAX3@Sdf>;Sa_ThC>6=I~WH!GtK*t zpng++Zp%xTwYM8I>aGf|v~Z&;WfLWnxRj$S>hR3wvr<6dL5Qxlt1Rht>aP9DeNEBx zL{@YX!}j87CiP%yfEi4g2Z7{=-SC3P@Ey3L52yZ5f5iN$=**4`1ysx?0Yp~J;;l^a_XGUDutWE9f3by(U!))C{tYGAuS} zF0YeyeB1Wwco^ni9vuITcvEkoCGq0|K*SgjiLG&O5C<@G|{man0sOjDnlK8r!$m# zk2OY?h^zc#QML`M<_OT=TKu zcG_iW`s;1v11wQ}2uoirISC+^z|P$7&0-g*8i@*u&Af}MzO0YG&`Ds|dLQ@^pFSqc z-9c{4LL@evTmZtMv;Lj9xMKcYH;Risq;&2m>N!eB;1m0yH8IeQ zr#D&8ki3%o!8@^D1}05(yzYWyuV9&nr1Of$aA33V8KqIYDwpW?FxKyO?%d2@om%^k)<*>-r5hWU4CqltZGRC<=a1(tZUX941~Ri47v~W8JJeH;p5}tho`scp5E`-*qrMJ9=i;LfwW#O+H}et^-0Bt zcQB(sQT-J*&doWi7;&jUtn0v0&e}g=ADbMG(7heRI*Xh|`)^mH7swkTkR6k$0((b7 zUdSaRnVjKC8vihe4SmvSMREP<&92RcmlfZOykrs$j(|w#cq`l9cVyfzCd%}iC%YuK zyPQthv4SYKeqBV`gGsqtgd;HEqA^ZF!qa2ULH>DaV%5{jsj<&sT2bw8de$*mh< zwS$IvvXp zWStWEs{_Z!%fj+0U%7g@0>ZXVyDe_v67WLU+veo(=or|l>cyqmLW}o<8IT61#jCZS z^}?`u|Bv+*`2>B9kWKpLK#nD_dd^9)>&zxpa-V8+GNzNYz`jDBs2f1*Z;6y(f`z=gD`F}V?x8Cgdq&%p_r zTK((EhL*G?b6Q=X2;ZeU8?jZ#BLnh|-IWq=jK|c+^c{S5c`%P~DOy&qY29uCb@gO3 zS9A?_7)H)3E0MLF6QZ36))@8=LXc~SgU2OrlT>&ubZR`b;|t0_AslV z@B618dcIi;FWH#kxZ>KbJMi{}4G#whIXXjYPfWVkPn`!EK-j21c4U*!oo^)a;;}+T zRm*`-KPSfQZF(9Di3FL3j+ycaZO*p6EPnLx(I&eGgp7NugKD!sEwu21!l-aCVe52k z)jJq+r)d~b)C&?Ru)&za0SL%t>fx3rnEIB8rcJp5P`!S#eie!2@jn)(Vn}MRN07~Q zlKG!(Wl}WDmuVEq;qL;C_kAj9$MIs-lcnm8J}a00bkM;MGeKaA%j;7|wA(5eH~Y$} z#KKX}e;^it5*;9~FG^dE)i^@H+^FND&3giMl9>=mp@h zR$1?gcxM@XNT-i=AX%ug{%5 znh-p%Mh~?B-Kk)QpuE?D?oJY*Am#u9A>oNX(m{!Zt8spWK9|PL zH3x6TSRREU4(oT%7uv%%UAoxKQQ?~cBx&DUUxx;hm6P3d75bIt$Q^ayoR`XB7K5B= z3xhd--52o5>+AFTXc7fTx%D?fbgQ(D4 zLR7VV$(BT}HjAt7_$S?Pn{OkS#Kio_tjDw=Gx$Mv2Em+P~jSr}2zO^)B8|Mn+qtw2}r-?%?tZeY42G ziv+p0lR^{yzSCgwWnCmuIG{V>KQptUb&_T|4q?Hp&;ahCXRvR5Wh6h6}Y^A z-@%w6|7X|#J#pO7HS19z|D4K%2E%&s&JI4r@BrrGJ^4m9{Qpk&rur0aV1#Vl1<0}m zw>IaNmywsySK1wDu|7h{;AcZa!+SE@=H(Y(A*g*73_7Ji;DCy>|My=)6wtOxw~ftF ztYlbi$@@;duaG`qJgs)Vs4F<+dxYJhYk-gX^qA;-v*I+xqSpZ^Q$<5V%jR?1i}iah z7~2(ThK-lS?M<7Q`x^)-1Y8dHHhRHBl?$3zXK(sUDa0=+~iCaVwEg?op$! z+Sd}GqJ|t>r%2^R9PnghA;uG;<1>tdB?I{sv{vS#9=J?IiWBtP$%`i~cOWS&qfFxb zS@P+!@ZEQaEA8Xe7ue-n_%a-oPkJm>+_FDEVHLLJnrw$egZ55y2<@-*q=wlYvCG;H zeNl9iE>B`kWAmw(M_rH4Z^;p9a6rp?P`2}G)`%Of3P&uHGY7w?knLOF<+ZQNpPK?0!XmyFkzJeLO6P6^sz-csgr8P^Ux|WE(IG-HJ$JPFvqH=MWA;lv#Y9+?&e>W)m z-FllS)0n}THX*;40g^+8LOh~pTU(LrQgxN2^!z^)Y)uvdzYXdU9TYg)`(o`8jIO6w zXQgpO3Cr))_L6rQrA!*~GXwqyqTKrg^i)#m;a&AuL zGSXxVHy)p53N%6pQrt=DsJYyoH~^DMn$wUKm|e;$hx`L1^_V`GZ}YQqQ@N(Z{mU++ zPba6xtHAbMfC;krXcA#Je8<*~f`aY7VB~uzbMt-j*Naf7$gctvNXF+)80cz=X^+E` z9#0t^<6A2A$M>8#{=cBqJSDhQ%SFr~#%zX%Gb6Ml?f-$K{Bw%w{==lCYtyENHi2#M z)WHCJb=jNk3poGS89H6tg6Z&nb8*695lIHB$Kx21<}fv_Dv8f#V|j8R@STKZ$XB>~ z8HUY#iv0PT$J=Iw(5ObyXoy6kv@_2xfHP86Q>#&#OgPtf)W)I**FdZs7v1VU#TTb? z-hp32*FmdzQgLHge8OR;&&sADV}cP*=mMWI)8bu#s-bp*(R((ORr^23PoSk06c1P| z{7QDyOrJpUvz9lyGK=#V}_^#rg zf42;l^NXzml~SgK4h8}c)EdI^#sXPT2+TyLJ!3QET#L(y-}QVOV-9_Mct(^vob)Mz z$V&0d$zE4Usdacb{mft3zWg#D@?jTuh~67| zekHEOY_`oCuItmxp4M$pkB?R{%l}SgRqO9A>6>lGN|r5KMdYuZj&D0ue1Fe(U3iAC z*wF5<^JPb?o~_-a3+s%_02isRNZt$}kn9f3yG%QwI`cco)> z#d(I)j~|g((g8hAnbf$ulBgO~D7>7Sb*(fClXvbGqkv9ehjOeVJxkKfz1yA8Z&v#^ zo2Ragm)~pV<+ z+v}1xD^2j}p%b~l=>n80#(-RxoX-08Hle_qdm(}0H`91JOxsVQ=N&hixm>*Y92pPY zJiBkRFOTbQa4%b<@zZBs?!P|~fclr4a0y*g)CkNb&a2AG9=czFZ`Q~2RsRgF3P&08 zc~br#7N2jIsKGe;c@q!|EEX`lXF^bv8qhj*KOB{7C|aJG*~3cW&V?4wO5npVWKZb@ zTsgQ+(eVD}m|33Quow*05F@Ce?5C(aRn_In4z0@%8Y?VczAU1q`?wl^^!@V#91)9Y z@B2xL+TUO1$@uI*^}kkhPz@{jj11Ji-U-`&7FElPcFq?OCSnla!rtuq3m{^SVlMd3 zR6^8M&0U}D^@TO{^|9rrY|D?r$ytVPAsN(QvY+|f3W<3&Bs^Q&L4YWFF3AabSH}b( z7{KE4(qDp6DDt^@Vz9ytBMNMRvQsjeW$`Xjrvh`E?_b(;Wh0YkR5PTA((;@Z1T? zcsyssEfl_uU?2)PpmQ9zKR&sfr`UFfm@_iDw=%nBoL>g-Pivel1fK`k%(XVOROfm3 z1)m-Z)B!z%WnULF&p9!envyK!c1@RwKe2Bw+7kb`LIotnQvttE>o)_N@IH~P1-w*d z$arUQoS5o17gR1WPWl*XkF@E$v~zArhE23Lcb1u}f|f^RkcgTfwW-}DWJt6ce+oUacT7GqaR0eiLFITz@swZP$Ii+eUvfym$0DArze-* z-g>K(xvuUieU3N#YG2i?cZVYY@i(56&`bhH*qu>p^hKK02YEr!M&c*1)`>K677Cik z7?e<dTb?ynJGYXFHL{NTK`Zm86V3gqB4ZG?4VYuw(sXV4}rUbjK|`z^(# zt0?aqhWF2mWw|4P1e(8i0ws!{1^^G?h{-FWV6BUz)&K=!7k?tY3HaZNl=y^03~y$e>mu0x=p5un!W z8n01!U9tbGF2H>{Dk`c|^n+J(@uyKEyDxwmdKo1$wof8FaOk1#^lZV4r8zIjDL+y_ zcfP$oef;?G?UMY>zw^!SA=PiO&U9>UWbuIW_QUR0Zo{8b4u6%u-v3I z#>z!uao3Ua781(06(*%3#fH0g zapj1yMR@1{K5}B+r-QGj7Nk#_!Nm2|pA*U&wOkAm^)`-Qr$_b6@Q7*1InH})d0bK7 zqwf-G^;lLuWk}DJHlUl;Ak&|Eo}B4J8qiaD_pZ}e?Yu8nu^X0?e~0y;xMLZtvpLv1 zDIj$-`)v<~vh3QQ*%XQqPT8%Ku$?^->OL0kZFY!3%O)WQeSsa{eR8upujRKmFt9m5 z&BC0xQAK%!%1IS+h1g)JH{td~pn*ldIX~U{0^R>$fP0e#W+bN!%dZ!6!A2b~r>B1t zt)c_I5CJQ-%xKx+$4t1`$o=+{;WZ`nl%^9+(ecSW%q3|vC{d8O{{-3{W}&ej$=gO~ z($LeFw6{NPfgX@@w@xmE+s_UHEj|)Y%;9;KUY2?6I;sIV@DUGP+ zCpsnEw6-X+0j4KH%!XdhR=A4?GtsQYUx*z+2{{#D05j@=d=F8y1k9Jzv|Wwcy1QQ^ z+vb2?KfhnQcT;BK7|*rMvzHi{NLXGC5=iS>obIjcapbO{_a_yL3#X>V&aC~9SUKgZqHd;WKz*O*hTSh86k0bl2CERCoA!X#9Y{TTWUMYkUcxl(P=%W@Sg#mO^4Yk_A*LEJ?p2BDTWGnejD9y2`X7V) zHgeDfF24WxF~)g#d9dYWfn1>pTZS^1Gi5~ps^*FOP!+By7G;mr&d{Sl#|T))FvJM#-)=d?;wj zUKigf1NX~zpI;5;z5@JF)CMlF1U`?*O45`EO5lHDcdQR#3N^;Kx9OOnH7gM4%?jb2 zRDjjhZ-U44$MIkNXr$mL^sUKVl%GX@f^}GJM9g2N-0^a${rAO}L~R%aXQVnDo31GA zA#gfo$;;sO-^6}-`G7`pONwRlhEVbrjT&T3b~c+o2zx~J$CoN*AFABl<@}+4vV*=Q zuYvdwZw&X}tlcIB0oCcAOoFp|x@GGvdpGOA-Yd_-I`vLFUFkDo1VP|*^>W9yp|=93 z;>$Z$uu;$SncT7--ua4}UOb?!`UG`eA@47)7ZIh@8^yGVF3(D{w27adLw=XIO~rrl8oiiQTH+(zuEkBU(=0r51Vjp&Y+71 z8^!$p3+*8q68%rKH?W0hB3M`QyRV`HE;EpS>2ET)Wt!hN*1~vV`sg+xAi-t-jaxde z-_S6meEEe=tJ!X%saXbu>BwjG<~fy#D_I+AMyQXSDJfURbMEez1rnK-|FPTkm86rL zZHycp6Sjp)ocE76epM))31#Lk`Eo#*I=J<%}hH zE1t7E#EMG&Ut}p=Ui+6ebze?ABMD;R%X5Yq+$jEumnsCO5qugRuKso*O2U7E1~A^$+PLXJ>t z$+{1)EolhXV!5G46aVwlprf6OcIE-8k3EPSoYU9Wl{2^C@<10P;_b0p2bLiV4B7uS zc*i{CnWb4V32KESQ?US6)w4$p2Uut5%W^|hi5J6x#TKgvGGRliUOSJX@16a+B`ZEL z(ph)UUrQ1VpM5R7z9#cgp0)2yjPsR|mzK|%z(aqc(oquW zMOtK*Q!hIdzw&)EQoPiTvj_!ROKAG3q7ckDd$0aJF%eN8kM+Ha;D%XGm!SGfTpY$f z8~@^)!@x!%C_7rO+r&NYnfOKh?EZM*!2A8i|9`Qg@hhk2e<%{v8RYx@Kj~@)Xz%*a z|Jm_haf12JA%5Z`3GrA7TQwMDz;4YAy`B4cJfud_>NuZM%IiL5?yHN%mbFpjS!_F@ ziz`3~?EXghE!;~5{9;lsq#JKoTsi1~Zr{IWYx^V-k$u7>EmAHLWlgR5JQi)uVOK}- z&tT(v&l+4P!)%$k3gO@8pn_9lN9p)HuUCmhfjKj zVS1|^?X2!6<574JzV0BZ_M?7QN{9IAFxK@PG7GJVgK2q6SHl#34~i(s9!|OHSfdhD6d(94}e2U3qAp1ls%CNc_s5Y^-GnAuAXhn<^pFmT`rB3!- z9@y-zE6p7%A}}-(2##rZt7FtA?7K!wKSC$3zWeM`%=;Gr(r5j{yYh=EX{F^ZS56Jk zq8dI%R(BXfD(KNGNHwkl_gVhPAxNr-_qSfN9x0x|*-&OlG5%X$G`QmHZ)n{ab-tP{*Wq@dvx2u5egbNi?se_k>bh&(Kg^ zmI0klHd-yzdP3^wdU>)Yn~4SD)U?*kpI6$pK8Fy5@z3V6~rWq^K*&-}d>+O|= z@t)7)q~DmbqMH41KYC`XufZhy@5iCuqr7AVIv({CNI_7CnlXyDHI=5eQVa$=tOsdv zVrWIi=|zPZ^yaxGLFL5lq=pq|H_?e%7nJ^rPC=cqz|LtzsX>QdJt{vz3vp%xzXJEl zye(%-&gX7(4>}S`khqE!6qe&T<)|CE$n306=S^6^1HVt$ygI}1M>%}7YJs868}SK! z-bJ;eW5^%Ht8#o>Vv#1?^9#THxXYUy+YbJEwEkpW&$F4AP?={;-Zd+LlcCkoN)#4L%}}sx z`RNS3lM21oxGAOlo^c%lZKgv#C(Bn zUR~7`NM@nv+{`R_T-}&8Nu$k{J?5LJFqO?5IIw2_cT3&f_L53cXu~ z?XYq4lR^$^oEM{3D;3BKP-?-MfT9MsW@SoEw!U+%%#euLBqQozm+tnpoyZYo#$-@8 zS{NrQr?Zr_W9A_y=*nmxybvAPFV7XMbxD81;N>xckqz_``LMc|VO%v;=_g`Y`HV3p zm|;h|a$M7xaUz)GJ}kT#MHf0XUBT!j3gtmcD4WwfQO?F`q^X$Rcm!W^B=XEFWz zBOw08U*TXte=TMTQzNmx@-{fx2${%y;Sb)tx?E*d2U=*VWZgHkf5vJD`gFO?eHqRQ z^&&#_vzKxN@!jM~4ZRnxShtB$#3W5inX#wmT0SKkcrqPxR?q8Wcb!;m5zr~pF zT#X#x$j1YxLX!0pi&d9qL}cmZIMI)@FBeL@{0_2Iiv~@0vXnlAlAv*_Ep9tXaP&c( zJl~$=l#n@pq~ZxBu4=X3Rg9=_N;H^oUg$r2RnSn{9?q!IE*6(hWzbcOh&jn| z9yVT1Hb_Gs)Sk*O6`4;Wm*u?R=qw3g6to3|4xw`lVv)f-tIuV!DS98@ZMgVkhHsT6 zoxlrLs}lCt8=C8-7l}lBz1?-gFJ2nHU8Ug+CvM=30!m902#7qF57!Z(@8=Hrhvj)II8)QXyym;vRcs}byukk27+M=|*OK+cHoK<#JTX#Lo zc)nY2^m@rAhO$FPNGzRXrtjw1Bga==4O<1ElK}D@FE&<_le!6VEIrKqIpE}y=|HDo zi5IkV`B%8LZikOVdN9VbXe3&7Esrv(soccUA}rOa-0I}=vXC0=;5Mhqg|`QM3r*%V z)_&O};y7kj8C195EdMiz#Qizilej`&206!_j-QieVA``X0el4)e2h$rASB@W4OQo+ z=RNzNYGZT3&~Yh5ppkL;FJEvlhu=#vv-&`%Uir<%ew9Tr{J;;|j${z+!9`v@!^5=P zqF%@R7qP<_uG{>y{2PTJ)y_K&(C1g_q<=aHoP7!T@Je{Q@A1Uw@B(s zhZvIMkNVv;SgdNiBywD8W|7neRx2xtWNLmjgE2|iKgjKs=@n#x@r2X@&|a&&82e>r zF`zB$pz&|~wz}+qE8eZQTlIXwbY1HA32*@&_u7S4wU?1U@3Xv@h3bc0%)+d#{F}J% z6qfUA=-&XSNA_JTIrJ$1CFz3y`vtiF#7zI^uuFh5Qt@q9?OFfo90)BgGfqn zKb4gu{3kV=Mz(H0ZqcAKd9fqtIzc-E21=hiW5VIo!i~i56XVs+Ierkbb77(85?iB${aGeo>|2KKd~sU-nMr#Y>%KG z&kLk6n7zeW<}fcR{$}bgVn5|-Z|?5u?3i@ihmeE~myI>fQBR=lfpY#tw1Nq4#2{9Wk34k_U(o!1v~DIrmFPyNeeW z18c@_8S0QWdQ4TA z<`5FFyNy-Xc|RUEzXs|*iul4-YaCX8Yi;=|$zpQWCPxcLIEpA}I}JWzTIZ-^ppwyv z&kS2aKdF#kQ7vatOnj7>?}IKM#*kW5IZJjGbNrJV@iGB!cT0h2hFg;Y4I3WnLYhZi ziK)~pms`$+qm@tc(Ru{2$sC0`l+&`W9GZy!($98)Mr84ZQi3!Z{gu6(6P-GlEPDQ_+9C_ z`>i{<>CB_wfgqwmUP3^dTtwr(TN`8$(d?< z-a2~))Y^B%GBNc&&XU1qQ`Ua*Z?hHRVyD{L>jLs{^#qXmpnUg;O&+%Ef{?P$Dbj<) z97eMpGd$de$P_BJ;yv%Nfk_25NANIrNNyEFtTJ&3 zyuTF;FA#W%A~n74WkzLud*%_1G$yyx1(%*4h(L>>Zgvz#S%m&t6QzP(wHcU-s@r+& zYhyumen%5IrNYyGyQ{Bzu2C%7lWxOVk9Ip_^cfqU=f&H#%Jua_$S5_cs@PT_@sDd< zSjsWh)#uWXhB>kYw?h47AV}#0JdbpWe%;|TimG{H2x&b+wR9TQ>$*)<9q)?pY}ZtCDT)Q<5n}eu z-K}m++8(AVrQg*?THV^N_eVcPz>7*}A)E zOV6t+*((jU*)GdmOFP{_e?AA;c_>=e^JSkl`~px6l3{_G=Vgdtc?gIZg#^%CP*!S( z43bT$ehBVeA9mvUYtBFF>TMUlpWIbLDN3Vk0d^FiDvynt)c74jEs4U3RpD5ImcKF5 z%iW}nl4DG)i6fq=-}COh$fbd$Wqd~UAa$+CzS1sG^DcKqRrA$@|8pxjdfX}(>Dn~& zaG9qov^PobseovTiS049Y=iO~*D*<}NSb;En0Bjmx!=PW2>jEN=yqXkYtRsQ2%TI& z<_sGTz!B>4UFu0VTdtWclym~ZYREFhfVUtP)5S~s*6?Ii4qQz5oH$&Ww}KPs>`I1X z22<-aq{Dl+%dr4XBT#|RcN+}wh z@>0xG4~tEsw~m^!<0i61zxpH5xh55^fwMF6GtbM_$Kkg~zH6{6EntU#7y}ZnlbuBKfBA&c<7_fQ{d}#}>KX^c4WB2K5 zC-E9!F9h3-G7M83$Hay)7;|m3qT_Ka}K|aN?*sn zXl`Vx;_uL3eQR?(@y{Ua`-SCZBgF#1^ij4y@l&l(AKCS8{5=mQ*!2h}3SP-o3bQm0 zoaVCql|8SaK2KORFijnjFP9OeQ#AK|>jFts^ML6mLP%{*e-O>C(b~=|qE52_Z9egB z=aX=w+FbQ8v^pv$$GtG5CsDXofGxhXY~@8}m%rbXXwh8VB2w7ACO>MLnVs%@G2`ps zH}i9!+@-cN@AWK-kHG~YqAVuLmNtj!Oo=io1tFLX7DPcGjg&o%O1(hiVKD{nsN+$G zM}76`X?J9L*5e(YG&%MrnC!?qej@rD$Qz2(Xfri`4;R;F<09%PY*3C=(;2Cn8x^TW zYed6La5!7TYI>lqNu=YB@y#jbCONHtd-i?$eg67#%jY9K&r^}}sT@SUCNa%k&P5q7UIM;14sw2$pmDbXG{2t`x_cWwa{!0K0FT9Wl^eCpa ziyL-vE5rgE+!_;=TkV&tC{oiB&-3}pCD!3+fTygL0-z!-I($#&X1KhKsqbm{9e1XT zhhtu*;a72)SdZZ~QHBX)@Hndq#zb9Pe-atK1lI3C!G@)9Ufo|_sSh{f0$VsK z9}AbHYw{4!-o+NT>Tq8#s1&6;yDegrVUz!GClyquRv%4HB7mD*v_VRi{+#LrQe8Q} z`b@XGyntOBFEv_m2`fE+Q7Vvh#TraHE=Maiqgb}jgmr2AETRekFYzq3c`}IXQ?9$m zYAzZobNyE2GWZdsv;FeT%xjQ{SKEslG0(zD{b_u~w&QR-=OG zZ#j83@&-R6F2Ol*c6cQt=eBX2#q7x46Rbu;bPaPW0(O!17G78xIFoV2(7AaMWo*Z& zOu1sn&^gex&rmP1rDu7#Sd=llpt;dBK#fGmr|zo@qcjf%S*rYMlBJSiNH)!al-8MY z^wtDm#!4m$8J9@>-6HyzWvR6Q4MjVP`A-$e!LCfT?C9$=$l+l$3>g-x0pSDK%OsL+ zrZKubDT#%&4E{49<*Q7ClUcn$>FP3YI1PjIbjXWzu$1B8eC!>)`a}oL!WCv0EnQ<+ z&osTB|Ibg;R^afc-OB~dgwOdZ$A~&#S&~k$upJ+^k%HC73PiTaauDF+gbRv5ygxQS z(r#UyR?6VUai`YcOWXc5vt--&IKU;7EMKBR;*y;MWu zX{yyu0SKq?p5=i#i-o&ZhcUUV{3cZOtItD_F}!KEytX@@t@z+5i~j_@4codp%lE40 zo(Xa8?d1ILFfan|Pv*Y8(z33RrdX?5pY?v6axj;CTiU<35O4f_>~z0=ts=hCH`=t; zyXN{W=6>P(*NRcP1ijD+?EUav$Bdx@6ELbAYR25_Crm<_%Fh}dWET5IS8)V=hQ4_!M5A3>_wNjYJwGLe_SAU!U zkYduz5TIx^w#^$TZg;$mw;20-@6>p1CDjq_mx`igM)pdssJp>VyN_jUDJ5Km&;`oN z#7n+)adXZ+Iht;^m8W(zeZ-G6S)%hPYEy<3YFuvVEw?Z^&4gY8M&gn@1JP2sIS)+* z=1m(tQ?MvICZ?DcSPKYZ$6{08Wn<8)$hcP`oEuaYAM$8(p%(q&nM*)-zW>nOzp0Nh z9<@vzrkt^q(dbwitkc#oQrPd|jlYHlSjp!WNFZd*r{N8p+{R^a2`LsW7a>zy^7gy{ z$9Q&74}@H(hHZn8Bh7ULxbaM-k7uLW&^|j4j<#Ms0@2V=?c7nhw!ISt z$ZKjuCvDk2lGoZfHd<+-%*=R_ID^WR zNJbTx)-pa!%kxGpGn~PzBRrL@!S4rasEeLnJGK*TS0Q+<)+;}0^*VDTV)#!R0?$w+{YB>NJ&qjaYIA8R4pD;$8erNX{Cp6j|+w}zfV zNSb_UbyV!KC>APy=+4JML&9zpp?JK#kM}BX)i?U>yuIT8M%!Bk z#r1XTzJvrwfIuL)26qYWB)AjY>EQ0Jjk~*d@Zj$5H16(=yStqJzx&5t&+b~a*6KOOc*bu$^KkA~_#$MT-@Vv{>!p>~`a^htVko9Tf0C5hhULJ4S|h_K zJmk}7)T*`c7cUNgpW4ul9_Ho+N7{tR!C^>x8a|#}ZG7RQ)l23JWIHoB0)D`QD>E|! ztSoMgsKk3*6pvyxv#E? z8x1$ksPPZ=Y^&=GIm>AYvt>H7C819t29-~>fwgs_R?^lEYS`xA4>XtU*7&z^j;k7R z;UiI^?D1>+>xB&|tJV5Fo~)3#bZn}44Bcn5jg_`QuPvBkKc`W1AiLkA%J2GUC%w1AI$nPq8 zy~hl;pz@~pe7@GDbv>t0qwZAvvw)?pfkvCCrB5H>0ooL4Qqu!E1YF8ym^BQ~KDxIZ z7)_@E^9oDWPdzYRV~P3~*ICsk=9E|MbMW?xOvIi>i!7PX(e%KqOD0Kmsmj%t=2ao7 zLqI?o(cw~C zEubjDn_xG=IzA#T5$MQH=WUvZOhR`y&+3;9s#rDm)+fWd{jp#)t@%)EUVopuW9`jx zFc|IQ2RDqq9Zy3wswqpS=(xXH@)mt@egW%F zc8%kFgnyLb{o@V}T;U4e?JMR=YMtI{zWhXmGVp7Iw_H#u7vL%e1Qr&j49(A+zR3>TwIzf{lg0{FC`p?! zLfBmHjG)GMu9;_>eq^s!0{`5sA7UZLbV7S0^?|*3X!0LQSE+bM% zdzYSgn&~5^CMKuf4(H|A)xw&nOBS<>Uh^rEnjcD{J&S?7L>>_>wLbscEOeset1(`! z)80KvcG^^tnI+bhW_OWU_P>W-4;DmS0~!@3dOe|`aCaiauhCk6IqK`uA{fW%rZqf) ztJ&Sekzy_gOq*?4`O()sUdwrp7YKe6@=z`GN7BVTB-&thZ+lzBdTph6B<@N^x+irO zfLKSESyz4P5j=e9Uzg_l6n_9diloa&iS@m(c92X{U!+&`D0|s1?U;zN$kbEy?yp%I9ayN$k>tIVga}qfN)x`p%XusFnNVNTqF*9yfhH5aW2fijI?d3-t70xHGi=u{S=!`$ROoQeZ_fgPTj^MZ;2pFEmC~Aw3_2Ilp!U%i6n~F=2_=RAzWF)v`%=zbKuJ zuCHGZi)G@1vu}s)Y*Pk#qt68H)dpt1Cwu5E16k++dR(`y8`$NYyl37peK0VCszf^# z$D`Td!$SedyA=$idZ7jM+#JNe-`m`H5%NpepR%=8JB6}*3L}x!2%TVec=0Wh;OJ(e z#p-AL{8>h@lyN%@6%SuJw?2FApp#{C-UNjcFH%%^m$Ra3|0R}=W;)@~|7sq)!u#n+ zZ4#k7Si!{j!&G&ce)8L4Bo1_@bp3s-yjj@0!>%$!nl`@oXXE(cYWiL6(+^qMK#|VP zKYwkUEvNcursoqR6ciu^$u`Gj30T==;uCN!8}eD$GFf#2iIM$N>dcbU1PKujc5Zi{ z2@q!q%W1OX6(~n+!|oYt+^`arXA>}|VOQiFz3mMxQ4%?b7;ezqw$G*si|DcySW+V% zGvf_d-_@Q48mLUh`ZknTY*4pP{>{LzL%KyU?Jr?U{|8mbm(->>w0!_|S2YO}%d}=A6S5nJKC#-bQaZv5ZdkvW}^X?gq z^HF4~{ER%Jy%*xt-@M&t)^(M5G@|dls&;9DAN)05l^X6994qbX$f5V}Xf&L1ozkAO zfEA%?#a!yPZ=az0J6KxD{}cKXz+iqn3`uo2`cR6(Q4*pz=Hg9ncCVeF{{F<<*dLoK zjEP{@)=%MGCLVM7;pNSYWp@wM6FtN(GP2c)z3p}othUcN$DK&e>z&?k^;b#5^T`gJ+Stke)Qo&i7E-%G zH6?k)$VgX<4cHg_${O8!SI%@tLorr=&JI~}ZoSt2Rv@Mq7HAJOZ!b*Tvq$OQtyOOf z4$3s{Z=CROd8R?|aT-1SJI>$?RLmxyDSoOXl3O0U?9MKfo8U!Dag#TeOi1)3`EJ6r z18Eb4-kDHvadK}(2de!l_ld^T>vVHMJ8|z{P|wf6x3@anpJKACf7n`P4xX8(5oHTdb^)q)pL0fc7!v>b=c}xRzmj{E{Kh^)xa< zvGSVtr=kKxfXspgPOP53`^~Gyw4D_%Pz9Z=T)<^n1 z>4fgT7MFw?iMl+%*W(?0I_?(RHYcg8!DX`pK$D%DWwE;YEIzfHL3-P>q z=}$2)9Z6fm9znUxmI`w(2jG3PlYpwKw#X=4pyE5MpOUe^IYyE(NZw{5Maes7oCPc64lOZMG*`0S z2P7;VKy8T>HyD))LNZU_+DC5Io@{O=gYB?c+i`4`Z1#R|_mRCL!AVL|IY%A&<&ZNi3K7)E-QcZC zzjxfs#3Um5Y9JtSjAIZ-KmzJ{%(yaQeHzT`}N3$zblr+qdVO?BsDjZ=xBi&cU;+d)#Bnt`!ftD1{j zv&f_1qfUqWgKTvhK*TvnZF7TKa2Hiyc4$#2M<$U{!4jRyi@PYM@&2~TahgtjUZ3k1 z)^^_3m_E-gQoEA6CM~ku?JGnu?|{bw2|E!J$wA^KPM_oekssDIhz*?643G3 zAJefb!0)N{Bo}CB1IWT7%O{B$D7alN)m1RovtJ^90Jo`4j&I&B#RJ*JayNLV!3=ap zdj*z#?k|(Z7(L)6+k|+T{%+)sf{RAVer6eZ9zphl0S`oAtaqc0w{v~o?)i5LH+_p+ z#me%W^6tCluW!GcYMY|sk%Lol%#h|2tskEUXBP6)ihKGIa{~0zjX0hW*o#hH&aHMd zP{zg{6EX8!I-;d}O=Tg{Y@m2UW2($~wfiYU`XQQ0e0ErYu!ll=b(DF_=j!&N?RD-XC()33q=+s&>LGVQ>vhzagkym# z1M~LeitM>ZJOZeO+2dw!xxh_O((XlA!NW0MS-nq?jxjfbtK_e@OUWR^*T2q1r>@7W zq2y2-`<6Le!bC?g(XmmRT?8Q%gT3an#{^@&^_(n&Q#a53c{I1(dLGSl|>IZIgI6 zK-1+Px3RKl|1#P%m(CI+`X8*%53GwH|5jf3w7+frqr3S0|Dmq@9|at){de7b zF6eKPz%z`06c?Bcz4IS|Z~R@DYH4ZdwNhv{!=x86!#oS~f`k&^{uuys>YqvbtX=fl zC|SkqIc0dmoa&S*JzUqnTVU+<=PCm=?_V4gbX4OK>ay!Yt1IL@O>Ff3qhe<2r;Zh4~ z?kPcUL^L0-OEhs$E+$i&xe)w$#EPd3EV*Q1ne zQmQ_rYL-1-FLMC}5XW%z3I>rfuL|!|1Wr^>YgB=j$2<-0S5yG1*TI`9x`(^Gqh@S5 zq*n5@jhP_ki2aFX&Vu#sTFa}kU#PBXHcu%Gog~-_-VCLP6nkkIaD}CeC;NHFJ~agY z!ku7F@2W9f62n~nrj}M1LU`ik+Us_y8Lv=5s&mcTKibxF3rAkww;GE8FJBM3A~$u? zl5YuWbA1$aEr6uKt}rQ$|G{%HAr&e4%pg`Kq}XX7%(!g(_U!}&B%TJo1M*_KSL)NA$S7VfkyY8jnYHXGvT0V@16HDUQzRq8L- zkqdzBF8u^8wW_A%=P{wB4ORMgx3Jw)Il`TNtFvl_r6lanhc9p;H@rblkM!2YZ64`Y ztK@&r&iGEgUC}>Hz0H!hoJ>d63!vKc5Tu-2eSd0nq{$NDnf2Zh3C;(OGB@T7%}q0v z7{R$ZEv!!)+*lnd0?#TP-a-GGe74TlN1k^5UZ+AoR#&W_|2Ry!*?ZL}kfEr%H@l1R z^BFnCXSc?rQ_Xg)Oe!-Xsy{t3WWh!jjed(>8hv3!TfsgH%sTZ|xcU<=8sZe0by{_w zG=Gcv25JE0Zo1J!Pzrviu3AooG_43l7Tv_ep^QeLM2qL)VUFRESHfeMM=%6qm=<&# z)h_mj4IM?gqkB@3zKgyKW9p=o$jUx&m98UbVtC1A%qq?u`7M79Mk)b8TJl@b^yh+}PI=upz-&vh>!w;ML8Pi)vD%o5S57q&LL*%Hbfw6)p3k6$MaKp4+WBxTt+R|Pu&FTEF40wZQ?_tiF z7bejJgY41(2hcszcW)ot%TZZQ_Y_^3e9?zR2l>{#wzLn`v$P9W$HM{N?{2hU2m4ft z(uUaMHoXBKk6@!OnpWnqE)j*)x4x1j_Yg`9a?at|q26^En;;73oPOOQ)gYOdE84*b z+i0BR8@1(6C@uM!WKF#H#g()vBaMgyRNGqb{u)NWuPKwa3`}UV6)j6J_-JE;SQbt(5aG;xE(I zih+nsLnO=$>-oRMi8E&Dqa`+RMTt2Vzepxu21oju2HwsqFflFx`$q#B;X-+eb=0+p zO9Eb;nyO|jShgs4(R6Z9rvPe&=b_*0%wsAO`Ahbn^a*>~Dm1V!TemLd%EZW?vN>my zMpuH9;kDC;Df7RQB&0$mO^^9P3F{R;1jC+F8KvmdQ*X0o-Wvlw357EHWExRz4|j~% z)K_oI6h0<~GroWU0CSIdWgscGl1`4Wy;F;3$(K=AsJhzu-nbA+P|EDh;#P@pR5nW) z_W8XYn16+p*2;$3#+=DUh&+>T$;CZGT8Z3}^9DIxb-0SubN}^gH57;7NtGbqDykDD zQu(n-i(&>=IGL^$C=uX7F=6yWn)QV0MbOEN4O>6OUAvn;D5bMm&^a zN+FGL!w$QipXeeV8(x`Yw5KCbG5^c3$oV8}S^@gI;86?HxFQUe4w;{|3x_C5?%Ft# zC{C%UWzM8>*c)rBZc*_$4b+{D;^W+GWwf-XeN6%R*T1WLX;duMO^?hMKfY8w!)}3p zksF@Eg@)gyCl`HzSzLyZ`pSg$VB`LDL!$-jfvj)mA(i5v)H?C@WFP=C*uKT{#>kWqB`b+?9$)X3}c6O^qVvbD^%I{RRsC4 zJ2fTY`k#VKNJ|h$?{UbN94}uAOyeyBj6!+PNdAQ}ETfWA!p@z}rRt?>)2o=@a79>8 z$Z?HiwUFhhz)zE4j!!Nxv2@W!fdn)%c@hH(LI(1c(1pWU_@k44lZgmbJ;#e(h_RWm zQw#+nM&|e&Bcxc7_wQgP;HNnanHy!VN^L00AO^ zo0CmcB7nblV#9nukcmY+9OH=G%(4U=b6Pe*$`U=Op|65TWNB$s1cW!p^n1r?=GrQa z3)+k7rzLk4HfBdS{ASINH%*h_FJ^kQvJ_^<3l6*GKpWZb8FPMa%kl#E%wzgd}y7Z-z zIY2xwvmDjZk&T9&Fh~i?Di)@+Oy2})G4M?J||6GgX&0euEpN==d$O%q%iHTd}OHVgOEZ zJ=KE%K!KK4#X~BQ_Z_F!+^MYVPrut+s@(wW!=T{!`9G8ZMg5WI^c~?7*l*$FC2^yCh zZl6%Thvd(dh(nb>FJK%P+q!pSYM#WUM1)c)60+bp+Cv>bVfb9_ zFR!j9{YmT3G@hy6u-7|W6r^sCYpUVyM#nv?=+8&r297CPpi}1!{t0D|PHmv>o?od9 zL8a`|nik8(oZ@*h$*U4b@hD4B`L5Jleue!pvR!h0%BF(H8|!O{Q!uFF_1HH$&~p88 z*9GX!+O;Ne?5cZRq_hsDi;WRnG)h@ZO81mnK3a(Io?Dl1Ud?9zcjs{VFGS@Uq0jpqws+n zUrp9I=^Z#H%L^^)dCFy@Uk*pL7XAnf7zw(po0Om)6bsgcI|1(iZx89NKk{PLBT7nX zzV2)&_izTkA#r*g71%g4UM5IAQH=}U4HOru4-78a@Zu72XgYnbvvqq$Q1eemYAhOm zm0iZZTW?*M_8RlLIkZ6(ywYxx@|@Po%*wjCG)mjkolr>@9DPdMN#8vH^d-Tf1iyj3 zcE*X^#(6Znc4mlcjqYk8TWo6{T84IdK`IYq_H^dmi5N`mcqze380C3A-})4e1FXZWDAGx z6|KLhR7HpVH0F6kHBzSDxr3;H82K7=y2!FPw9@qU=HzjX)uySn^v@m_|1)zv+iZD6 zq63^xG_}~VxU{%zHw7-;I^Xn_s};DMhAVK*G8QcS@R7^|_%nvz z%|rcJ?q;BZOPhBC2?#w6A9|xgL}0fG_cW8aHP7t2eFZRYpgO+eFUaop4jHSKU8N!8 zZ+mM$h9 zAAW6OC7I7o@m&*b>gTq(OTFpJID<|X3jBC=@};AJWesI<-s5}t0D+go4Qk`cJI4XL zHorAr#zN@h@uKNqwnWi5eq-_IS$rZ|_RNp+)V{2l|4TZGralFI8Q2^Z?D_D%^Zlj* z`s+@9`T?=f8u9Y@%ldtAwcv~WrY@X&hpmx$n=V7amr1WoT`H=E8H(r!kzsJ?4_JQW zIY%?z%WX|Ki<(BWNLnNt1?||wUu~*lUiV}j@-CK2U906RW2^w{gDm5<;l;qjvdj~n zC4*CQ_EgQ5ARP&_<9%l8wX3wfuGmut;pTBM1FiW#ghgq*ONaS?@?k24T|Z>CyNJ=;Vj4il^Q}C9#-)mv|6I-_B~E&z80!nL5@g9>Ga=0f;+WuxVjW zrBFJQswZFi2AZ^INL7+VlYN^DDW&3NC@q~coftAD3WM}OdU~eY1C)WqxpVWYYkRug zLOK>Khr@~J*1c!-sCRer2r;#<%E3!(ZkHKMzKxBx9y^xn3rb7{Eh3Zrt6$$KB zzfu!(t+dbPxP6bSMOl=}Ryve3>uXj6?+a%KT4Y*Zfz5yKk0=uZ=uS)vpX5MDE4k9z zW>yv@KYv!q7?M;vYIU1E?ADk*xKl;B_sR~OH9}P8&ZFVCHDeOP+um-S#zCG&ZD+?i z+t`{4>q{#>yx12!^!{F|%D`tiwQ=`4;CeUj+gqT(TLbL?-H9=(hUSzx-w#HPT0$!h ziL9KiKVe$(9e!5gJfrG>E3RWa_Pzpm)y7E+In~LPS<+kA7#YT|N~Ip2GZa&%+xlpn zYz6|;CZBDk&lJ9OF(~6}B5MYgenV^C!r{CFIk38I)5i|>DjDi8TlQ!NhQ;H@u4;Q0r?teMa?&nO$ky~R67qS-&ce8OeV^i#7~qI(^qMko z`4)|sEEi@}#Txa?ps~2B#NU8*R)g<%@g-29XttoD-s~1asf~S+ZwZhvOevTC2vhAN zPPWxiSIuIAAIkJ%y@fw8(EiF`>M;-#f>pe_r0YXSEJQxO1l?qq6WExdplrnMsKDC#NgVdK5_M@}6f8oay@N{*Tf+=xt0>J&GkG~Ign4Sg{WUHPS^ExKm{JxcJciab zR%T{Lb`#A>luq4NeOrHGvE$ON4Dsry4Qn1~tQ@rXjZVxh%*@Vi1|!NoUpi$|wb#|- z_E}Fs>aFp0fGf&UOm6*845dRptTXyn@mbC(7u{t3yogQP*O1S(xfQE3OZ>iUqYO*k zGDlPE+`*$9z+S7m60Wd?Q&Xx^`@7 z=j`&_<50Ag2??^aC>+vysDO9ezr=?PEk? z;&eFp5H5n)CdZK96fwOb3rm=)DT_ck#(hpJh*lXn)@y{f<7JuHFMNuNEr3w_N5Gv0`43t8`;{!1ruEoW{{kjZ z)gz8^m(|@ysqg-p*&$!5rYJ(GDr!-fo%#uh6zx|#rREA6WNpWdkLF;Dnwm@VzLO`+ zF{BY!Y()k+ULkFQ9ft<4kl@`WQwIohI-P1!U&QL+H>4LSsit66D@VEqNtKF8NEk0YWDMr3ElS7K+T_vTmt@NKQ3pSKr5L(a=@Y)Lc7!lw zg1WF@=ftFBxwK3q zWQfD)2Xwft+2MfC8;O+lYNXqrEBTszhOkSvwLw;tF)TT=henV_92*^wod9HZQbpHF z$%dq4ncW=pt!&rGlFmTq-7q*=Q@6?$D+MmP2d#5B!*2%RB4pU!da1?-dl<{Zhb}2R zAhnPV#_(OVOfiV*j}y>gw*_F){;&)Hj=4&mU*wcYvD~&tFPincmu3_2;n zDf>>%uv#`N4KXop@SILkwjt{99X)g`jAVrZg}8=)+j5)~=(A%W4***Hrf zhI;uA62W$Ex7KduA;Wqs1l#2(3{H33TQ|u1!X*^w7a!A`Jy?m-sn&87FnCg=Fflvh zQvb|2`ieMJcRb1wU+mj`XmecVVT*(mfAz|3;0@YhtnStuw3^MeQ45CmP*fZo-j3>S z{n8g1oN~>;Usd}|mn8tmX5pAb1^)QZb6M}YDVKvhz3Wu^~*8TI$_m{ zu8TgVPc>-t9@-a!I%_c-HyNT%7T)5)C(UP6@DNH6%T*E6-J`LfENNU}rzBVtIxDdC z=RwW|(#m^cqvc~M)wb}f9gwhw5vtwlg_Rys5ry0^M#leV@L5JJFgTJ>Ty=0{Nr3hC zG#RhiEHJwIE>t6>`lx9t;En`xa4EOjCRQ&r zcQb!wyw_Wp=*zlg#TVY;3vAaN)BS|8v5KxWeho{c3GXs-*!&?nXIf`xO0kK0^K-T< z!D{IZ-@6sHt{VBR#`ZOe+TLLa$4)W=6*jGj}w;KovY% zIImKS6B^-k9W(lk+7L?yWq#z%=6zj(yF8p}F>t$-%GkPf zQ{+X%MO`CANBQx-R;q-QFngyiQGd?pjwu#pfuK}-{ZEeV5@`DmZt|#f(II=$K+V6q{<kB-2H9{^-Clu(lix|`J*zMM zs!D21j6dx(#5)pK@L|hgW~bKZ+9z&Qf}^d>_fHdVyqyfw+c&hX@6Q`Y7M55gh+rz4 zUKG=gzih2~L$c?TZn%PFu7u{+98M|9Yn!3PCS}2P>_^>xt9e#>NS*A0P*9Mn(jN!g z6)ZEs$@z81K1e0R>0K!MLW|C!>*&g=jk)#dX+E{W&lUCsexfgCGWOdC7o}b+blX{< zaIZBVQ2Fjn020=RGlfJO9i~KmIiy3Lwx2(N@(ZKQzdPTsL7XQNkqXs_t#vQuco&2} zCs-|HB8pr@i2*o`%&pJNLLeUzH?Lr~^*mDR!RpM1_6S(VFWXm;RUUM`Y@ag0&R_YI zN^ad#Mi&eeu>L(enX;5+g%+goyy&-UtT{=$QC(OW1)oQ+ofl!HKRpGA&o9kZ+_)#*tlaGRe9e#VTI1HqA+Y*KpM`5b_s)^f$?ITCti) z*SvXq%#<<0CfK9*MNzu@?M1#_!@EL)Neag8cPX#Q{LY3eQzTGBQZWyyzI9$G0FzK#W%fPlr*s%Ks)kijBHx=9)ZK!g#N>K;QGdlp!4dH*3z!g@Sa1 z*JnD0acSIn`3k0vaDlXyo4%K<%93YkO4%uhu6jFYYDV{g2<5BWUfc4S*LY-x&Ql2# zBfnzDa}o_~u2t`SSgr664-G!)taBb-_4;!PCCrNvofb`IL5!~-1c{z+BG)~_c1}IA zcRHlKPp;QSekqmTZ%i_I9l8*AVv41i#XLV2uBE42G(%3QFoO)nk-Rq%Tdx$_Y+*J? z&Z&V$HYhsUs+6s4Kr6IQ(riZHss|W+*OIfN{hx6Tg$Idc(g~8kkR^wt0?Jd5P%T9- ze>5G1qndcanrVnu4FhlBpLEAZ+<*>bCiAS3;uasu(XIw(`!MN6jDk@)Iqc!#3tYkw z>`Pr6*Hn1r~lM~{e6TlkSfO$sf)DkM3*URzmV(<6vOu#*&%eki+VjP*2QY>u_VQZ&`88GxRnz<)Q!en^js#VNFHHF@M93GWT15AS#x7A~nNJ)z8DXXj~3nSsmX; zwaD|_@=x)Bni^@HEe_AeKRnTzvr!27`izG@SYdmI)Urzz{g_G-dAmv;3L3vmB`1EM z?7%L)*I#^&dAN*B%vennkH%PpUu%r(g;iH0*@TS2XDSIACNvP%@^H4Zt38_B)oa!M ztu3YI;jK0A!n|D?nONlZMt=)(z*l+1%a4gxQrDYLFglb{4#8(K?v|j&K>RhaV;CUC z_c=~)FU4qS+znp7&yY(J$?RQlYWinHsl0nbWA7;zH>cQ|hRcw4nL$ZPgS`4GX|=N% zF(gG+u-MArqG1EUlyJXsmiEne{6^3A`94WTrd)z5Ykz++_ySz;ZV(C)KWV5KH>~mP zvy0a?@zIe~AT^#*&VBtC9U%8<*~}3gIrR{;jG|9U#Pk9DQocHny(!o4Mdh&=-4e-C zZFxIE{+El16d;A}p{98M!G@axpe=aSft_$@)8es}oDY07TaR(ug$JHJKD;@nyp8Ny zJm)r*!uz16WYRoyw@4KaRWgITJkZtw2^5|JHVxI~$cylggKd`Udy$XDm2T!k`K8iP zpCbVfYUeWsq^O9IfN+$xa{rz}?si|_Vb1#}UFI$Png0ce#|hodbKP%>LyTmz#Kl3O z-#b;M4ul<(vbDDFB}S_Fqx}wK7x|g1f-y&D90$K7!9loOmQd$0aFhe!*>aGJ`Mj9T zY6HRS_a*D+k+t0@>qHEE@6`?*V&98SN>ELdvh-Ev>;L~m#Eaxv{MS4@JzBR;;~G!C z+xE%w6sSc_NeP`0f4|31{8|ox#W5};hlOupj*(%jp<(a5jjp<4V*VdAdn~zAd^yEnVoNktJ|qC4jz2~mp9O`n$cE2}ui-1!Mz$rLCaps4h-MQlt4;;Tl) zPfIf3oNRS{+@Rg3BE`4RUSc^`?v;o5PzXrqn?#k%hhIDl7?P6jenvCLyZC0`392E~lqc#Vlj_zQ8t5{~9%y(y9^4o0}y>yZ5?cES#2|x*48-Z`q96 zRasjqRUt!(7Rie0`C6|t_8)ZqbtKmz$b^kT)Gq@jE=h9o`N7TE$ZhSQhqFTeuoyp@ z1bjbLjQ+pS`52%v_`MzpGPLaxh`u*5O_H#5IM=51YeHDC*HsmZcmH2EVcP zDvL;qMAWqnpP?>9Ve-=odasND>2k}FZ7i?-nDpgSWhb5M+Wz16h7JWjic@FD{{*^k zTsdqieyUG5j5lc#bmZ=NOzQzq-;RzqWw?IiZkcya`UIbvSl0TjPxm7_Yq@s1Hv|tw z1`~hi_f7|D%R^l1Kyo;L?6sESt~$yXT)dMa4`&3~)rRMnXco>eGUK2K+ka4gma{=+ zcPI2ggW_=|XTb??_%baW8SD&l3f30OrSr9gx?b;ChD0t{_2bZ?>Lruu;dj5-M z0d-j`@*S7EC{W8CQ5`wwYAYv^dOHWdr?Yc|a;Qz{|3j~UouS(XQ=Sq2*!D{Fj_oe2 zi9ldR?n#4ubRyPSTDr7K%)y7T%nq&+L8^u?-}o?EEmOsvq$Cv@15jE#|F2$wvRl_w zH-gnB&XYK*+^U7u*WU9nL`jtu+@4dZ+EG66c~?Ik2gW+zAK5I?{Y(6cX6KW>(~6!a z-1=;X*Bb^)qlBj|@8hHzE%Y6_@W7_|)7}{F2M>yj-?rgW^A9xBtv$KJi^|LlCW~t@AdukX=G0`T|w$< zO*S`10V-~-cj)lq=g8f$N{pd4d3~Z>TU|vvQmd?@`;W83HgP8}q}75QhzQ~j-vvYI z9h{S?mGUJ`<9fjgaWEnP3gS6V0AhS1XNmQ5(2=wb=s24ITA>1y92*Zfeh@ky)7LEE~jfg z3P)!D625)5B)Svx0bV#~KBE>6%<&*K(*dq&(!a#s>#u7V5FZ1CO&Ln_#eXBe&;bd@ zkK2cbsaYUBT6>VFX}@+OjUSIK@^PN_Skuj$P-RNyw;Kb!rOF*#h`D6YM}&Is{Ti7s z2%VL`M+tk4JjpXTd=T|BW}=>+r=H>`XHSSl_+F_H zmrmdq9W+&=7FV1?OPf@xi_rAYa#^*UqX&%WFjv-l?2(x^o1VS?khM@!-_3e*1>kCo z9-7gzaBrYTe?(=wI> zZM`ZWm;XDei#Vq;qjIn7vPE1R#W8Oex5*qI#%rf@P%s`X6RA^N#A8`1vEyu&w0KTD zlUIM&(}3y8&Bc49rkZg2D!_=A%O1(JNpBt3h3?=L$RyjJlY!o*;Ln=${Vl;LOEiu> z^G-IB+k#E}wK{AY=zpKA>=SX-{jjO|G=_5K0;T~Ag8BF%LK4t*@3zZU?tG!!e0 zg9uz9L+mTiE(tOwvr4%5S80Q>?eZy}RzjdRhpiWdIh}QB$t7we?*L^WyHme1=EzE3 zpoWIAt%Xw>8Pn_pn_Pn?L(Y=szUiE zz`p}!S%HDX+D>=(@{>tdfN!EOFs;Ny%QYsb?!TDFGkbymW0&q*x5{zt-2Gkr^249n z=F^Igu=keE(fs^lYx^gifV@|48?LgSzWn5kmbsZ%`q{(pTv-@yGM}jdEjc{({^S1g zjMTdicS*6en6SBKu4g0>;Xp2GQG9W_$4ei`6#CG*z+b3|2 v1q^_KBmaRrC;tD}lzUbP0l+XkKt|_d_ literal 49081 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%0D3USsty(QiGM-t|(Q{zGi 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 diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-3-.png b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-3-.png index 455dc7d068b5f8685368b45cdb778c23ae02e434..38346c64df1a612df4517da77c29cfbdb2b184dd 100644 GIT binary patch literal 56888 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∾7w*C_pXfpoyzj{=E-+4RR=tO`_fhEAb}=@?c?Nr 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 C7KD+&~%jeoV^koNSCx3 zR;h^BOT4l35NOAtGFhhVU+l<5j_8$b*v0Lt5PAv`68x!kvafuQNNv6B-C>?=tXfb3 z(K(#=WnTc^RMjHhVcNd={ozv*>!|{g%%mrky}m!7Y=M6->+&I6IT>IO)NTL(Gmc*@ zw)zcl2or5u*e_&|;Kth_8&Z)eU(;F{}(!`O&c9vs4Sgm zV88tHCWE=R`p`IE+W0J;fu46hqq17(?EZ_ep|HkW(z${kk@qBU)b~V*8(d=NlH=!A zGnhJo6k5_36?|R*ZeG>XHc+Exw5W>xx`F)0qFGV-8UYR?HaJs__Qc9ehH zf?o-~|Nd83Zh`av|0<=bmBQ2X)o=*4L)Ax7npE4D9>ob~QOSSb{!Wv_yDwNKo%H$8 z+Z@D7i>BrMZgQ*ZPE0ZIEo+|&CHx^v(Z*){ygq<+($(shKR&1}FUeybH?aU_w3psA zZPjP_TNQnIEC=w`=IG{VT<(d8HN9^bL)X^~!7bx^`9KapCtR}TpXwT)G#Qv73@d%Q zTZdPd-%6AdEdge=He8wVpwliZ2dA3)-aQ#)G>b2m^Q`k-ZjEP^ca3mL6D-j+ASE8f%hzb&sx5|Jiq;3vyov}WEW|gh zJr=sY7pq~<-_?_(B9605Y9@lpn_CSA_DAjXnJgox7hsi+hK0i%^}2wcm`erXo^oR^ zdin~3mZG}$jttb(w7cnom6oQ<2aV81Wx*LpUS<4zLV0WGbB6_84V5|zm;fG4U1fjeV6f*Dn58J7}JJ~m; z042&fk>_1=w*`OKJ#RA*lN`B(G8$YiRvTQgGTjXxYlwAL7P-`CA@uL=TDbg;vZstp z6x-jhD9|aPaaS0zkbC{Vn)$A~rjvsk;jm9Hd0 zhuJ5g3QKsfMEdVbR(jj-*G_I)#uF2_vv8j`5_s?(0;rSl94vovf+sT77_QE1R zhMw0$aJBV?NdtEAhq00ZF(*7%jtgsv{~!Ubo6(`0b5+jfJ+}&HbxGu`(~}Fc8h)6dk?)v<@s~ z4gmWqERff9O4n7vbw^S1k@UFkY~d%}Do$nY``2;=GQZui>F%&@y;Sfnyv=itz#Ysk zC|FzNrW{fw@6>pmaO~-Y5C>g-Lyrn<`(yZ|);_Q*ytfh2`+A~vh4xP06k@LzW7_kT zjX4V7msz1uKzo;C{7ZE;M=Xj&RlUcU1^goTam8?zt z6+%cC>3P5!7yTF4yUb4XxR3y+6C1D_x=ks2F1}<|{N@;RbNGhlt3aIiz)oF%XK>wCe$-BymC@>ZcwAx!Dd>$f8IuOmV`y2~o}d-uxCl6;aa zi`=SQT#7E&sP)s2eq=Ql$}ukucU@O`{OpdPkfX5JJ1X93Xg2Togw{NjG{u=c&eN8^ zQ*Q!mw))!;m2;6{t!$WHCm;W4zAN$$bs0ALbd~i&{Pb!%*8B;7`fSz3;*1hd?z67$ zaeevqUoHObgW~Jvu*2h|cRpZ*d@w?_Ew{Hp#|4R{$Mx)oE@tjw_7xlZ7-Kxb@*4vB98S|%v&wxey z@8^h!sPvyhRE+Yuu0Q@m_b=6g8ec14%?G|yibye6ZaDK0^ zD;1{@zh1X7?|u!xdb<7&z2fn`FN32gbmtTw#xhlZ`PLYF)_JdbeVqb$JyE@F>0wU`$P-co2Zje&peHL6fu~+d`5lL`oF}+<|5@!pVm0s6{Wr38 zsfG=OH!5uJiOn8Q2K~;?*X<&3ggt-lAUdbXhfM>)y`YQ^yc#pdD}XEe)W-&!T{5@4+R zBbnVqdq%QO3r&h>5{ehpR95%O%9tr*G|{i#VV2J^j%W~IdVr&(I!Pw96 z`69aOfkZnje-LEOdAJ`e`kXEQq$Jwk{Itn-klde-0Qp6L&Yc@Vk2JM`di7%@-1Y6xe*JL{j5ec%(A3mgZ7 zJxx5MO@!Oo-i`I|?)r&gxDiIRw4=-Znhs+X<=X)mz3?H)1aOj`YPuZ+v<1#+Ztu0z zU#4POc7Tknv9KMfui#x}pXXNSv9NN&k=aHpR2G=)IEULmUTK6&%WURy|GH!O5T5E( ziMk^e)Ndp8XPnQo8O|r6q@dLCq#4^6l3^{BCdkH?c9{@+@@cRnn;c3fu*BMi#6e)d zaPZ42z`GScDvGu(53eMEUVi_N`T4;BRTDSKM$`Iuo0^#s(bhJ>aT_muQG1!e!}lD- z^gV~}y?-wJ&Oa`pDh)O$)ee8LO-#TPHM5t9>z?gs$GKe>G}Jl`biDp=GKuX;rK^Gp zX1^431<G{9jwbMJ5xWlYS-Fnd$4W#l5@XylDT_IXB>I= zu0W;rfH8^&Oq!ahB?y13-E8!3q-v6`a(1ZzdkSD5F2rrZCdzhKNMI?`_iJcKsPV_G z5NHVS7SZQRd%~NrQhi{-o-00Q_NBPgHA^qo5GCuH)^xn|SD23DDtiEhoce-Qbmaxj z%K2mnK9omMQBi8Eqp-3=Tv2=~hey^n48YLovdL$}^md)rzy{cLuW@5m0# zA|AV)E$Ss4&Y%UNjZ#&@5^*3=sZT}wX-g*+JCgn(E!YlSZHk?+F?AO+8 zI>()%#K#iW&L3I)O6RE~glK{5_cowNWJ;BEVDc<$;mQ(_n@I}X>2+tiEa8iKXZBe% z@|W#z^w_2q)6%8XpUg3D_IiON%0)X9(%5c?v5(8GlTO+C`qAY*C8c=3(I^#uC|P7R z+NXu@4|G;+qJRNWsx`@MhzYi=)Asw|uI{$S}pZWf`Q2^XbPyX)?72Mrlhe6V~?zP>wmT+e2VVZ&Ont z{a~r%-vGPPr%|<;2?2BY3Vm$j9 z{~hKGzInf;@hU=1)qth(*Zh5+I+P|F$33>ehd^jOzQvo~S;7;2n?VbvVKCIi;ZVm} zcjCQMZmt>)QWX9+ao$A3JSf8GnQ!8O*ZCzuXbSi^KhqFfiAQscvNeoNAJ1!Jo^@%R z)0S@B!Y11$nZBt(t9&5Ga4gA2m5_-YE{mCFk;3dM+f=JKb`tLrLb2ntJcROqo~LFl z2&$@MsMNN0##0bv#GR%2;sK+mCYIq9gy*-~wka8anp9BiTmL(K6G5hb&(I`lh1{O@ zSdw7wA~tGyFi>~Q*_~$8=<~9F5cnyzd==04F5SuVwDm1xHRd8#oWcrhiCpRz=w znXLzF{2FdP)JXCJ+8<3q4ZWL46dhD9$XE)lQNLn;{`X&3cpmZ1ZFa6wZdni6S?jXQ z(|lR!Ra5h(`#h9AECqD#o{?A_47qn-u_Uty;dmY~UNCtk{(@O(Y({hRxz*QUr(;hN zO@ubAS1@mzVE?(_LKZtHwpvZ;s7HMs`y$q8`5?a7)uClJhb~->m~9&~4eXj%7TEL` z=+I=@#vh*Kik2?xZOFCIS#*hy^J+iNX)5l^3UE)j8a)rHSm6 z(IC+WCj-NX`)CnB)8B_uUTe#Yo!)<^Xra>Um$uHIS-BZW*V~LNYm8E7D>U@pG`IfQ z{qmh0u(;R5`5sP!H1;-;GIFSu7IUS+2AqxbTS@&6pQ2SGf-nqg~#Q&9*WUc)h`Dk ztyL?H>C$NWqMS|Y^fQKuavo3Bn)`46pitbRe17od8@TK+vM|W(gK57aJz`3XzaPxN zn<>)Xy7ayS$szI`Hyvv7Y{0F!@HPO@wJ!*PrK|>^HB!dAxZ-g*?JJ+pDzxzV2rT`| z>KesQ_0-Vy`+H));{DweF|n2rMD+sc)xTjlDLZ67Ty=YfTs}h1IvilZGi#XW{MMB1{y$}R5H)aS^ z9Zi}V`>9RYeQ5K>$nK+A|BmJBV^Qf<08IGB`&A|e?BL9^OxtOA6fGND7%EYUk{(I+ zg+uzS;mP*dKnP;PC2O(&xeRPz;sEm1%%ui3@3Va8Y?X<(N1aEzu=-w3i}m5p&nLT4 zDq+0_gKE8Tqe>j7^x(iihkDoHZHpuFv*j?%kZfm{;aA4$5k9X~RuA&Pp*(?Xi%AaXt z;tZDk3)7j{N96LOQswzFIQ`aVX%TXuXWKdFWE-N*myj6CYBzDLT^pss_|Ffnu& zRAp%yekGrPWa?}(Znlo9-GZqxV zmqnFK0rSEi!ku5{9V;8dJe`EU{B`bx2rDfbZUA&#@AgOS{x%F0QKd!6$rMDJUJ-LQ zj7(vaY(6)hOj+eknQ^wwA2b(8t|#TMAa^&IasZ-i!SnrK`o6A}{yzsP#{(I`AMO(^ zNKV0a7gP?~CGZN7*Zg?p#4eiI%V~Q)iO97W2dt>N-K?z7{yu>WLIsfC1+ra^xbVYV z92nzULw6npQYhHMAmw w|Gz-7}0awIC^e3j!qD7DnVTS0rnhvB+)i&aP04dE4EC2ui literal 40472 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 From 05f8a3e32928ba43df31254c71e7f9d7ec21c813 Mon Sep 17 00:00:00 2001 From: "zoomote[bot]" <305051434+zoomote[bot]@users.noreply.github.com> Date: Wed, 19 Aug 2026 17:14:12 +0000 Subject: [PATCH 32/66] [Fix] Mermaid labels are unreadable in light IDE themes (#1285) * fix(webview): adapt Mermaid diagrams to IDE themes * fix(webview): add Mermaid visual regression baselines for all IDE themes --------- Co-authored-by: Roomote Co-authored-by: Elliott de Launay --- .../src/components/common/MermaidBlock.tsx | 107 +++--------- .../common/__tests__/MermaidBlock.spec.tsx | 89 ++++++++++ .../common/__tests__/MermaidBlock.visual.tsx | 102 ++++++++++++ .../__screenshots__/mermaid-gantt-dark.png | Bin 0 -> 9605 bytes .../mermaid-gantt-high-contrast-light.png | Bin 0 -> 9798 bytes .../mermaid-gantt-high-contrast.png | Bin 0 -> 10617 bytes .../__screenshots__/mermaid-gantt-light.png | Bin 0 -> 9954 bytes .../common/__tests__/mermaidTheme.spec.ts | 89 ++++++++++ .../src/components/common/mermaidTheme.ts | 153 ++++++++++++++++++ 9 files changed, 453 insertions(+), 87 deletions(-) create mode 100644 webview-ui/src/components/common/__tests__/MermaidBlock.spec.tsx create mode 100644 webview-ui/src/components/common/__tests__/MermaidBlock.visual.tsx create mode 100644 webview-ui/src/components/common/__tests__/__screenshots__/mermaid-gantt-dark.png create mode 100644 webview-ui/src/components/common/__tests__/__screenshots__/mermaid-gantt-high-contrast-light.png create mode 100644 webview-ui/src/components/common/__tests__/__screenshots__/mermaid-gantt-high-contrast.png create mode 100644 webview-ui/src/components/common/__tests__/__screenshots__/mermaid-gantt-light.png create mode 100644 webview-ui/src/components/common/__tests__/mermaidTheme.spec.ts create mode 100644 webview-ui/src/components/common/mermaidTheme.ts diff --git a/webview-ui/src/components/common/MermaidBlock.tsx b/webview-ui/src/components/common/MermaidBlock.tsx index 111919c649..346fe3c471 100644 --- a/webview-ui/src/components/common/MermaidBlock.tsx +++ b/webview-ui/src/components/common/MermaidBlock.tsx @@ -7,82 +7,7 @@ import { useAppTranslation } from "@src/i18n/TranslationContext" import { useCopyToClipboard } from "@src/utils/clipboard" import CodeBlock from "./CodeBlock" import { MermaidButton } from "@/components/common/MermaidButton" - -// Removed previous attempts at static imports for individual diagram types -// as the paths were incorrect for Mermaid v11.4.1 and caused errors. -// The primary strategy will now rely on Vite's bundling configuration. - -const MERMAID_THEME = { - background: "#1e1e1e", // VS Code dark theme background - textColor: "#ffffff", // Main text color - mainBkg: "#2d2d2d", // Background for nodes - nodeBorder: "#888888", // Border color for nodes - lineColor: "#cccccc", // Lines connecting nodes - primaryColor: "#3c3c3c", // Primary color for highlights - primaryTextColor: "#ffffff", // Text in primary colored elements - primaryBorderColor: "#888888", - secondaryColor: "#2d2d2d", // Secondary color for alternate elements - tertiaryColor: "#454545", // Third color for special elements - - // Class diagram specific - classText: "#ffffff", - - // State diagram specific - labelColor: "#ffffff", - - // Sequence diagram specific - actorLineColor: "#cccccc", - actorBkg: "#2d2d2d", - actorBorder: "#888888", - actorTextColor: "#ffffff", - - // Flow diagram specific - fillType0: "#2d2d2d", - fillType1: "#3c3c3c", - fillType2: "#454545", -} - -mermaid.initialize({ - startOnLoad: false, - // "strict" is required: mermaid renders LLM-generated source, and looser modes allow HTML injection through diagram labels. - securityLevel: "strict", - theme: "dark", - suppressErrorRendering: true, - themeVariables: { - ...MERMAID_THEME, - fontSize: "16px", - fontFamily: "var(--vscode-font-family, 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif)", - - // Additional styling - noteTextColor: "#ffffff", - noteBkgColor: "#454545", - noteBorderColor: "#888888", - - // Improve contrast for special elements - critBorderColor: "#ff9580", - critBkgColor: "#803d36", - - // Task diagram specific - taskTextColor: "#ffffff", - taskTextOutsideColor: "#ffffff", - taskTextLightColor: "#ffffff", - - // Numbers/sections - sectionBkgColor: "#2d2d2d", - sectionBkgColor2: "#3c3c3c", - - // Alt sections in sequence diagrams - altBackground: "#2d2d2d", - - // Links - linkColor: "#6cb6ff", - - // Borders and lines - compositeBackground: "#2d2d2d", - compositeBorder: "#888888", - titleColor: "#ffffff", - }, -}) +import { getMermaidBackgroundColor, getMermaidConfig, useMermaidTheme } from "./mermaidTheme" interface MermaidBlockProps { code: string @@ -93,22 +18,26 @@ export default function MermaidBlock({ code }: MermaidBlockProps) { const [isLoading, setIsLoading] = useState(false) const [error, setError] = useState(null) const [isErrorExpanded, setIsErrorExpanded] = useState(false) + const renderVersionRef = useRef(0) + const theme = useMermaidTheme() const { showCopyFeedback, copyWithFeedback } = useCopyToClipboard() const { t } = useAppTranslation() - // 1) Whenever `code` changes, mark that we need to re-render a new chart + // Whenever the source or host theme changes, invalidate in-flight rendering. useEffect(() => { + renderVersionRef.current += 1 setIsLoading(true) setError(null) - }, [code]) + }, [code, theme.signature]) - // 2) Debounce the actual parse/render useDebounceEffect( () => { + const renderVersion = renderVersionRef.current if (containerRef.current) { containerRef.current.innerHTML = "" } + mermaid.initialize(getMermaidConfig(theme.kind)) mermaid .parse(code) .then(() => { @@ -116,20 +45,24 @@ export default function MermaidBlock({ code }: MermaidBlockProps) { return mermaid.render(id, code) }) .then(({ svg }) => { - if (containerRef.current) { + if (containerRef.current && renderVersion === renderVersionRef.current) { containerRef.current.innerHTML = svg } }) .catch((err) => { - console.warn("Mermaid parse/render failed:", err) - setError(err.message || "Failed to render Mermaid diagram") + if (renderVersion === renderVersionRef.current) { + console.warn("Mermaid parse/render failed:", err) + setError(err.message || "Failed to render Mermaid diagram") + } }) .finally(() => { - setIsLoading(false) + if (renderVersion === renderVersionRef.current) { + setIsLoading(false) + } }) }, - 500, // Delay 500ms - [code], // Dependencies for scheduling + 500, + [code, theme.signature], ) /** @@ -225,6 +158,7 @@ export default function MermaidBlock({ code }: MermaidBlockProps) { } async function svgToPng(svgEl: SVGElement): Promise { + const backgroundColor = getMermaidBackgroundColor() // Clone the SVG to avoid modifying the original const svgClone = svgEl.cloneNode(true) as SVGElement @@ -266,8 +200,7 @@ async function svgToPng(svgEl: SVGElement): Promise { const ctx = canvas.getContext("2d") if (!ctx) return reject("Canvas context not available") - // Fill background with Mermaid's dark theme background color - ctx.fillStyle = MERMAID_THEME.background + ctx.fillStyle = backgroundColor ctx.fillRect(0, 0, canvas.width, canvas.height) ctx.imageSmoothingEnabled = true diff --git a/webview-ui/src/components/common/__tests__/MermaidBlock.spec.tsx b/webview-ui/src/components/common/__tests__/MermaidBlock.spec.tsx new file mode 100644 index 0000000000..428e3ae306 --- /dev/null +++ b/webview-ui/src/components/common/__tests__/MermaidBlock.spec.tsx @@ -0,0 +1,89 @@ +import { act, render, waitFor } from "@testing-library/react" +import { beforeEach, describe, expect, it, vi } from "vitest" + +import MermaidBlock from "../MermaidBlock" + +const mermaidMocks = vi.hoisted(() => ({ + initialize: vi.fn(), + parse: vi.fn(), + renderDiagram: vi.fn(), +})) + +vi.mock("mermaid", () => ({ + default: { + initialize: mermaidMocks.initialize, + parse: mermaidMocks.parse, + render: mermaidMocks.renderDiagram, + }, +})) + +vi.mock("@src/i18n/TranslationContext", () => ({ + useAppTranslation: () => ({ t: (key: string) => key }), +})) + +vi.mock("@src/utils/clipboard", () => ({ + useCopyToClipboard: () => ({ showCopyFeedback: false, copyWithFeedback: vi.fn() }), +})) + +vi.mock("@/components/common/MermaidButton", () => ({ + MermaidButton: ({ children }: { children: React.ReactNode }) => children, +})) + +describe("MermaidBlock", () => { + beforeEach(() => { + vi.clearAllMocks() + document.body.className = "vscode-light" + document.body.dataset.vscodeThemeId = "Default Light Modern" + document.body.style.setProperty("--vscode-editor-background", "#ffffff") + document.body.style.setProperty("--vscode-editor-foreground", "#333333") + document.body.style.setProperty("--vscode-input-background", "#f3f3f3") + document.body.style.setProperty("--vscode-input-border", "#717171") + mermaidMocks.parse.mockResolvedValue({ diagramType: "flowchart-v2" }) + mermaidMocks.renderDiagram.mockResolvedValue({ svg: '' }) + }) + + it("rerenders an existing diagram when the host theme changes", async () => { + const { getByTestId } = render() + + await waitFor(() => expect(mermaidMocks.renderDiagram).toHaveBeenCalledTimes(1), { timeout: 1_500 }) + expect(getByTestId("rendered-diagram")).toBeInTheDocument() + expect(mermaidMocks.initialize).toHaveBeenLastCalledWith( + expect.objectContaining({ themeVariables: expect.objectContaining({ darkMode: false }) }), + ) + + act(() => { + document.body.className = "vscode-dark" + document.body.dataset.vscodeThemeId = "Default Dark Modern" + document.body.style.setProperty("--vscode-editor-background", "#1e1e1e") + document.body.style.setProperty("--vscode-editor-foreground", "#d4d4d4") + }) + + await waitFor(() => expect(mermaidMocks.renderDiagram).toHaveBeenCalledTimes(2), { timeout: 1_500 }) + expect(mermaidMocks.initialize).toHaveBeenLastCalledWith( + expect.objectContaining({ themeVariables: expect.objectContaining({ darkMode: true }) }), + ) + }) + + it("does not replace the current theme with a stale render", async () => { + let resolveFirstRender!: (value: { svg: string }) => void + mermaidMocks.renderDiagram + .mockImplementationOnce(() => new Promise((resolve) => (resolveFirstRender = resolve))) + .mockResolvedValueOnce({ svg: '' }) + const { queryByTestId } = render() + + await waitFor(() => expect(mermaidMocks.renderDiagram).toHaveBeenCalledTimes(1), { timeout: 1_500 }) + act(() => { + document.body.className = "vscode-dark" + document.body.dataset.vscodeThemeId = "Default Dark Modern" + document.body.style.setProperty("--vscode-editor-background", "#1e1e1e") + document.body.style.setProperty("--vscode-editor-foreground", "#d4d4d4") + }) + + await waitFor(() => expect(mermaidMocks.renderDiagram).toHaveBeenCalledTimes(2), { timeout: 1_500 }) + await waitFor(() => expect(queryByTestId("dark-diagram")).toBeInTheDocument()) + await act(async () => resolveFirstRender({ svg: '' })) + + expect(queryByTestId("dark-diagram")).toBeInTheDocument() + expect(queryByTestId("stale-light-diagram")).not.toBeInTheDocument() + }) +}) diff --git a/webview-ui/src/components/common/__tests__/MermaidBlock.visual.tsx b/webview-ui/src/components/common/__tests__/MermaidBlock.visual.tsx new file mode 100644 index 0000000000..c8c95e7090 --- /dev/null +++ b/webview-ui/src/components/common/__tests__/MermaidBlock.visual.tsx @@ -0,0 +1,102 @@ +import React from "react" + +import { expect, test } from "../../../../playwright/coverage-fixture" +import MermaidBlock from "../MermaidBlock" + +const diagram = `gantt + title Project plan + dateFormat YYYY-MM-DD + section Planning + Define scope :done, scope, 2026-08-01, 3d + section Delivery + Ship release :active, release, after scope, 3d` + +const themes = [ + { + name: "dark", + bodyClass: "vscode-dark", + themeId: "Default Dark Modern", + colors: {}, + }, + { + name: "light", + bodyClass: "vscode-light", + themeId: "Default Light Modern", + colors: {}, + }, + { + name: "high-contrast", + bodyClass: "vscode-high-contrast", + themeId: "Default High Contrast", + colors: { + "--vscode-editor-background": "#000000", + "--vscode-editor-foreground": "#ffffff", + "--vscode-input-background": "#000000", + "--vscode-input-border": "#ffffff", + "--vscode-textLink-foreground": "#6fc3df", + }, + }, + { + name: "high-contrast-light", + bodyClass: "vscode-high-contrast-light", + themeId: "Default High Contrast Light", + colors: { + "--vscode-editor-background": "#ffffff", + "--vscode-editor-foreground": "#000000", + "--vscode-input-background": "#ffffff", + "--vscode-input-border": "#000000", + "--vscode-textLink-foreground": "#0044cc", + }, + }, +] as const + +for (const theme of themes) { + test(`renders Mermaid sections in the VS Code ${theme.name} theme`, async ({ mount, page }) => { + await page.evaluate(({ bodyClass, themeId, colors }) => { + document.documentElement.className = bodyClass + document.body.className = bodyClass + document.body.dataset.vscodeThemeId = themeId + for (const [property, value] of Object.entries(colors)) { + document.body.style.setProperty(property, value) + } + }, theme) + + const component = await mount() + await expect(component.locator("svg")).toBeVisible({ timeout: 10_000 }) + + const contrastRatio = await component.locator("svg").evaluate((svg) => { + const section = svg.querySelector(".section0")! + const title = svg.querySelector(".sectionTitle0")! + const sectionStyles = getComputedStyle(section) + const titleStyles = getComputedStyle(title) + const fill = sectionStyles.fill + .match(/\d+(?:\.\d+)?/g)! + .slice(0, 3) + .map(Number) + const foreground = titleStyles.fill + .match(/\d+(?:\.\d+)?/g)! + .slice(0, 3) + .map(Number) + const body = getComputedStyle(document.body) + .backgroundColor.match(/\d+(?:\.\d+)?/g)! + .slice(0, 3) + .map(Number) + const alpha = Number(sectionStyles.opacity) * Number(sectionStyles.fillOpacity) + const background = fill.map((channel, index) => Math.round(channel * alpha + body[index] * (1 - alpha))) + const luminance = (rgb: number[]) => { + const channels = rgb.map((channel) => { + const value = channel / 255 + return value <= 0.04045 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4 + }) + return 0.2126 * channels[0] + 0.7152 * channels[1] + 0.0722 * channels[2] + } + const lighter = Math.max(luminance(background), luminance(foreground)) + const darker = Math.min(luminance(background), luminance(foreground)) + return (lighter + 0.05) / (darker + 0.05) + }) + + expect(contrastRatio).toBeGreaterThanOrEqual(4.5) + + await expect(component).toHaveScreenshot(`mermaid-gantt-${theme.name}.png`) + }) +} diff --git a/webview-ui/src/components/common/__tests__/__screenshots__/mermaid-gantt-dark.png b/webview-ui/src/components/common/__tests__/__screenshots__/mermaid-gantt-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..a4925cb0a5d14a8217c43b0ea29fda45213d1db9 GIT binary patch literal 9605 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 DCo28_ literal 0 HcmV?d00001 diff --git a/webview-ui/src/components/common/__tests__/__screenshots__/mermaid-gantt-high-contrast.png b/webview-ui/src/components/common/__tests__/__screenshots__/mermaid-gantt-high-contrast.png new file mode 100644 index 0000000000000000000000000000000000000000..5cf08ac4cc411b7a84d7954774b52ffd6d79f3e8 GIT binary patch literal 10617 zcmbulbx>Ww*Cl!*5D0F;CAb9%?gV$exVyW%1-D=qcb7me?(Pm3cZZ9+%kX>kzWQeV zn5vog{^`?os#fjZefsoXd({e8kP}DxiuV-&03b<9h$sO79}eE)BilD9R^7iGNI7-LA3wHabpn>}bOpopZv|7YrC3-J%wjOD&6Un^<>ToQ> z-3swebkPeth*FWqFX>E=4{S~m@W#{;$sazZQzIH1{p%VZhkeR+pb=!ci8H?UnMY{o z;aY!LxP3ZqSm#;>i@b*)ji7j6g}y3D;|D!NW!&Z*>itcV4=!@{E&8OYk_5(K$+LTZZ`vmY|P{3YS6q z+y2b-P?|uf_qOS9eNbZEA&89eVN#$I2!H={uoLgil?UdsF0x?Qjjw0lPT&gvVmC9V zD}`u^dU5!4+YI5Lt^0vNm&8$hN001clbV0FXd=P4b+VW~A&{$oTg@~6#8#35d@ z`$QoKeQ6k!iVJHfb1z1U7E+UHK!YAtGHp^_ROo&J?d@C7U?{g)KTm*P9gS&(757Pq z)0xxdGg{3s)3i%DWZTy-ycN@&*{VIRUYeUDmdQZGpwCGbv=8b)VLrVvB9mcADwn~a zfnydnyf;XpjFU5Uj>MQGC5?=97}L-+~t@SQGz6Nu4M z&q(?99Tk4RwxZuXB$+`fJZBfd(7mzxs~M4p!M%?qi6FuMi(B9Zp3Xz z3+M`}fSmqkfo#G!a+!#OjF#S$q5=fcR4xa!0Bbq8WOHJ9k|+e5Xxpu-+y~LiaJ*Jj zWUAj(-QC-tb)*63DgW7FEd?E)9#X@5Ni^#uP8#Jr;aX51YpMT$mQPcq2|71rAen4z zm?W2N8bF|TzYk^)PKdOJvs>sPI~XURwGl3cmoI+4T6c2~hlomn0HX&1&4(I(v+p;F zgSK(+BPbOo?z8kJbE-9-(rSYP&J>rc2 z?8|JZA`?o{E7wm>B(EeQmlwV-v_BjzD-nI-^#M%e#-&&=_Ly8<*M zE+&>`keaYS>E)I*jbV+!M;~=E<2H2|5A2%Uyb{hWjm_FoEA*1Li(@`+Epqg z2u3|aF5$|2C34j#7od!9q+tK+llr@-pst9WIiC@2zoA2@1W1eMU|ys*_Z>jQ0%tpE z#Z9CV$dm+3W2C7#Vtwsp!kWYL4C^Ns8pm|=tMso6A&#CiXb%uGf|!R9(!`6owlgaS zO384Q#+Nf)pWCPmF&|IR;h5qDL%1t9xxdr!We$8R?){C>_kfPO*Pxz}(0vTtMzh87 z7YDrmT#Ci{Qm0iEg)d>(luFG%TC}POjuLl8X3{^ZGQ>n;NB}e0lXvF9vO`10>03_* z`&8yK5CoxR(_SPN3-$Jh#sGo9)J<%(z0h5%zKe$a`sZJWMZ^gq0C#l#eewegnJ*a< z%%=M4`d+|#xd>DbdX?20qUfUG3EmmG48|mhON1jPix?5P?cXqtOCbkQ8}i7e*}C(a z2QgXkpb*aQ-!tmru|h07LvWg;Rhs3>Q}#rb26ll}_O^}0A2-7NH(-5)b=sLk$#?CQ zKSxsCKf-ooQV+|(n@Nd&RNM~|Eb9$Slu?n0C!wI7nU7SzNZ{Lg&XDnK#8#ogD28)V zkcgMK9^2xwn|Kf**$}t?2O6?6JpGja5G*bxhkSEl+MS+)10RJ^NYzew{4{Dzl#MTu zVEpx}oV)Uu%yo%*z)FgQVG?{KOgEVA+^R#{BPqUB5{G< zl5(EfIKyb?q(;apE;?tIdxK1n?_SylF+fteO~- z@^a6Vjx2G{F7eI*>f^|<7)4YLFU``Y-noLKdxiTFm!jSRrGEx?vr7+GcnuIaL}emT z_jb%EgN>lfajl#II0)E#`{Xgz;(+I9dQ^Z95t*}&9Hl%FHhTN(rIA2$3|d-B0&f0R z=S+H%|50cQ(uITOi_uyZU3CzvRLW#0@+)mFQ zyk`(ROC9YJ*&>S$Zypa14=XAvii#*_5OOL!RzJ0Az60&LY>bTZ6{tf{h;1z_pa%zG zoseQMI8KIATujUmCj@X1`>17)g3n&j)U-G>1P#X4C5e-O<4uy1lDfRQ!pFly1-vNw zEprVS{|wLW<%KV}g^Z4jMBYob{w4!F=D&VhQB^IvLj}@e1r+04u#%WclQjPFg9-ig z@&Cz5JShcDy7@_8J|uWezxLlhCOkZ=@|_6Spo^><`awiD*x1+{Nx;5Sx9ce}GsjFu*0+7JU|Esj$kRW}c4a0tYxxY_YRf_Q@C7 zN)(hS>o%8p|ENUR7|BCXLo%D>qV$})!9?*#JFIAo+1TLMYUBWhs1R6Dljy%xLBGmp zp*HHL42ZNt)wpVEBUoZzutTC{Yn}kDVk6{YD-A~npB83{OyiSGq|epnEaU2e@Rz6h zhpQKX;+5S?rfxq5ov}I0xRYe6%`Ge1oy3Ec30GD!ttH1iZB|!lMajZ9_fD;?OajvI zupFC|%#KcXjZK&|(X?=8R2t}xuE{+^`+=&Z4rCtzyo!EYTdF3PWTYI}hb5I5@gkDX zgZSx_`DNU!Zr9&Gdm8rQGY65S3e|(n7THxntJ8QE^ztZF=~}b1F6`s(CQV<#GGE4W zOpOghyKSY*>wwsd93d`kaeLj?&2)5gtZ}JCSqxGAmrEe;x*YVvG)v>YL(??EAhGJa zg%-~E!(lsGdn*ur&s>Q0MDfeZ;!&knkx5~4uD5C%LM6IOJO2yJ*6 zaRMolJod#O0*3{-gotnz$B!_*VO~>)D$i?jBPgXG^FIeRqNYjFs(@1;TF+4?c#|+b ziWwz&0foBTI%X? z(PNmAa~qVp2&|kvi# znnT|+AI%`z69G2WTi%HNogBJ%6LB_{R{9$FvX=h)YSy4#IK{*)5ZIz7lukdmBU+IC zjSMfHh9YD?l{Jex6Tdz*7BwN7A~-bcADjUH9x@r!ghg*L8)T~(}2x5{gw z9{})N){AarZVJOTOxw2A6GXCo7~smt?pEm&9p#Ln^iCME(`wp%8(+Tr({ug<-G<%* znJDPw4@IibbUEz^-K-~RDAuftwb?|MHQh*2NDEf4Ourtlj95jzrlb+dxoKR*A5}%g z`PZ%l)1VKFjVO4-bNGm`hG#~fOqr;ywZ9-bR+F+>l-XL%XvWu-hc*NSgC*6pbRuzW z!l8KRJw53r7E={}n;`y2;L7L^0A7PwcTSSU;FMgDsT2@cbw0?%F8iB^P?sVOLi(~W zv#qYL4i^dv%EB8bI48vjj3taBT- zJZpmqDk`fefm{frlnE6b+P7V)&_P<=eN+Y{lfCdh0p5?_MRe7xX%SN>VRC9VS=1jm zrd~UG)dI{bPp6LNyd;c=-di;^NW|yq6^Gg!etlZg&6eu zs@#W2OzPc)$F`~w>fOfQ{k-O!nMpAeeF!}-6K5F<+x5E4SBr(qFs&fO=tpxfKZK;UoBUyLfJ z(bc9?K*RWgvNBo@j=Q6(4l%&Bxa#=$__uH0N{9_=7EOLk8eyTK#l^=5{uf{dXk}%! zmAbLD6-dNEZKZoBSfzRzhQmBFH<#BDoK##)b*RV7%L|K45JuFXOB*>_*0txdj&5>t zauWVB8+!-j6ptl3iC)bz1saFf`oygJ9mkZyQTS91KCeV*!-O3B6Sdl{rSzd#|Sm6et4?d{dom%~YP zC4TQM>x;5*5VXbq<>iI=jNejU*LJN{^0<_Nnp*G$!FwM6AR7@jsIZWt;8r=NOCMDL z>nqHmo_;UVBUS#?!US^i$Jm@3u5ra0LLBf5Qz$CT;aL?{fIA2$NL~c9VIE}n&`rnoUs^!c zSP_{9NI!aGX|gapAyT=$YyDx1O^U+t%20Wyn7snsct}fL)&x(LYQhOZLcZK|N^LUi z1rcvnv>#)edPE9ck|&fP{uwuL^zWJ5gq+bA%E|aOhAuJ|p8dEvL`-gP%xi2tPVQIV zlPbltJ;Z@NmV;*@GKRIQ5Wdf9IAm0h#qaTAfY|R5TC9T)ioVNr ztHI+lmt5KlCgT-WE3iq~{AAY)aK{{$CRH@C_tw<36nf5U==ZF@Vf(7%VBNQ(0e(7< z!w6d3xvdNTqeesu61P*1%8(l^bEX!_Esy;hwyJRabZeCuW#VKu7O@)AQLle_K6j=~ zhC;y8a^?7iTPKb#Ec0e=#e{U2E+ObkGi=Ar*H!2Inmmr3Em!CH4Jc%>sXXjRF;MIK zm1(TA$i~p)2wDTBm$dcs2VA+kG|co?^6#qHN$z4(CnJ9^M~9ot-f7a5dF9(bXVufe zIN{LySRa$AJ?Qov{h}28k9KF-m~H2#_%H=-rTV{7bSB9WNt`heRWt{$wwTUsZHO@= zRYNl7#BVC0Uy+c);mmhok~1L z*aH@}gl_&A@>)WUb4JvO{-U!qm$&4_ zS(CvOD26 zS5+|~=hHtM;gDiRdBO&}8{LAq?4@rll+xjX>*q}3NhO6IN*TK>2f?WWnUJe1R`-3d z-Wi`#?^k>y%~`iv#w@oyR3&`gx&vWKMtSXrIeSRKm%b^8A346-96O$;X6Dwx?wP1e z7{=Q_*1n`WSHjjyO$w7iR6|FCsZe=c)^eXTQO2`sZ~q`{gdw|OHq6^WurOh1ukkP^ zkzGbUuho27)!mT#E8gs&-4{85A&qT8Rv|J)O>M|xfjR3+p&kuHu2*YMUG%urvtCN zHmi{(s<<`BlA0U8%GV~OEZwxD&^bG!vGnAWVM7$$!w|jY22)wzp22x9b;9|Lm;^Q3 zEOGIO6`NvPSB#a0>iUzbeV@ct z(S=;+T=n;>c!()ok`xTM;Zh0uW0BpD2;4grmp6*;jnqP!-53gQ+pOi!Q#M#?H4V&I zs18dxwACZ3E$Go~+_J1s-S?UVovfj6g6Q z$06R?%O77;|NNedWm`-}v{)&pGmpW-8$% z4XdSC?3tBO^%~avp0k~kP;^&~7-R|&Ld%Zlpw4UM>ycYI*%9>K9>p-9!B6r@lWjsx zD!8~fh5_07^qLeL_sjZfR~HM`fs|gy-IVxOSd&dx5~c;UzY`9?Fb+9=Kc#b zrB6khfi_}_cBOu_#NmJwkRR3Qq(}@{w(wzD z+0BuCd9=Ny@JWrz$u^jxi&(aF-dCV+G+{UbttK7vtbSLBJl|+n65NG?xP6E6ikMmi z`LaGWA$11z*bzo#d%*=1&-n!5Cljh;`sSqfnXxmRxNl@zpR7p=_*b{31F8odifc3$ zb~p|hrDJT#VP@?h#O)nsi9&8k0G=NbhGs15 z)T(sr>grCSudD;w<>%iU1$1=B%N@y?*iN@3|JR|_RX$c$RzAMAo2aiFP!XAUcP}q5 zclVrEm_Yn%Eif1y92^|`V%#MSqSt6~{o%PXT2j%(nj}LBF=w42*3fD9#=T+eg)8TH zE%~1afY)}0im$J4VPWBc151AOo(oFO+Hou4OD0dxUqskXhk9WxRsS@GiPF){AO}-BO+pD;rFC<(21jxk>ghw z^kn1qH2s4QqlS4bzv?a`1#j`x)+{(E&#SQV8ohRn7B^yO2K(<%v$>yR_i6P$|6&qn zrf{9ewh97iO+%N+BK;1I@&iWHg z&@s+5m@ic}F0d9wd@4G`)aGGAZ}jClkg@8iT6BIKTd`jT*G5NG($y?Jd`$TPp33CW zc7&+?X}H<>b!1$14AkGOm$0VeZ7GOiQkaAV%RMmL*Jnji(THo9X5(=^Ta|o zZuj!4IT?7Lnon?D_EjTXq}9hv^8D%SGnl&ZTI4Xq$rhnq{n68(PQ{Cd@oM>|JMUMG zz=j+STUc&~Rz}-X&B6>p;p-g)4yTo;>n zrv!0K3y-j0vAU*8Rj#_CeZRkfF9DBs?$nJYk684oj8InmnB;-#&NtwQ#f@+1Z4rxp3U|jcfSy zHQaotn*>Tac*UeI2PK_cw!Xx%$}iYx0JYq6hc{CVbWcBJ(tNdW2<{I#vB+;*mLTTr zT@}+%^*l0+T{U=_o9-;6GweqeJS>~8o<`u|$i%;13#_Laa>Ewutw_Nb1+&nScf8)8 z#4a2~QX;$J9PAoEfL^lK9@qPPx51E8W|W1#2wPnnXF|e*lRdsa8hW~#PEU7F*TJC& zhA7In_I+U`?v=4}x%Ebil6T|&Mxr2p7<@?5xaM|Qx^$D+J>xbi`GXxw+qfr?H z9o2bJS-qHF2I=EpbUUDmm1c+GpJO%)Xh)_9^OW9ukGmshB&qV@On%0f&B9PSwbVoDcqUB2Uy7!b3Nd^9M!4PU>Hek!^-G-+| zlen~ZI?S%q;C}M*r@L^|?y?F|>-;q`V)^3P{zl#QA$@$eVFT^&Zv945c9 zSSi$vT5V0zzdkei0p&Hpzpo&qzOEQk`#>u8m*Yz@e{zcl#iRXJ$%u^E)+DnX*+YRP z&$sHeLhPsn(^}pffyGhD6zL_rOh=^6FlV>*=E&DKM}enBwGNM%YoO;{js^1>)^c;5fA2ip6M!82|h;Td;ds;mQm!}WhQmvPHk@XTE^g_2% z+C!5(H=5FPSRk|Pw3zm_Div~aH|}Y%CO4cY3OQli;c9(hgnWAR+cnzyhCHMVN{KY^ z)2TnYno~LAG>F&XFj21N0+&-tc7!eF*3N7{PM^81X0o~*faO70O`gxMyT_tdXAr`@ zHkR(JX_0cin&Y4sSH^p;W~AG@h7sMmPUi{v7%kSd(&IZLe16@yBTmcT6ZRbOx_WwE z`w}ZNZrhOY#PwpvKlr>w9V_P~I@SVCT~xm`-gL;E40ddFFQA8n9+z29-9c{PP}*hZ z!aZU%GHE5%N-UjXdH0@%9c|ab`j$}t)HaKr`fHyj0e#K{oU*iN)Ccom8s;a2z6&4XKb-=}xw%ziR2C9Oh{x;S`4F(3b8B9#z z;f)mZOe+1mT!dad`SJ6KD%56J-|o5lm2dzEl$JXG64~#?vz&m(Q(Gr2OLIEjB~m`8 z^Ywlw{fvD8S^3$qdvA$c zM*aJFHidD_*OS#~7JZsKJZVu4g)p4*E;2QSRx@^NXxm}24%-(CS?GsewrjhtSC2Qi zd4n{$PHTSfaEv)I@{lz5So;XZwPBU&=6CH5yT61hv zk9~~dztf?JnHb+3h^a)SJY}2_$9bUyxKXYVYUD&Y1Sl~_ld{3Ii*8aGlB0_lhk<$H>4HXCT=f5smN+xYon2}i>m z0s!#e{^JX1J0W??VRBvFf0JxKPLTQzML;R?tvc3Lt=(=IKXLdPlg3kV3JMUDTrart zJu!K7GSWQ-ANTE9sDcU}>3HH})qnR<4LGrB%_gkjPfY7f-1k*mX`JRv*Qf{w)(Ys< zBI9)7qGMjH|NSt}@^j`6l!UC8aoy^+z1Og|tZ?H!P!03cP6u^nT!8%%o_6?mT!ZE4 zt<1DCipZKiQVw^5barhre(CJNO?C9fs`+tt(=Zyv?cW>D#QL2#jusXg27WHz4mual zpj;+h^JHmJ(o?yjG9g1|`7N=>>4MIqgn(W49|x=Yn09ya{n!S_(eEGfsd9pd#n1Sv z;L!DuuV)wHD+`lRjgBc_f|8K%n2%Ha$(|Yp`=ku_&z*zZ|v9-!(XA){|l{^PG4|YljXQX!+>6eR)a?f8bkqA3pTQ0C; z^lA@)ASdUyF-mAxO+G(SA;XZ2&X3f8jvB0{jpw5s>zBEzS-k3DsB2Bf_>UElp!|?* zF6o=seI|M)@~ysT+k6qTA2N0pG$^XK=MCaKb)X%7-`4`$VOSqVYje8DL0dAhwhcF* zo(PJLB$_XN=MO;cplD+Bym=#Rb)tID-Dulk(j&Afhd43`wfc@^cbk>r1LpdqnhvSR zy1C)=IVO^3^_6J_)tgrxuNdxl?MB-#s>Jx-A;Gyj{Tqb+PqhZ0yAe;Y{7qpl!9 z$wVi{PfSK_V|^(@ht6UtvE?a*AtWh9<5@^Uk|#3RA{&0bbR!}0`S+0O3Ud9TmyJW@ z;zWVJWkeGhC`=}!t03PVe8_0i>$Mx5)l?b`GcFL|c^i2MvOT#s-_13QZU?s$i5p+? znfNs-tTpjj&Uf*X!6y1#b%k1RFjePrA07A%leX%vmRMO-7AciY<~}~3NbirQjcB=? zds-A%*Uiy4Y<^!`e2ab%(hf?)uY5~OZn%RS6h7HHQ(2}N0{3y zlaO`sSj3+2eR8-SCc^?5qn9p%ur4=?Uz9<`;k_x4;&(II%OHjW)}>m&>tDa)WeQF48iQ zhVJ^nYo{@lzKj!y;7ZjJ#h#OVI*%IDF`ee4hP-i;X!`p7L6TY)SLnC!qNdVAwW-CG zd@E2Tw^G2=Nd;T<@fX^3-`v`g?W_9Qx%TC1Nr8D*4GkrUvC&++3nMXVQ98BE8fO#S z#NEQLvM!nJU~q){8v82Wl+9wlW~{}wHYV;f48Ef!ep-|!%$&1_&UMAZk?+7v!_gw+ zmzkD4zuvX9ftd%P0B8Z-DIWs6DJEEde%~Cz*p-VDXxx0>+znwdp-FrYlI6?Y!GWnm12SPp{GTo(`npa z^ks4yG_x$?pM!&=bJp7ATBY5H4o&_lXfkQA&-HVs%D8&G_kYF%W@fL8Lx zQZ|;=wRL@rK5T4`+0qRr(zA1?pHh+PJk9FKm=Tm+_CYewvfkZs0(TkC^eq?98!D;z zWEpAyOtrLxF9K4ytZLshXKbui--=;KIN_i?%Ryl3hOMsBGY@Mxs`Wj96 ztvy^PYWvBL1@e`CgdY42ZO5~z>ic0`x>Vl%u#zcb>ny#PW@rKN_v3#%#6gZWW zb=7B0#5OoK3*t>Tq4?@ERy8ydKf$ZNn5tLatw}r?QkExmxv>G>&T@fBRec+B0fyN4 zSfuW5n0?Z&E2OA{eSm+Rj`lnLMT+5tmcRTqiqz3uxzu(`K^4>`SVN&kq|ND(di-!Y z!j3Z&EX4nId8LKY+qgxfs{MnB!JUZ<5|$Fos@qKD_D6yvJ6$>;D>ENgjF<;o|K&fGB#_m4I-g4@ zi-v3hzx!$?^uRcp{%_id>p*WrX#11u5#O7z=ORAM(HfEUqC!=xj${78^qEUfaTM{f z^#r-qZhV3j_K!0#Be0|8E}&W6;%|V6&<$;Lo86>>qX}4h`TPk)^#8K!mJ5l(<-}k` z1G%v7&5h8OW8zaB!d}1>Gb_VGH0f*gCm*X`q;-{dZ=We_%=Z6CV^I|R4jp>YTeH16KGTY%s+*0^Q( zAMULCFmq?_%YCU;>#W+Vc2%7^UwylFl)9=s4kkG!006*I_$;Fd03hwZ?8l%Zzib&8 zawz}+e1L+?NA0gU$7?u7T364)XIwonGw#3&>dN;y%&|g&qZ%UuQ1Lw zV=#%*Ad5x7NNhjlI#xVF9QM5|ZJz*O8Hs{y_T4O!Ls@~qt-SA)q`g#5r&QfZsdC;1 z{u#$yLYX$Z}mwX1)WMECYG z)H@W0SWKnuDD-dALVBXPjdBt-w4Dz-Hi9)VrZ^2*4_!##6Zc!E*`53_Ri3-xS16wJ z(kiCcv8fo-o6RgN6Jo{=zqqu`Z*KkL&h|A=obMz3?|x!J?;jN^-ZdTNPLno@Cp1CGOQMtW!GuF9eJa=mkVkJccW0DN@DPHG9M|2brM@{ko{f zvmj7-%VKT>)@@=$J21S{I~XBJ8hwfy{d%ZDBaGOG$;}Y^@Pa&tiuUhKN4vt##VaQx6BElw zX@^u?H`%uJU5^gosxscdjjUG#n;=&y%-r5mI-T|bvxDsBq<-z9p*rOozRPwnsyU~!V8rO5)Mfwv*!nBs^$?=C zeeY??Hz2p}M3Sb|)5I6YSP%_&4nCXMg{beHGe0fNTv6C4@s2r4> zg1`y6{Xu1pOdS#bTXuMhBV3Y$yU+x=%N2=Gi0orP4QmS?HeEgcy2bnYovJ>^ZbPS* zHd8ry&0)i8>#lkA`6eU3=kWQ!K!-OflR zPJ#)e1)7;g)Io=?lMg}%)KNDbvHNqf z(d4LIzg`~R02wT3hIA92QQ`|{k_8K)JN>lLlHs%i~$K6tM@#?q{YM1L^bwvdh5;sI2 zjF_(+wk#cz+afxW=suWkt9<<^%mgTUrO04bIpe53Vo`!t#+&(N4hKe8M%`};Y}6vq{5J=BP9ba`qH z?*D(}_+O#Mh7u-nu(|n7t_wX(w%EYj-PsU5<_|a7=1`IK%ZV|F7>}14%IfN-tauAd zb$oqA$=}iu`_T8qKk0aW`I5nFJ<=0~6-9>>2S8V`#%p#rk$#fIg$aQR`7_-^mI~Wvqy5*s1=7sLaB0XR%AS$LUp+Ub$q}!u@Nr% z3q1L7YglOsKx=tbnI$%8F>*Pq>SXINz-Usx88mx4@w|MN3JdwlEYJH^$5A36?lL;y zEHSuGVuU#_hKLC0I~_@1z1R`(P)2+JRln{^@o(r*9Yi;5(%n}efPDl6N36CJH9=&c zHcBN}5ekhN%G!CKv)*IaC6&2MDM~8;nVCZ2O|_;cMF`o*xZ^itjf=6{$m;A8G)hK} z+cBrYMW)Rlnu{O%-sQMkO(cOuf8?J&vIAvfn-^Z`1Z0`Y7iC`Q_L&j&UcQ4gZVu&1 zlz7Uqh4q_qnh*>fjz0~s_U8r2Q(Vfi#dW&p3MUpwLFFN8&c(IjpMa61epv}8!y9Fg zR~IInBoXz87koG5Z~2QU8G z+B*nl-SI>nE&9r)9e+lV(r!9sb`JAM5gPycI0N^K_p8P_>n9WazXl5Qbo!ZiSm|wM12ZC>6e{*CNa+Hg(V#(Rwh4(WO(47~~^1n)ra>S9D zsr_0WS+1zW*_Am22_|A!NIr9b%C9P1<~)zS@_4Un5RYl=zU1*K#>_IU?}oOW^}9tY z$yRtZxEf4*)UJtHpLHddmcMi;QA-=we`7O)A0}5so4fR@23(;P1l3WAZK#ry2s8hU z=9$nE1@(D%G_QQ4LbpFY>@GLHk(&lG4bix6prmDjDx2#TdTFq+2tNj`Z@r zLKn(t##nlbR9bkc-6G1KruTD@UhLxg=S;}QYD}dAj%sYZ6WR1(oTMewsKutQuj>xfv!L=DOKK0UG24#NuLRa>o78$> zHID3!E!Ejka4HfY7V=<>Yd6IzDE{iOaY(vs@FEgPLcev-LI`&>I8q-w3n4;c#5+5xs5?n z17%WsKwQL>4$_v@|=N3n50sDsSop zDq7a*VRzQ1I+0lV=&j{FRy|zG8T|aZrYv>3b5;L1rpXqz+wzq`!?awwFFQ|Ois8M! zec-62_*?etuK(_Jy{WH=S&VK>2C^X4fsSG-ZbI!(Q*6*CHwSCnaL?fHL&YivG6{aW zbvB_V&mFT-(wbDxlZGz89kHmjPIguQvIp1l-+O4f`%rJ_C{13$R^Mdzdye$L=C)Hp zuS8*_WOq&>4)#g8B^l_^OsMpH<8&yd9+xkoslDNtWWlzIcUY`H|M337O(l- zO(sm)%@1)4;OW2HPJ-}r^K0p5u1BjzkzR8O>CA+k>$CW$m9x_s51UIO# z0L+vrDDrdq8ZTx!mOMBkC@86D9`pTUASo$C=LlfFG*aT|c(zcLZbfb`6|$K)IZ;$L zjMSDiYO1Ed_Tu~fy|28yysfP*Dz)SbY~teLUZ~>O762TkOAwciZ7?t}&}Mz}LJ90% zv-hvKP2zgFGV7a~f)2~eva+&VR-3;CO5ot&t+VJ=$~$NJw9^RE4T@zu`-0p}xnEME2(Ifc<{T0kik(p1o=K85Om1PQ z$?;yW=HYf@t9`M}F0yYc9hBpOp2SodBAew)n|)+PQD5T3jgyN6-c^6jnig|&6o+uM zO!ml$#?AK-l(_sr_wCFYFCI}Inx8C>q(~u*8|6cccnS|-8MSSGY@ z<~E`yi9si{hiHl|e#a<1Z2OL?-$Cz0bY4=Ve3ckY>o5!xFBm~daKVgS#B}<_6<0()G(^K5C$-(4A(QvZaLEwV|M?K zT0r!=;Qht7Q4V2a=C$)wqqH|+q{BMC?ckqeOa?>NEi7sleWOv}cWQ{ga$D3b3gXtP zdE_1bpxydV5+jYGjO;DykgSZRCQNs8zS>h*z3^Oi4ZdmV!1>t~V@NneLN2_sPGV z7^FBp^$D=dB*#F-TKNrsvS&A1QEA0>Vp;r|1nvt zGiRoTCiR=I4JDYJT-MhD+*bC}eEQeOZ?XsKl#lw@UTxiQuAb7(7VjMluF(|x$K(T7t;pBM=8WB45m;o-vP zu$0sT0y1m7%U$}^Xmh=XtL0W$_I)8D%;c`$AvCdu({VFuY2bY$v`w@+XF0$^&YJv- zq}(2+ldVrA4Qw>M+(SA~F%E<1ooi?WSt>;mq2tJ~st!5-;fSxp7k@eajTTKwZIGx< zV#$DYHoLNUPfF+&mF|~HncU1wW}$roAiGKd-PO<0OebGdS0$Sqvbs>&q}8^NwxG`8 znlU4-#NJ(Q5hRT|B&TX%$bFG>6k#Z}t^7b)SC`+c#OEyt8Q3$jy=!iB?|Dz9FFPe5 zn;Yn@+IS-p0 zkQKr|gmmfg9BX2@kuyw)d?tG{EaGjCSR=qJ(fA~slKdRk$qtj<;tj1 z(Fu$6@z{!0C1V2*FX5-#PHUmiD@cn@U)d|}V1^uAj4-{T99jWjld_3#!^qx>`=8`C zi)>~xgi=yhBJHWLD|kWR8!PE3_0pOT#$QjzGKk{33dE2ak6MJO6L4 zuTi(>C#3$x0zT~DUmd-SyvR34nDmQ%!E(i>(BEn3xjTPzvwsn<(o)9%$@t>c7xM$} zG2#G(VGIi-ALy2RaXu#`F7Cgsn;~tH^dU&vKDFg zta0ubvQ{VN<`t;#aUxoHC*E#zrFjF*&3?X^KwGVDh`Epax;+pXRTh2WMKis%NWZaE zJznO>Wzylkme-$mc(MuSJKy5bp%|P|UGWF%%`OK8Kyf?&l}*HF!xY6`#V=`Rr@JwAn$?Qhf;0ggU*q)s;NOL4;yqqQRuNK6U_9+m+2a(8k_M?D|*SkEoRPQlIgl=bK|K)1ZK?#UD8g z6{csdoR6Iocsg&tFbM{A$M6v3;XGJ{?UYfd5Rp+Qw4d!}CpF}}j=Jl~`Xyo<@%-qr zKAd)4?G-VsG+$O_z5pMA;~q&q5L9j!?^+<<@WsJ5C8JJkZ0+H^rr`E37-eeN#{>H0 z4+FKm13naf-oF+oT^*|oKzGrbrF?!+v9&Ol4VUgX(usW66AKkKDO zCg$y~#{pbV6@k2j8bEs>5T+T;HPe5@!1+_?vg9x%y%W#?r79i53$i0*wYw*>=Nc zk$i+{0O!A!^YAr#nvaWE6O(xU(3&ZK9lxbm#=G$LBtkJO(~PPOi80RIoztUrk1f3- zRqs1S=R>RT2Z@KCv(`nFFzZ>;9g+ntGUAH$<2Ni(m);Z}q;0~6zzi)TTL}E(Xne6} zHm;(XjGX9rW_o&3Zwf47Y%L{aaIqSqVB2}u0SX@ss|orrQKM$?Mq2FrN-c74PBUQm zs3k*338hjh&{$+gBb}%`<7uJ1{9a@t!h z$4*^nTk=zPHkJ!Xkk1gyq`aXK&t0nbb8XM|qpg_gSgImvv#5%b_n#WyAkW&7tjb>bu>_D8g6R(W-UWxMh{HRe++`X#-!L|FU}G75a74g z>KT!J#`cp3iVA*Rd>cP_otKmOc>b?4@NuNcG$-fpl767WS)=Sfb_c_}GxjSZ2~~t% zQqCoDtD4@H-c!NPJ$p0{=6~ngI)e&}#kIvv$Xt2Q#rfIFsa2!1fqP*7mND1e;m`s3 zQS6_+=cDnB*4bR=S)gRiY$8hT)jqRRUcn~4T z;d+QdLZUHZLaHMkT}-DD&S$LW@VLzxPrS+_Y;*2uo%*lh9N{v*PhbgiWT~03G>fn9 z#eVpVzcbmiCg!pE{fXw(K4@nR=+8ZfkvmqKzGrm1sX0Wm3nI0)~1?(T)TvOZ%p{rbBx_xqtL zAgF@Auh(b4_V^(Enq`c@u;KYOHsyk*|F#HZcF3#@_giW|D^|4+=XdV z9v7FyYt9nbIl}1{6wrHGrjY{|6)()QrM}-QVPH9LQ(Cw^noic;s1Wl9b%!h&Qhg%Q zOwUSKFzy7;Gc>)V~%RCHN7;jW)SmMBe(QCE9=joeBGYpO7aRF-o~bbEX+{@`sxJM;LJZkp7~ zheM0c-DK=|RjkN_INu-+-Nl3bUy+EJ5?Ah`c`!}qtv^s!B7W^H*8Wi(b`b9Q`$O@$ z2O_+{Ei5R=I7xC+8l+f1wJ8Q&Z>7f?W z`P&#phooBYR?C<8GfwYq0DLIhJ)q zMNM;k&0}-xU!#g%xI}o9z3YE#@zOk6k-WziX6xy5oBfPwhbyT#g_)GqA`y^DldZyz zQgF0fwtWwgdxKq(PX;-;i;9q1s`oiMaa=7URXJEIs7lNB5XBMk#bY}*9;^!3|6@)d z*9iJ4GPSlR6Pf2btKq%-H&Za8`mn|wOD9!6#yiMs;$+gE=IkLo5AU7oA%yCs8a}qu zsO8)A$bZxi(Z@24&EU%%cWX6S5M63m`?{HN|HH!1KympWRU6Q>c^B&R)%dut6ZQw& zd*-|lrL00t_xRtIWPo|I@i9^_#C?~`T*v>S+w@szkK1ziQH&`N#rs=Fqn|xIfni}! z{#s;>EWq+4C8a70MWlt*YxXEccz-+&WJ&_9 zytvm7{1DM5O(J&P9@E%aW@pUfVQyHVJn8u z4egEBeE({LL+x)&MZ6ygPnWJvo2g-I`sX8>+fA~AW3fy<$oKs+LabOf+0@xbUb~mu zF>isYb7F!zx{uZsBSD+~j;>;e5>Of5oOsIPplpKh0&F{fUIRxrpY(BptUz2RZ*;svA`yQG@tkRsP9#ToX*ngY&K+4sb#6-RBJWA&6H2but#|D=NSc3nLJj)pKqv4dOW-t=J_(HTJbkvilKSSV{O)y10aC`?&pg zvW--HCdxr^70b^z+s%XBmE&R@oJI?Ir82-Ul*TBshP2vORwnwK#+UBNvv=n+8auQ0m09HI~FX~yF(&HU)ShbCD#}k%0ov&*K0MLT| z>kDXW2~2Y)``+rOafxH#k9#id2OA^gRtMd|a`zq=+Nf6f$^~NJij)z;?jUO(<|FQ5rNE}=@%AcdzEDkZ^6y~K&7#2a;bIB9v*fzD zy=#+$qWiU=Z(HKMC;{2Rj4`EWXjp%v&B(WoBhdD3%YAl2=L3v)pk?BSv-LdaCc}QH z_Sc--`?wIpsJ_3)Fxo)Sg%NqDxxM!yihRN)PRxQywW|kd#}&jB0qfLJw;j9jyVPCm zc{aDDP;$px42yVeocFPnjh#o;?gJQ2LNdnM>DSRuRo1Fzn9s??c?_ee*v^L%sFw%E zybHRGUB^RlR}lDWOwF`Bi*grZSNS4)(;r@0Kfm9nrgt+&_v`vM-z$~N7=K4EEAO$w z>E!i{$TzAyG#$Pj2XaQ5gz~xRTBnCk8LlxCSlvVkuEJMT~jJuVlL9Him}h&b8f)USGp-+wRm) z(#woV89E*#?Ap^^}Xr;v|5s_hp6b@L3zYSXsgm#tq@7PPEqTJ0S!DyG0(~dx8aP09a?Xw0RzN?tux|5~dGaW&Uj_F)l=6>%&Y+7G zCK2vB#<-N%edLs$@0rrzKRr#)4)6PW_boo%gnjJAUF(N>M0Q&c4AYb?P9xM?y9Vcr z?^f*_fWns8aS-Q$Y5Dc2@rUkR<8gj(!-JV`RMezwb`otBdL?{x;Wx>oMURbQGm;v# z-oTY{>}T)-P-Tv0(b%Y9PO!;Oww<6g67(=m=X_Uf91$grISzV`(Lfk>`XHS3iTa}~ z?2oKCjBcK3_6|E&j6IB8OPa^dvc5Ln_a)^|H1Y&IF8*-LiqW;rYV7xKC>os$xcDKj zdyS(+pMl~%&lKYMcg@?KORxL~3?j(>r}3r$AW zkxupL8Lt>Gg?Ksbo(h%Jv?F%Mb2A!xO`|WxGt+LT+#2W_i^jM9QaqiscJiHW%u&rd z4|q5{+3SQUhB7|*f+$y1NV1qB+|S1{m59W}*Nz!6O`dwen=gvwE)n1up?Y;$E0`-9 zDC0?hxIoxg2pNh+{thwKULfDko5^8PHolNM=38AqC*$#DU!8m42fjXRScg?M+eFYh z8Zv?O73U2SXnRCefBMMxbsT!{emdCj)GAfAvt6S*mfk}tciqWx^sYa(JNlA`Sbj~B zeo5W*JF5EH87I}c7i;BTbKIE-#3!;A8 literal 0 HcmV?d00001 diff --git a/webview-ui/src/components/common/__tests__/mermaidTheme.spec.ts b/webview-ui/src/components/common/__tests__/mermaidTheme.spec.ts new file mode 100644 index 0000000000..654efc9deb --- /dev/null +++ b/webview-ui/src/components/common/__tests__/mermaidTheme.spec.ts @@ -0,0 +1,89 @@ +import { act, renderHook, waitFor } from "@testing-library/react" +import { afterEach, beforeEach, describe, expect, it } from "vitest" + +import { getMermaidBackgroundColor, getMermaidConfig, useMermaidTheme } from "../mermaidTheme" + +function applyTheme( + className: string, + colors: { background: string; foreground: string; surface: string; border: string; link: string }, +) { + document.body.className = className + document.body.style.setProperty("--vscode-editor-background", colors.background) + document.body.style.setProperty("--vscode-editor-foreground", colors.foreground) + document.body.style.setProperty("--vscode-input-background", colors.surface) + document.body.style.setProperty("--vscode-input-border", colors.border) + document.body.style.setProperty("--vscode-textLink-foreground", colors.link) +} + +describe("Mermaid theme", () => { + beforeEach(() => { + document.body.dataset.vscodeThemeId = "Default Light Modern" + applyTheme("vscode-light", { + background: "#ffffff", + foreground: "#333333", + surface: "#f3f3f3", + border: "#717171", + link: "#006ab1", + }) + }) + + afterEach(() => { + document.body.className = "" + document.body.removeAttribute("style") + delete document.body.dataset.vscodeThemeId + delete document.body.dataset.vscodeThemeKind + }) + + it("builds a light base theme from VS Code colors", () => { + const config = getMermaidConfig("light") + + expect(config).toMatchObject({ + securityLevel: "strict", + theme: "base", + themeVariables: { + darkMode: false, + background: "#ffffff", + primaryColor: "#f3f3f3", + primaryTextColor: "#333333", + primaryBorderColor: "#717171", + linkColor: "#006ab1", + }, + }) + expect(getMermaidBackgroundColor()).toBe("#ffffff") + }) + + it("builds a dark theme and normalizes translucent colors", () => { + applyTheme("vscode-dark", { + background: "rgb(30, 30, 30)", + foreground: "rgb(212, 212, 212)", + surface: "rgba(60, 60, 60, 0.5)", + border: "#8888", + link: "#3794ff", + }) + + const config = getMermaidConfig("dark") + + expect(config.themeVariables).toMatchObject({ + darkMode: true, + background: "#1e1e1e", + primaryColor: "#2d2d2d", + primaryTextColor: "#d4d4d4", + primaryBorderColor: "#575757", + }) + }) + + it("updates when the host switches themes", async () => { + const { result } = renderHook(() => useMermaidTheme()) + expect(result.current.kind).toBe("light") + + act(() => { + document.body.className = "vscode-high-contrast" + document.body.dataset.vscodeThemeId = "Default High Contrast" + document.body.style.setProperty("--vscode-editor-background", "#000000") + document.body.style.setProperty("--vscode-editor-foreground", "#ffffff") + }) + + await waitFor(() => expect(result.current.kind).toBe("high-contrast")) + expect(result.current.signature).toContain("Default High Contrast") + }) +}) diff --git a/webview-ui/src/components/common/mermaidTheme.ts b/webview-ui/src/components/common/mermaidTheme.ts new file mode 100644 index 0000000000..8f06500e73 --- /dev/null +++ b/webview-ui/src/components/common/mermaidTheme.ts @@ -0,0 +1,153 @@ +import { useEffect, useState } from "react" + +export type MermaidThemeKind = "dark" | "light" | "high-contrast" | "high-contrast-light" + +interface MermaidThemeState { + kind: MermaidThemeKind + signature: string +} + +const DARK_FALLBACK = { + background: "#1e1e1e", + foreground: "#d4d4d4", + surface: "#3c3c3c", + border: "#888888", + link: "#3794ff", +} + +const LIGHT_FALLBACK = { + background: "#ffffff", + foreground: "#333333", + surface: "#ffffff", + border: "#717171", + link: "#006ab1", +} + +function parseColor(value: string): [number, number, number, number] | undefined { + const color = value.trim() + const hex = color.match(/^#([\da-f]{3,8})$/i)?.[1] + + if (hex) { + const expanded = hex.length === 3 || hex.length === 4 ? [...hex].map((digit) => digit + digit).join("") : hex + if (expanded.length === 6 || expanded.length === 8) { + return [ + parseInt(expanded.slice(0, 2), 16), + parseInt(expanded.slice(2, 4), 16), + parseInt(expanded.slice(4, 6), 16), + expanded.length === 8 ? parseInt(expanded.slice(6, 8), 16) / 255 : 1, + ] + } + } + + if (/^rgba?\(/i.test(color)) { + const channels = color.match(/[\d.]+/g)?.map(Number) + if (channels && channels.length >= 3) { + return [channels[0], channels[1], channels[2], channels[3] ?? 1] + } + } + + return undefined +} + +function toHex(value: string, fallback: string, background = fallback): string { + const fallbackColor = parseColor(fallback) ?? [0, 0, 0, 1] + const backgroundColor = parseColor(background) ?? fallbackColor + const [red, green, blue, alpha] = parseColor(value) ?? fallbackColor + const channels = [red, green, blue].map((channel, index) => + Math.round(channel * alpha + backgroundColor[index] * (1 - alpha)), + ) + + return `#${channels.map((channel) => Math.max(0, Math.min(255, channel)).toString(16).padStart(2, "0")).join("")}` +} + +function getThemeKind(): MermaidThemeKind { + const body = document.body + const className = body.className + const themeKind = body.dataset.vscodeThemeKind ?? "" + + if (/vscode-high-contrast-light/i.test(`${className} ${themeKind}`)) return "high-contrast-light" + if (/vscode-high-contrast/i.test(`${className} ${themeKind}`)) return "high-contrast" + if (/vscode-light/i.test(className)) return "light" + return "dark" +} + +function getThemeState(): MermaidThemeState { + const styles = getComputedStyle(document.body) + const signature = [ + document.body.dataset.vscodeThemeId, + document.body.dataset.vscodeThemeKind, + document.body.className, + styles.getPropertyValue("--vscode-editor-background"), + styles.getPropertyValue("--vscode-editor-foreground"), + styles.getPropertyValue("--vscode-input-background"), + styles.getPropertyValue("--vscode-input-border"), + styles.getPropertyValue("--vscode-textLink-foreground"), + ].join("|") + + return { kind: getThemeKind(), signature } +} + +export function useMermaidTheme(): MermaidThemeState { + const [theme, setTheme] = useState(getThemeState) + + useEffect(() => { + const updateTheme = () => { + const nextTheme = getThemeState() + setTheme((currentTheme) => (currentTheme.signature === nextTheme.signature ? currentTheme : nextTheme)) + } + const observer = new MutationObserver(updateTheme) + const options: MutationObserverInit = { + attributes: true, + attributeFilter: ["class", "style", "data-vscode-theme-id", "data-vscode-theme-kind"], + } + + observer.observe(document.documentElement, options) + observer.observe(document.body, options) + return () => observer.disconnect() + }, []) + + return theme +} + +export function getMermaidConfig(kind: MermaidThemeKind) { + const isDark = kind === "dark" || kind === "high-contrast" + const fallback = isDark ? DARK_FALLBACK : LIGHT_FALLBACK + const styles = getComputedStyle(document.body) + const background = toHex(styles.getPropertyValue("--vscode-editor-background"), fallback.background) + const foreground = toHex(styles.getPropertyValue("--vscode-editor-foreground"), fallback.foreground, background) + const surface = toHex(styles.getPropertyValue("--vscode-input-background"), fallback.surface, background) + const border = toHex(styles.getPropertyValue("--vscode-input-border"), fallback.border, background) + const link = toHex(styles.getPropertyValue("--vscode-textLink-foreground"), fallback.link, background) + + return { + startOnLoad: false, + securityLevel: "strict" as const, + theme: "base" as const, + suppressErrorRendering: true, + themeVariables: { + darkMode: isDark, + background, + primaryColor: surface, + primaryTextColor: foreground, + primaryBorderColor: border, + secondaryColor: background, + secondaryTextColor: foreground, + secondaryBorderColor: border, + tertiaryColor: surface, + tertiaryTextColor: foreground, + tertiaryBorderColor: border, + lineColor: foreground, + textColor: foreground, + noteBkgColor: surface, + noteTextColor: foreground, + noteBorderColor: border, + linkColor: link, + fontSize: "16px", + fontFamily: "var(--vscode-font-family, 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif)", + }, + } +} + +export function getMermaidBackgroundColor(): string { + return getMermaidConfig(getThemeKind()).themeVariables.background +} From b7f78f8ef34248c84cc916780a6ade132ee1ebf4 Mon Sep 17 00:00:00 2001 From: Alexei Gubin <36731953+WebMad@users.noreply.github.com> Date: Thu, 20 Aug 2026 01:43:07 +0000 Subject: [PATCH 33/66] refactor(providers): canonicalize model-router calls (#1165) Use the shared providerIdentifiers registry throughout model-router integrations while preserving existing serialized and wire values. Centralize missing API-key placeholders and extend provider regression coverage. --- .../providers/__tests__/openrouter.spec.ts | 26 +- src/api/providers/__tests__/poe.spec.ts | 161 +++++++--- src/api/providers/anthropic-vertex.ts | 3 +- src/api/providers/constants.ts | 2 + src/api/providers/deepseek.ts | 3 +- .../fetchers/__tests__/lmstudio.test.ts | 37 ++- .../__tests__/modelEndpointCache.spec.ts | 15 +- src/api/providers/fetchers/lmstudio.ts | 4 +- .../providers/fetchers/modelEndpointCache.ts | 6 +- src/api/providers/gemini.ts | 7 +- src/api/providers/kenari.ts | 3 +- src/api/providers/kimi-code.ts | 14 +- src/api/providers/lite-llm.ts | 4 +- src/api/providers/lm-studio.ts | 9 +- src/api/providers/mimo.ts | 3 +- src/api/providers/moonshot.ts | 3 +- src/api/providers/openai-native.ts | 5 +- src/api/providers/openai.ts | 4 +- src/api/providers/opencode-go.ts | 3 +- src/api/providers/openrouter.ts | 33 +- src/api/providers/poe.ts | 18 +- src/api/providers/requesty.ts | 14 +- src/api/providers/router-provider.ts | 4 +- src/api/providers/unbound.ts | 17 +- src/api/providers/vercel-ai-gateway.ts | 3 +- src/api/providers/xai.ts | 4 +- src/api/providers/zai.ts | 3 +- src/api/providers/zoo-gateway.ts | 6 +- ...webviewMessageHandler.routerModels.spec.ts | 302 +++++++++++++----- src/core/webview/webviewMessageHandler.ts | 118 ++++--- 30 files changed, 600 insertions(+), 234 deletions(-) diff --git a/src/api/providers/__tests__/openrouter.spec.ts b/src/api/providers/__tests__/openrouter.spec.ts index f0000918d8..1e422e4ba8 100644 --- a/src/api/providers/__tests__/openrouter.spec.ts +++ b/src/api/providers/__tests__/openrouter.spec.ts @@ -17,6 +17,8 @@ const MOCK_TIMEOUT_MS = 300_000 import { Anthropic } from "@anthropic-ai/sdk" import OpenAI from "openai" +import { providerIdentifiers } from "@roo-code/types" + import { OpenRouterHandler } from "../openrouter" import { Package } from "../../../shared/package" import { makeApiHandlerOptions } from "../../../test-utils/api" @@ -349,7 +351,7 @@ describe("OpenRouterHandler", () => { expect(mockCaptureException).toHaveBeenCalledWith( expect.objectContaining({ message: "API Error", - provider: "OpenRouter", + provider: providerIdentifiers.openrouter, modelId: mockOptions.openRouterModelId, operation: "createMessage", errorCode: 500, @@ -371,7 +373,7 @@ describe("OpenRouterHandler", () => { expect(mockCaptureException).toHaveBeenCalledWith( expect.objectContaining({ message: "Connection failed", - provider: "OpenRouter", + provider: providerIdentifiers.openrouter, modelId: mockOptions.openRouterModelId, operation: "createMessage", }), @@ -394,7 +396,7 @@ describe("OpenRouterHandler", () => { expect(mockCaptureException).toHaveBeenCalledWith( expect.objectContaining({ message: "Rate limit exceeded: free-models-per-day", - provider: "OpenRouter", + provider: providerIdentifiers.openrouter, modelId: mockOptions.openRouterModelId, operation: "createMessage", }), @@ -415,7 +417,7 @@ describe("OpenRouterHandler", () => { expect(mockCaptureException).toHaveBeenCalledWith( expect.objectContaining({ message: "429 Rate limit exceeded: free-models-per-day", - provider: "OpenRouter", + provider: providerIdentifiers.openrouter, modelId: mockOptions.openRouterModelId, operation: "createMessage", }), @@ -436,7 +438,7 @@ describe("OpenRouterHandler", () => { expect(mockCaptureException).toHaveBeenCalledWith( expect.objectContaining({ message: "Request failed due to rate limit", - provider: "OpenRouter", + provider: providerIdentifiers.openrouter, modelId: mockOptions.openRouterModelId, operation: "createMessage", }), @@ -458,7 +460,7 @@ describe("OpenRouterHandler", () => { expect(mockCaptureException).toHaveBeenCalledWith( expect.objectContaining({ message: "Rate limit exceeded", - provider: "OpenRouter", + provider: providerIdentifiers.openrouter, modelId: mockOptions.openRouterModelId, operation: "createMessage", errorCode: 429, @@ -585,7 +587,7 @@ describe("OpenRouterHandler", () => { expect(mockCaptureException).toHaveBeenCalledWith( expect.objectContaining({ message: "API Error", - provider: "OpenRouter", + provider: providerIdentifiers.openrouter, modelId: mockOptions.openRouterModelId, operation: "completePrompt", errorCode: 500, @@ -608,7 +610,7 @@ describe("OpenRouterHandler", () => { expect(mockCaptureException).toHaveBeenCalledWith( expect.objectContaining({ message: "Unexpected error", - provider: "OpenRouter", + provider: providerIdentifiers.openrouter, modelId: mockOptions.openRouterModelId, operation: "completePrompt", }), @@ -630,7 +632,7 @@ describe("OpenRouterHandler", () => { expect(mockCaptureException).toHaveBeenCalledWith( expect.objectContaining({ message: "Rate limit exceeded: free-models-per-day", - provider: "OpenRouter", + provider: providerIdentifiers.openrouter, modelId: mockOptions.openRouterModelId, operation: "completePrompt", }), @@ -651,7 +653,7 @@ describe("OpenRouterHandler", () => { expect(mockCaptureException).toHaveBeenCalledWith( expect.objectContaining({ message: "429 Rate limit exceeded: free-models-per-day", - provider: "OpenRouter", + provider: providerIdentifiers.openrouter, modelId: mockOptions.openRouterModelId, operation: "completePrompt", }), @@ -672,7 +674,7 @@ describe("OpenRouterHandler", () => { expect(mockCaptureException).toHaveBeenCalledWith( expect.objectContaining({ message: "Request failed due to rate limit", - provider: "OpenRouter", + provider: providerIdentifiers.openrouter, modelId: mockOptions.openRouterModelId, operation: "completePrompt", }), @@ -701,7 +703,7 @@ describe("OpenRouterHandler", () => { expect(mockCaptureException).toHaveBeenCalledWith( expect.objectContaining({ message: "Rate limit exceeded", - provider: "OpenRouter", + provider: providerIdentifiers.openrouter, modelId: mockOptions.openRouterModelId, operation: "completePrompt", errorCode: 429, diff --git a/src/api/providers/__tests__/poe.spec.ts b/src/api/providers/__tests__/poe.spec.ts index 627d203994..00712924f5 100644 --- a/src/api/providers/__tests__/poe.spec.ts +++ b/src/api/providers/__tests__/poe.spec.ts @@ -1,6 +1,55 @@ -const mockStreamText = vitest.fn() -const mockGenerateText = vitest.fn() -const mockCreatePoe = vitest.fn() +import { poeDefaultModelId, providerIdentifiers } from "@roo-code/types" + +import { PoeHandler } from "../poe" +import { getModelsFromCache } from "../fetchers/modelCache" + +import { clearAllMocks } from "../../../test-utils/reset" + +const { mockStreamText, mockGenerateText, mockCreatePoe, mockGetModelsFromCache, mockCaptureException } = + vitest.hoisted(() => ({ + mockStreamText: vitest.fn(), + mockGenerateText: vitest.fn(), + mockCreatePoe: vitest.fn(), + mockCaptureException: vitest.fn(), + mockGetModelsFromCache: vitest.fn(), + })) + +const cachedModels = { + "anthropic/claude-sonnet-4": { + maxTokens: 10_000, + contextWindow: 200_000, + supportsImages: true, + supportsPromptCache: true, + supportsReasoningBudget: true, + inputPrice: 3, + outputPrice: 15, + }, + "openai/gpt-4o": { + maxTokens: 16_384, + contextWindow: 128_000, + supportsImages: true, + supportsPromptCache: false, + inputPrice: 2.5, + outputPrice: 10, + }, + "openai/o3": { + maxTokens: 100_000, + contextWindow: 200_000, + supportsImages: true, + supportsPromptCache: false, + supportsReasoningEffort: ["low", "medium", "high"], + inputPrice: 10, + outputPrice: 40, + }, +} + +vitest.mock("@roo-code/telemetry", () => ({ + TelemetryService: { + instance: { + captureException: (...args: unknown[]) => mockCaptureException(...args), + }, + }, +})) vitest.mock("ai-sdk-provider-poe", () => ({ createPoe: (...args: unknown[]) => mockCreatePoe(...args), @@ -41,41 +90,9 @@ vitest.mock("ai", async (importOriginal) => { }) vitest.mock("../fetchers/modelCache", () => ({ - getModelsFromCache: vitest.fn().mockReturnValue({ - "anthropic/claude-sonnet-4": { - maxTokens: 10_000, - contextWindow: 200_000, - supportsImages: true, - supportsPromptCache: true, - supportsReasoningBudget: true, - inputPrice: 3, - outputPrice: 15, - }, - "openai/gpt-4o": { - maxTokens: 16_384, - contextWindow: 128_000, - supportsImages: true, - supportsPromptCache: false, - inputPrice: 2.5, - outputPrice: 10, - }, - "openai/o3": { - maxTokens: 100_000, - contextWindow: 200_000, - supportsImages: true, - supportsPromptCache: false, - supportsReasoningEffort: ["low", "medium", "high"], - inputPrice: 10, - outputPrice: 40, - }, - }), + getModelsFromCache: mockGetModelsFromCache, })) -import { poeDefaultModelId } from "@roo-code/types" -import { PoeHandler } from "../poe" - -import { clearAllMocks } from "../../../test-utils/reset" - describe("PoeHandler", () => { const mockLanguageModel = { modelId: "test-model" } const mockPoeProvider = vitest.fn().mockReturnValue(mockLanguageModel) @@ -83,6 +100,7 @@ describe("PoeHandler", () => { beforeEach(() => { clearAllMocks() mockCreatePoe.mockReturnValue(mockPoeProvider) + mockGetModelsFromCache.mockReturnValue(cachedModels) }) describe("constructor", () => { @@ -116,9 +134,19 @@ describe("PoeHandler", () => { describe("getModel", () => { it("returns model info from cache", () => { - const handler = new PoeHandler({ poeApiKey: "key", apiModelId: "anthropic/claude-sonnet-4" }) + const options = { + poeApiKey: "key", + poeBaseUrl: "https://custom.poe.com/v1", + apiModelId: "anthropic/claude-sonnet-4", + } + const handler = new PoeHandler(options) const result = handler.getModel() + expect(getModelsFromCache).toHaveBeenCalledWith({ + provider: providerIdentifiers.poe, + apiKey: options.poeApiKey, + baseUrl: options.poeBaseUrl, + }) expect(result.id).toBe("anthropic/claude-sonnet-4") expect(result.info.contextWindow).toBe(200_000) expect(result.info.maxTokens).toBe(10_000) @@ -166,6 +194,49 @@ describe("PoeHandler", () => { expect(chunks).toContainEqual({ type: "text", text: "world!" }) expect(chunks).toContainEqual(expect.objectContaining({ type: "usage", inputTokens: 10, outputTokens: 5 })) }) + + it("reports synchronous completion failures with the canonical provider identifier", async () => { + const handler = new PoeHandler({ poeApiKey: "key", apiModelId: "openai/gpt-4o" }) + mockStreamText.mockImplementationOnce(() => { + throw new Error("request failed") + }) + + await expect( + handler.createMessage("system", [{ role: "user" as const, content: "hello" }]).next(), + ).rejects.toThrow("Poe completion error: request failed") + expect(mockCaptureException).toHaveBeenCalledWith( + expect.objectContaining({ + provider: providerIdentifiers.poe, + modelId: "openai/gpt-4o", + operation: "createMessage", + }), + ) + }) + + it("reports asynchronous stream failures with the canonical provider identifier", async () => { + const handler = new PoeHandler({ poeApiKey: "key", apiModelId: "openai/gpt-4o" }) + const failedStream = { + [Symbol.asyncIterator]() { + return this + }, + next: vitest.fn().mockRejectedValueOnce(new Error("stream failed")), + } + mockStreamText.mockReturnValueOnce({ + fullStream: failedStream, + usage: Promise.resolve(undefined), + }) + + await expect( + handler.createMessage("system", [{ role: "user" as const, content: "hello" }]).next(), + ).rejects.toThrow("Poe streaming error: stream failed") + expect(mockCaptureException).toHaveBeenCalledWith( + expect.objectContaining({ + provider: providerIdentifiers.poe, + modelId: "openai/gpt-4o", + operation: "createMessage", + }), + ) + }) }) describe("reasoning", () => { @@ -311,5 +382,21 @@ describe("PoeHandler", () => { }), ) }) + + it("reports failures with the canonical provider identifier", async () => { + const handler = new PoeHandler({ poeApiKey: "key", apiModelId: "openai/gpt-4o" }) + mockGenerateText.mockRejectedValueOnce(new Error("generation failed")) + + await expect(handler.completePrompt("complete this")).rejects.toThrow( + "Poe completion error: generation failed", + ) + expect(mockCaptureException).toHaveBeenCalledWith( + expect.objectContaining({ + provider: providerIdentifiers.poe, + modelId: "openai/gpt-4o", + operation: "completePrompt", + }), + ) + }) }) }) diff --git a/src/api/providers/anthropic-vertex.ts b/src/api/providers/anthropic-vertex.ts index 9d91b25fe5..7b72b1100b 100644 --- a/src/api/providers/anthropic-vertex.ts +++ b/src/api/providers/anthropic-vertex.ts @@ -24,6 +24,7 @@ import { } from "../../core/prompts/tools/native-tools/converters" import { BaseProvider } from "./base-provider" +import { NOT_PROVIDED } from "./constants" import { parseVertexJsonCredentials } from "./utils/vertex-credentials" import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata, CompletePromptOptions } from "../index" @@ -38,7 +39,7 @@ export class AnthropicVertexHandler extends BaseProvider implements SingleComple this.options = options // https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-claude#regions - const projectId = this.options.vertexProjectId ?? "not-provided" + const projectId = this.options.vertexProjectId ?? NOT_PROVIDED const region = this.options.vertexRegion ?? "us-east5" const parsedVertexCredentials = parseVertexJsonCredentials(this.options.vertexJsonCredentials) diff --git a/src/api/providers/constants.ts b/src/api/providers/constants.ts index 2269ce9b6c..e3491321e9 100644 --- a/src/api/providers/constants.ts +++ b/src/api/providers/constants.ts @@ -5,3 +5,5 @@ export const DEFAULT_HEADERS = { "X-Title": "Zoo Code", "User-Agent": `ZooCode/${Package.version}`, } + +export const NOT_PROVIDED = "not-provided" diff --git a/src/api/providers/deepseek.ts b/src/api/providers/deepseek.ts index 12d4afaae2..64782c9fb4 100644 --- a/src/api/providers/deepseek.ts +++ b/src/api/providers/deepseek.ts @@ -17,6 +17,7 @@ import { getModelParams } from "../transform/model-params" import { convertToR1Format } from "../transform/r1-format" import { OpenAiHandler } from "./openai" +import { NOT_PROVIDED } from "./constants" import { extractReasoningFromDelta } from "./utils/extract-reasoning" import type { ApiHandlerCreateMessageMetadata } from "../index" import { handleOpenAIError } from "./utils/error-handler" @@ -84,7 +85,7 @@ export class DeepSeekHandler extends OpenAiHandler { constructor(options: ApiHandlerOptions) { super({ ...options, - openAiApiKey: options.deepSeekApiKey ?? "not-provided", + openAiApiKey: options.deepSeekApiKey ?? NOT_PROVIDED, openAiModelId: options.apiModelId ?? deepSeekDefaultModelId, openAiBaseUrl: options.deepSeekBaseUrl || "https://api.deepseek.com", openAiStreamingEnabled: true, diff --git a/src/api/providers/fetchers/__tests__/lmstudio.test.ts b/src/api/providers/fetchers/__tests__/lmstudio.test.ts index bf7b57cdbd..789b57096f 100644 --- a/src/api/providers/fetchers/__tests__/lmstudio.test.ts +++ b/src/api/providers/fetchers/__tests__/lmstudio.test.ts @@ -1,9 +1,16 @@ import axios from "axios" import { LMStudioClient, LLMInstanceInfo, LLMInfo } from "@lmstudio/sdk" -import { ModelInfo, lMStudioDefaultModelInfo } from "@roo-code/types" +import { ModelInfo, lMStudioDefaultModelInfo, providerIdentifiers } from "@roo-code/types" -import { getLMStudioModels, parseLMStudioModel } from "../lmstudio" +import { forceFullModelDetailsLoad, getLMStudioModels, hasLoadedFullDetails, parseLMStudioModel } from "../lmstudio" + +const mockFlushModels = vi.hoisted(() => vi.fn()) + +vi.mock("../modelCache", () => ({ + flushModels: mockFlushModels, + getModels: vi.fn(), +})) // Mock axios vi.mock("axios") @@ -13,12 +20,14 @@ const mockedAxios = axios as any const mockGetModelInfo = vi.fn() const mockListLoaded = vi.fn() const mockListDownloadedModels = vi.fn() +const mockLoadModel = vi.fn() vi.mock("@lmstudio/sdk", () => { return { LMStudioClient: vi.fn().mockImplementation(function () { return { llm: { listLoaded: mockListLoaded, + model: mockLoadModel, }, system: { listDownloadedModels: mockListDownloadedModels, @@ -36,6 +45,30 @@ describe("LMStudio Fetcher", () => { mockListLoaded.mockClear() mockGetModelInfo.mockClear() mockListDownloadedModels.mockClear() + mockLoadModel.mockClear() + mockFlushModels.mockClear() + }) + + describe("forceFullModelDetailsLoad", () => { + it("loads the selected model before refreshing its server-scoped cache and recording full details", async () => { + const baseUrl = "https://securehost:4321" + const modelId = "mistralai/devstral-small-2505" + await getLMStudioModels("not a valid URL") + vi.clearAllMocks() + mockedAxios.get.mockResolvedValueOnce({ data: { status: "ok" } }) + mockLoadModel.mockResolvedValueOnce({}) + mockFlushModels.mockResolvedValueOnce(undefined) + + expect(hasLoadedFullDetails(modelId)).toBe(false) + + await forceFullModelDetailsLoad(baseUrl, modelId) + + expect(mockedAxios.get).toHaveBeenCalledWith(`${baseUrl}/v1/models`) + expect(MockedLMStudioClientConstructor).toHaveBeenCalledWith({ baseUrl: "wss://securehost:4321" }) + expect(mockLoadModel).toHaveBeenCalledWith(modelId) + expect(mockFlushModels).toHaveBeenCalledWith({ provider: providerIdentifiers.lmstudio, baseUrl }, true) + expect(hasLoadedFullDetails(modelId)).toBe(true) + }) }) describe("parseLMStudioModel", () => { diff --git a/src/api/providers/fetchers/__tests__/modelEndpointCache.spec.ts b/src/api/providers/fetchers/__tests__/modelEndpointCache.spec.ts index b5ff897ec4..300772617b 100644 --- a/src/api/providers/fetchers/__tests__/modelEndpointCache.spec.ts +++ b/src/api/providers/fetchers/__tests__/modelEndpointCache.spec.ts @@ -1,6 +1,9 @@ // npx vitest run api/providers/fetchers/__tests__/modelEndpointCache.spec.ts import { vi, describe, it, expect, beforeEach } from "vitest" + +import { providerIdentifiers } from "@roo-code/types" + import { getModelEndpoints } from "../modelEndpointCache" import * as modelCache from "../modelCache" import * as openrouter from "../openrouter" @@ -54,7 +57,7 @@ describe("modelEndpointCache", () => { vi.spyOn(openrouter, "getOpenRouterModelEndpoints").mockResolvedValue(mockEndpoints as any) const result = await getModelEndpoints({ - router: "openrouter", + router: providerIdentifiers.openrouter, modelId: "anthropic/claude-sonnet-4", endpoint: "anthropic", }) @@ -94,7 +97,7 @@ describe("modelEndpointCache", () => { vi.spyOn(openrouter, "getOpenRouterModelEndpoints").mockResolvedValue(mockEndpoints as any) const result = await getModelEndpoints({ - router: "openrouter", + router: providerIdentifiers.openrouter, modelId: "test/model", endpoint: "endpoint-1", }) @@ -122,7 +125,7 @@ describe("modelEndpointCache", () => { vi.spyOn(openrouter, "getOpenRouterModelEndpoints").mockResolvedValue(mockEndpoints as any) const result = await getModelEndpoints({ - router: "openrouter", + router: providerIdentifiers.openrouter, modelId: "missing/model", endpoint: "anthropic", }) @@ -134,7 +137,7 @@ describe("modelEndpointCache", () => { it("should return empty object for non-openrouter providers", async () => { const result = await getModelEndpoints({ - router: "vercel-ai-gateway", + router: providerIdentifiers.vercelAiGateway, modelId: "claude-sonnet-4", endpoint: "default", }) @@ -144,13 +147,13 @@ describe("modelEndpointCache", () => { it("should return empty object when modelId or endpoint is missing", async () => { const result1 = await getModelEndpoints({ - router: "openrouter", + router: providerIdentifiers.openrouter, modelId: undefined, endpoint: "anthropic", }) const result2 = await getModelEndpoints({ - router: "openrouter", + router: providerIdentifiers.openrouter, modelId: "anthropic/claude-sonnet-4", endpoint: undefined, }) diff --git a/src/api/providers/fetchers/lmstudio.ts b/src/api/providers/fetchers/lmstudio.ts index 73cb60e88e..842fe9d08d 100644 --- a/src/api/providers/fetchers/lmstudio.ts +++ b/src/api/providers/fetchers/lmstudio.ts @@ -1,7 +1,7 @@ import axios from "axios" import { LLM, LLMInfo, LLMInstanceInfo, LMStudioClient } from "@lmstudio/sdk" -import { type ModelInfo, lMStudioDefaultModelInfo } from "@roo-code/types" +import { type ModelInfo, lMStudioDefaultModelInfo, providerIdentifiers } from "@roo-code/types" import { flushModels, getModels } from "./modelCache" @@ -19,7 +19,7 @@ export const forceFullModelDetailsLoad = async (baseUrl: string, modelId: string const client = new LMStudioClient({ baseUrl: lmsUrl }) await client.llm.model(modelId) // Flush and refresh cache to get updated model details - await flushModels({ provider: "lmstudio", baseUrl }, true) + await flushModels({ provider: providerIdentifiers.lmstudio, baseUrl }, true) // Mark this model as having full details loaded. modelsWithLoadedDetails.add(modelId) diff --git a/src/api/providers/fetchers/modelEndpointCache.ts b/src/api/providers/fetchers/modelEndpointCache.ts index 06d6234f91..4e85213a6c 100644 --- a/src/api/providers/fetchers/modelEndpointCache.ts +++ b/src/api/providers/fetchers/modelEndpointCache.ts @@ -4,7 +4,7 @@ import fs from "fs/promises" import NodeCache from "node-cache" import sanitize from "sanitize-filename" -import type { ModelRecord } from "@roo-code/types" +import { providerIdentifiers, type ModelRecord } from "@roo-code/types" import { ContextProxy } from "../../../core/config/ContextProxy" import { RouterName } from "../../../shared/api" @@ -44,7 +44,7 @@ export const getModelEndpoints = async ({ }): Promise => { // OpenRouter is the only provider that supports model endpoints, but you // can see how we'd extend this to other providers in the future. - if (router !== "openrouter" || !modelId || !endpoint) { + if (router !== providerIdentifiers.openrouter || !modelId || !endpoint) { return {} } @@ -61,7 +61,7 @@ export const getModelEndpoints = async ({ // Copy model-level capabilities from the parent model to each endpoint // These are capabilities that don't vary by provider (tools, reasoning, etc.) if (Object.keys(modelProviders).length > 0) { - const parentModels = await getModels({ provider: "openrouter" }) + const parentModels = await getModels({ provider: providerIdentifiers.openrouter }) const parentModel = parentModels[modelId] if (parentModel) { diff --git a/src/api/providers/gemini.ts b/src/api/providers/gemini.ts index 44065d8801..ec0d14e4c9 100644 --- a/src/api/providers/gemini.ts +++ b/src/api/providers/gemini.ts @@ -25,6 +25,7 @@ import { getModelParams } from "../transform/model-params" import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata, CompletePromptOptions } from "../index" import { BaseProvider } from "./base-provider" +import { NOT_PROVIDED } from "./constants" import { parseVertexJsonCredentials } from "./utils/vertex-credentials" type GeminiHandlerOptions = ApiHandlerOptions & { @@ -184,9 +185,9 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl this.options = options - const project = this.options.vertexProjectId ?? "not-provided" - const location = this.options.vertexRegion ?? "not-provided" - const apiKey = this.options.geminiApiKey ?? "not-provided" + const project = this.options.vertexProjectId ?? NOT_PROVIDED + const location = this.options.vertexRegion ?? NOT_PROVIDED + const apiKey = this.options.geminiApiKey ?? NOT_PROVIDED const parsedVertexCredentials = parseVertexJsonCredentials(this.options.vertexJsonCredentials) diff --git a/src/api/providers/kenari.ts b/src/api/providers/kenari.ts index 7895a9452c..a6ad643ec3 100644 --- a/src/api/providers/kenari.ts +++ b/src/api/providers/kenari.ts @@ -6,6 +6,7 @@ import { kenariDefaultModelInfo, KENARI_DEFAULT_TEMPERATURE, KENARI_BASE_URL, + providerIdentifiers, } from "@roo-code/types" import { ApiHandlerOptions } from "../../shared/api" @@ -37,7 +38,7 @@ export class KenariHandler extends RouterProvider implements SingleCompletionHan constructor(options: ApiHandlerOptions) { super({ options, - name: "kenari", + name: providerIdentifiers.kenari, baseURL: KENARI_BASE_URL, apiKey: options.kenariApiKey, modelId: options.kenariModelId, diff --git a/src/api/providers/kimi-code.ts b/src/api/providers/kimi-code.ts index 0a50ce6ec3..3f7136806b 100644 --- a/src/api/providers/kimi-code.ts +++ b/src/api/providers/kimi-code.ts @@ -4,6 +4,8 @@ import { KIMI_CODE_BASE_URL, kimiCodeDefaultModelId, kimiCodeDefaultModelInfo, + providerIdentifiers, + type KimiCodeAuthMethod, type ModelInfo, type ModelRecord, } from "@roo-code/types" @@ -16,8 +18,12 @@ import type { ApiStream } from "../transform/stream" import { getModelParams } from "../transform/model-params" import { OpenAiHandler } from "./openai" +import { NOT_PROVIDED } from "./constants" import { getModels } from "./fetchers/modelCache" +const OAUTH_AUTH_METHOD: KimiCodeAuthMethod = "oauth" +const API_KEY_AUTH_METHOD: KimiCodeAuthMethod = "api-key" + function getHttpStatus(error: unknown): number | undefined { if (!error || typeof error !== "object") return undefined const candidate = error as { status?: unknown; cause?: { status?: unknown } } @@ -37,7 +43,7 @@ export class KimiCodeHandler extends OpenAiHandler { super({ ...options, openAiBaseUrl: KIMI_CODE_BASE_URL, - openAiApiKey: options.kimiCodeApiKey ?? "not-provided", + openAiApiKey: options.kimiCodeApiKey ?? NOT_PROVIDED, openAiModelId: options.apiModelId ?? kimiCodeDefaultModelId, openAiStreamingEnabled: true, }) @@ -45,7 +51,7 @@ export class KimiCodeHandler extends OpenAiHandler { } private async resolveAccessToken(forceRefresh = false): Promise { - if ((this.kimiOptions.kimiCodeAuthMethod ?? "oauth") === "api-key") { + if ((this.kimiOptions.kimiCodeAuthMethod ?? OAUTH_AUTH_METHOD) === API_KEY_AUTH_METHOD) { if (!this.kimiOptions.kimiCodeApiKey) throw new Error("Kimi Code API key is required") return this.kimiOptions.kimiCodeApiKey } @@ -63,7 +69,7 @@ export class KimiCodeHandler extends OpenAiHandler { if (!this.modelDiscoveryAttempted) { this.modelDiscoveryAttempted = true try { - this.models = await getModels({ provider: "kimi-code", apiKey: accessToken }) + this.models = await getModels({ provider: providerIdentifiers.kimiCode, apiKey: accessToken }) } catch (error) { // Model discovery is best-effort; preserve the configured ID and fallback metadata. console.debug("[KimiCode] Model discovery failed; using fallback model metadata", { @@ -74,7 +80,7 @@ export class KimiCodeHandler extends OpenAiHandler { } private canRefreshOAuth(): boolean { - return (this.kimiOptions.kimiCodeAuthMethod ?? "oauth") === "oauth" + return (this.kimiOptions.kimiCodeAuthMethod ?? OAUTH_AUTH_METHOD) === OAUTH_AUTH_METHOD } override async *createMessage( diff --git a/src/api/providers/lite-llm.ts b/src/api/providers/lite-llm.ts index 74a610b073..8cfe2d0a19 100644 --- a/src/api/providers/lite-llm.ts +++ b/src/api/providers/lite-llm.ts @@ -1,7 +1,7 @@ import OpenAI from "openai" import { Anthropic } from "@anthropic-ai/sdk" // Keep for type usage only -import { litellmDefaultModelId, litellmDefaultModelInfo } from "@roo-code/types" +import { litellmDefaultModelId, litellmDefaultModelInfo, providerIdentifiers } from "@roo-code/types" import { calculateApiCostOpenAI } from "../../shared/cost" @@ -27,7 +27,7 @@ export class LiteLLMHandler extends RouterProvider implements SingleCompletionHa constructor(options: ApiHandlerOptions) { super({ options, - name: "litellm", + name: providerIdentifiers.litellm, baseURL: `${options.litellmBaseUrl || "http://localhost:4000"}`, apiKey: options.litellmApiKey || "dummy-key", modelId: options.litellmModelId, diff --git a/src/api/providers/lm-studio.ts b/src/api/providers/lm-studio.ts index 79f5355ef8..be752ac887 100644 --- a/src/api/providers/lm-studio.ts +++ b/src/api/providers/lm-studio.ts @@ -2,7 +2,12 @@ import { Anthropic } from "@anthropic-ai/sdk" import OpenAI from "openai" import axios from "axios" -import { type ModelInfo, openAiModelInfoSaneDefaults, LMSTUDIO_DEFAULT_TEMPERATURE } from "@roo-code/types" +import { + type ModelInfo, + openAiModelInfoSaneDefaults, + LMSTUDIO_DEFAULT_TEMPERATURE, + providerIdentifiers, +} from "@roo-code/types" import type { ApiHandlerOptions } from "../../shared/api" @@ -171,7 +176,7 @@ export class LmStudioHandler extends BaseProvider implements SingleCompletionHan override getModel(): { id: string; info: ModelInfo } { const models = getModelsFromCache({ - provider: "lmstudio", + provider: providerIdentifiers.lmstudio, baseUrl: this.options.lmStudioBaseUrl, }) if (models && this.options.lmStudioModelId && models[this.options.lmStudioModelId]) { diff --git a/src/api/providers/mimo.ts b/src/api/providers/mimo.ts index 2901c2e926..e3a794afae 100644 --- a/src/api/providers/mimo.ts +++ b/src/api/providers/mimo.ts @@ -12,6 +12,7 @@ import { handleProviderError } from "./utils/error-handler" import { extractReasoningFromDelta } from "./utils/extract-reasoning" import { OpenAiHandler } from "./openai" +import { NOT_PROVIDED } from "./constants" import type { ApiHandlerCreateMessageMetadata } from "../index" import { sanitizeOpenAiCallId } from "../../utils/tool-id" @@ -27,7 +28,7 @@ export class MimoHandler extends OpenAiHandler { constructor(options: ApiHandlerOptions) { super({ ...options, - openAiApiKey: options.mimoApiKey ?? "not-provided", + openAiApiKey: options.mimoApiKey ?? NOT_PROVIDED, openAiModelId: options.apiModelId ?? mimoDefaultModelId, openAiBaseUrl: options.mimoBaseUrl || "https://token-plan-sgp.xiaomimimo.com/v1", openAiStreamingEnabled: true, diff --git a/src/api/providers/moonshot.ts b/src/api/providers/moonshot.ts index 42bd2bfaf7..6fd012ef7f 100644 --- a/src/api/providers/moonshot.ts +++ b/src/api/providers/moonshot.ts @@ -8,6 +8,7 @@ import type { ApiStreamUsageChunk } from "../transform/stream" import { getModelParams } from "../transform/model-params" import { OpenAiHandler } from "./openai" +import { NOT_PROVIDED } from "./constants" export class MoonshotHandler extends OpenAiHandler { constructor(options: ApiHandlerOptions) { @@ -16,7 +17,7 @@ export class MoonshotHandler extends OpenAiHandler { // OpenAI Node SDK path as the generic "OpenAI Compatible" provider. super({ ...options, - openAiApiKey: options.moonshotApiKey ?? "not-provided", + openAiApiKey: options.moonshotApiKey ?? NOT_PROVIDED, openAiModelId: options.apiModelId ?? moonshotDefaultModelId, openAiBaseUrl: options.moonshotBaseUrl || "https://api.moonshot.ai/v1", }) diff --git a/src/api/providers/openai-native.ts b/src/api/providers/openai-native.ts index 8dffe03dcc..a919e2c82b 100644 --- a/src/api/providers/openai-native.ts +++ b/src/api/providers/openai-native.ts @@ -28,6 +28,7 @@ import { ApiStream, ApiStreamUsageChunk } from "../transform/stream" import { getModelParams } from "../transform/model-params" import { BaseProvider } from "./base-provider" +import { NOT_PROVIDED } from "./constants" import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata, CompletePromptOptions } from "../index" import { isMcpTool } from "../../utils/mcp-name" import { sanitizeOpenAiCallId } from "../../utils/tool-id" @@ -95,7 +96,7 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio if (this.options.enableResponsesReasoningSummary === undefined) { this.options.enableResponsesReasoningSummary = true } - const apiKey = this.options.openAiNativeApiKey ?? "not-provided" + const apiKey = this.options.openAiNativeApiKey ?? NOT_PROVIDED // Include originator, session_id, and User-Agent headers for API tracking and debugging const userAgent = `zoo-code/${Package.version} (${os.platform()} ${os.release()}; ${os.arch()}) node/${process.version.slice(1)}` this.client = new OpenAI({ @@ -555,7 +556,7 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio systemPrompt?: string, messages?: Anthropic.Messages.MessageParam[], ): ApiStream { - const apiKey = this.options.openAiNativeApiKey ?? "not-provided" + const apiKey = this.options.openAiNativeApiKey ?? NOT_PROVIDED const baseUrl = this.options.openAiNativeBaseUrl || "https://api.openai.com" const url = `${baseUrl}/v1/responses` diff --git a/src/api/providers/openai.ts b/src/api/providers/openai.ts index 5b4476fdef..5588dd37d6 100644 --- a/src/api/providers/openai.ts +++ b/src/api/providers/openai.ts @@ -21,7 +21,7 @@ import { convertToR1Format } from "../transform/r1-format" import { ApiStream, ApiStreamUsageChunk } from "../transform/stream" import { getModelParams } from "../transform/model-params" -import { DEFAULT_HEADERS } from "./constants" +import { DEFAULT_HEADERS, NOT_PROVIDED } from "./constants" import { BaseProvider } from "./base-provider" import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata, CompletePromptOptions } from "../index" import { handleOpenAIError } from "./utils/error-handler" @@ -40,7 +40,7 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl this.options = options const baseURL = this.options.openAiBaseUrl || "https://api.openai.com/v1" - const apiKey = this.options.openAiApiKey ?? "not-provided" + const apiKey = this.options.openAiApiKey ?? NOT_PROVIDED const isAzureAiInference = this._isAzureAiInference(this.options.openAiBaseUrl) const isAzureOpenAi = isAzureOpenAiBaseUrl(this.options.openAiBaseUrl, options.openAiUseAzure) diff --git a/src/api/providers/opencode-go.ts b/src/api/providers/opencode-go.ts index 6b3f633829..9456ac8fdb 100644 --- a/src/api/providers/opencode-go.ts +++ b/src/api/providers/opencode-go.ts @@ -8,6 +8,7 @@ import { opencodeGoDefaultModelInfo, OPENCODE_GO_DEFAULT_TEMPERATURE, isOpencodeGoAnthropicFormatModel, + providerIdentifiers, } from "@roo-code/types" import { ApiHandlerOptions } from "../../shared/api" @@ -81,7 +82,7 @@ export class OpencodeGoHandler extends RouterProvider implements SingleCompletio constructor(options: ApiHandlerOptions) { super({ options, - name: "opencode-go", + name: providerIdentifiers.opencodeGo, baseURL: "https://opencode.ai/zen/go/v1", apiKey: options.opencodeGoApiKey, modelId: options.opencodeGoModelId, diff --git a/src/api/providers/openrouter.ts b/src/api/providers/openrouter.ts index 3e59b4360b..f61e007214 100644 --- a/src/api/providers/openrouter.ts +++ b/src/api/providers/openrouter.ts @@ -10,6 +10,7 @@ import { OPENROUTER_DEFAULT_PROVIDER_NAME, OPEN_ROUTER_PROMPT_CACHING_MODELS, DEEP_SEEK_DEFAULT_TEMPERATURE, + providerIdentifiers, } from "@roo-code/types" import { TelemetryService } from "@roo-code/telemetry" @@ -33,7 +34,7 @@ import { getModelParams } from "../transform/model-params" import { getModels } from "./fetchers/modelCache" import { getModelEndpoints } from "./fetchers/modelEndpointCache" -import { DEFAULT_HEADERS } from "./constants" +import { DEFAULT_HEADERS, NOT_PROVIDED } from "./constants" import { BaseProvider } from "./base-provider" import type { ApiHandlerCreateMessageMetadata, CompletePromptOptions, SingleCompletionHandler } from "../index" import { handleOpenAIError } from "./utils/error-handler" @@ -151,7 +152,7 @@ export class OpenRouterHandler extends BaseProvider implements SingleCompletionH this.options = options const baseURL = this.options.openRouterBaseUrl || "https://openrouter.ai/api/v1" - const apiKey = this.options.openRouterApiKey ?? "not-provided" + const apiKey = this.options.openRouterApiKey ?? NOT_PROVIDED this.client = new OpenAI({ baseURL, apiKey, defaultHeaders: DEFAULT_HEADERS, timeout: this.timeoutMs }) @@ -164,9 +165,9 @@ export class OpenRouterHandler extends BaseProvider implements SingleCompletionH private async loadDynamicModels(): Promise { try { const [models, endpoints] = await Promise.all([ - getModels({ provider: "openrouter" }), + getModels({ provider: providerIdentifiers.openrouter }), getModelEndpoints({ - router: "openrouter", + router: providerIdentifiers.openrouter, modelId: this.options.openRouterModelId, endpoint: this.options.openRouterSpecificProvider, }), @@ -197,7 +198,7 @@ export class OpenRouterHandler extends BaseProvider implements SingleCompletionH const rawErrorMessage = parsedError || error?.message || "Unknown error" const apiError = Object.assign( - new ApiProviderError(rawErrorMessage, this.providerName, modelId, operation, error?.code), + new ApiProviderError(rawErrorMessage, providerIdentifiers.openrouter, modelId, operation, error?.code), { status: error?.code, error }, ) @@ -352,7 +353,7 @@ export class OpenRouterHandler extends BaseProvider implements SingleCompletionH const apiError = Object.assign( new ApiProviderError( rawErrorMessage, - this.providerName, + providerIdentifiers.openrouter, modelId, "createMessage", openRouterError.error?.code, @@ -368,7 +369,12 @@ export class OpenRouterHandler extends BaseProvider implements SingleCompletionH } else { // Fallback for non-OpenRouter errors const errorMessage = error instanceof Error ? error.message : String(error) - const apiError = new ApiProviderError(errorMessage, this.providerName, modelId, "createMessage") + const apiError = new ApiProviderError( + errorMessage, + providerIdentifiers.openrouter, + modelId, + "createMessage", + ) TelemetryService.instance.captureException(apiError) throw handleOpenAIError(error, this.providerName) } @@ -535,9 +541,9 @@ export class OpenRouterHandler extends BaseProvider implements SingleCompletionH public async fetchModel() { const [models, endpoints] = await Promise.all([ - getModels({ provider: "openrouter" }), + getModels({ provider: providerIdentifiers.openrouter }), getModelEndpoints({ - router: "openrouter", + router: providerIdentifiers.openrouter, modelId: this.options.openRouterModelId, endpoint: this.options.openRouterSpecificProvider, }), @@ -617,7 +623,7 @@ export class OpenRouterHandler extends BaseProvider implements SingleCompletionH const apiError = Object.assign( new ApiProviderError( rawErrorMessage, - this.providerName, + providerIdentifiers.openrouter, modelId, "completePrompt", openRouterError.error?.code, @@ -633,7 +639,12 @@ export class OpenRouterHandler extends BaseProvider implements SingleCompletionH } else { // Fallback for non-OpenRouter errors const errorMessage = error instanceof Error ? error.message : String(error) - const apiError = new ApiProviderError(errorMessage, this.providerName, modelId, "completePrompt") + const apiError = new ApiProviderError( + errorMessage, + providerIdentifiers.openrouter, + modelId, + "completePrompt", + ) TelemetryService.instance.captureException(apiError) throw handleOpenAIError(error, this.providerName) } diff --git a/src/api/providers/poe.ts b/src/api/providers/poe.ts index 1e5315b1ba..fb3255c572 100644 --- a/src/api/providers/poe.ts +++ b/src/api/providers/poe.ts @@ -9,6 +9,7 @@ import { type ModelInfo, type ReasoningEffortExtended, ApiProviderError, + providerIdentifiers, } from "@roo-code/types" import { TelemetryService } from "@roo-code/telemetry" @@ -18,6 +19,7 @@ import { convertToAiSdkMessages, convertToolsForAiSdk, processAiSdkStreamPart } import { ApiStream } from "../transform/stream" import { BaseProvider } from "./base-provider" +import { NOT_PROVIDED } from "./constants" import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata, CompletePromptOptions } from "../index" import { getModelsFromCache } from "./fetchers/modelCache" @@ -31,7 +33,7 @@ export class PoeHandler extends BaseProvider implements SingleCompletionHandler super() this.options = options this.poe = createPoe({ - apiKey: options.poeApiKey ?? "not-provided", + apiKey: options.poeApiKey ?? NOT_PROVIDED, baseURL: options.poeBaseUrl || undefined, }) } @@ -39,7 +41,7 @@ export class PoeHandler extends BaseProvider implements SingleCompletionHandler override getModel() { const id = this.options.apiModelId ?? poeDefaultModelId const cached = getModelsFromCache({ - provider: "poe", + provider: providerIdentifiers.poe, apiKey: this.options.poeApiKey, baseUrl: this.options.poeBaseUrl, }) @@ -108,7 +110,9 @@ export class PoeHandler extends BaseProvider implements SingleCompletionHandler }) } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error) - TelemetryService.instance.captureException(new ApiProviderError(errorMessage, "poe", id, "createMessage")) + TelemetryService.instance.captureException( + new ApiProviderError(errorMessage, providerIdentifiers.poe, id, "createMessage"), + ) throw new Error(`Poe completion error: ${errorMessage}`) } @@ -133,7 +137,9 @@ export class PoeHandler extends BaseProvider implements SingleCompletionHandler } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error) - TelemetryService.instance.captureException(new ApiProviderError(errorMessage, "poe", id, "createMessage")) + TelemetryService.instance.captureException( + new ApiProviderError(errorMessage, providerIdentifiers.poe, id, "createMessage"), + ) throw new Error(`Poe streaming error: ${errorMessage}`) } } @@ -148,7 +154,9 @@ export class PoeHandler extends BaseProvider implements SingleCompletionHandler return text } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error) - TelemetryService.instance.captureException(new ApiProviderError(errorMessage, "poe", id, "completePrompt")) + TelemetryService.instance.captureException( + new ApiProviderError(errorMessage, providerIdentifiers.poe, id, "completePrompt"), + ) throw new Error(`Poe completion error: ${errorMessage}`) } } diff --git a/src/api/providers/requesty.ts b/src/api/providers/requesty.ts index 5753660de5..1ba0771ce2 100644 --- a/src/api/providers/requesty.ts +++ b/src/api/providers/requesty.ts @@ -1,7 +1,13 @@ import { Anthropic } from "@anthropic-ai/sdk" import OpenAI from "openai" -import { type ModelInfo, type ModelRecord, requestyDefaultModelId, requestyDefaultModelInfo } from "@roo-code/types" +import { + type ModelInfo, + type ModelRecord, + providerIdentifiers, + requestyDefaultModelId, + requestyDefaultModelInfo, +} from "@roo-code/types" import type { ApiHandlerOptions } from "../../shared/api" import { calculateApiCostOpenAI } from "../../shared/cost" @@ -11,7 +17,7 @@ import { ApiStream, ApiStreamUsageChunk } from "../transform/stream" import { getModelParams } from "../transform/model-params" import { AnthropicProviderReasoningParams, getAnthropicProviderReasoning } from "../transform/reasoning" -import { DEFAULT_HEADERS } from "./constants" +import { DEFAULT_HEADERS, NOT_PROVIDED } from "./constants" import { getModels } from "./fetchers/modelCache" import { BaseProvider } from "./base-provider" import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata, CompletePromptOptions } from "../index" @@ -63,7 +69,7 @@ export class RequestyHandler extends BaseProvider implements SingleCompletionHan this.options = options this.baseURL = toRequestyServiceUrl(options.requestyBaseUrl) - const apiKey = this.options.requestyApiKey ?? "not-provided" + const apiKey = this.options.requestyApiKey ?? NOT_PROVIDED this.client = new OpenAI({ baseURL: this.baseURL, @@ -74,7 +80,7 @@ export class RequestyHandler extends BaseProvider implements SingleCompletionHan } public async fetchModel() { - this.models = await getModels({ provider: "requesty", baseUrl: this.baseURL }) + this.models = await getModels({ provider: providerIdentifiers.requesty, baseUrl: this.baseURL }) return this.getModel() } diff --git a/src/api/providers/router-provider.ts b/src/api/providers/router-provider.ts index 9e29be7bda..65ac904b87 100644 --- a/src/api/providers/router-provider.ts +++ b/src/api/providers/router-provider.ts @@ -7,7 +7,7 @@ import { ApiHandlerOptions, RouterName } from "../../shared/api" import { BaseProvider } from "./base-provider" import { getModels, getModelsFromCache } from "./fetchers/modelCache" -import { DEFAULT_HEADERS } from "./constants" +import { DEFAULT_HEADERS, NOT_PROVIDED } from "./constants" type RouterProviderOptions = { name: RouterName @@ -41,7 +41,7 @@ export abstract class RouterProvider extends BaseProvider { this.client = new OpenAI({ baseURL, - apiKey: apiKey ?? "not-provided", + apiKey: apiKey ?? NOT_PROVIDED, defaultHeaders: { ...DEFAULT_HEADERS, ...(options.openAiHeaders || {}), diff --git a/src/api/providers/unbound.ts b/src/api/providers/unbound.ts index c3ec9c44fc..0848e0804b 100644 --- a/src/api/providers/unbound.ts +++ b/src/api/providers/unbound.ts @@ -1,7 +1,13 @@ import { Anthropic } from "@anthropic-ai/sdk" import OpenAI from "openai" -import { type ModelInfo, type ModelRecord, unboundDefaultModelId, unboundDefaultModelInfo } from "@roo-code/types" +import { + type ModelInfo, + type ModelRecord, + providerIdentifiers, + unboundDefaultModelId, + unboundDefaultModelInfo, +} from "@roo-code/types" import type { ApiHandlerOptions } from "../../shared/api" import { calculateApiCostOpenAI } from "../../shared/cost" @@ -11,7 +17,7 @@ import { ApiStream, ApiStreamUsageChunk } from "../transform/stream" import { getModelParams } from "../transform/model-params" import { OpenAiReasoningParams } from "../transform/reasoning" -import { DEFAULT_HEADERS } from "./constants" +import { DEFAULT_HEADERS, NOT_PROVIDED } from "./constants" import { getModels } from "./fetchers/modelCache" import { BaseProvider } from "./base-provider" import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata, CompletePromptOptions } from "../index" @@ -54,7 +60,7 @@ export class UnboundHandler extends BaseProvider implements SingleCompletionHand this.options = options - const apiKey = this.options.unboundApiKey ?? "not-provided" + const apiKey = this.options.unboundApiKey ?? NOT_PROVIDED this.client = new OpenAI({ baseURL: "https://api.getunbound.ai/v1", @@ -68,7 +74,10 @@ export class UnboundHandler extends BaseProvider implements SingleCompletionHand } public async fetchModel() { - this.models = await getModels({ provider: "unbound", apiKey: this.options.unboundApiKey }) + this.models = await getModels({ + provider: providerIdentifiers.unbound, + apiKey: this.options.unboundApiKey, + }) return this.getModel() } diff --git a/src/api/providers/vercel-ai-gateway.ts b/src/api/providers/vercel-ai-gateway.ts index 0820e1b2d8..bf434e5a00 100644 --- a/src/api/providers/vercel-ai-gateway.ts +++ b/src/api/providers/vercel-ai-gateway.ts @@ -6,6 +6,7 @@ import { vercelAiGatewayDefaultModelInfo, VERCEL_AI_GATEWAY_DEFAULT_TEMPERATURE, VERCEL_AI_GATEWAY_PROMPT_CACHING_MODELS, + providerIdentifiers, } from "@roo-code/types" import { ApiHandlerOptions } from "../../shared/api" @@ -27,7 +28,7 @@ export class VercelAiGatewayHandler extends RouterProvider implements SingleComp constructor(options: ApiHandlerOptions) { super({ options, - name: "vercel-ai-gateway", + name: providerIdentifiers.vercelAiGateway, baseURL: "https://ai-gateway.vercel.sh/v1", apiKey: options.vercelAiGatewayApiKey, modelId: options.vercelAiGatewayModelId, diff --git a/src/api/providers/xai.ts b/src/api/providers/xai.ts index c47e9cefd1..189ec4e9ed 100644 --- a/src/api/providers/xai.ts +++ b/src/api/providers/xai.ts @@ -11,7 +11,7 @@ import { convertToResponsesApiInput } from "../transform/responses-api-input" import { processResponsesApiStream, createUsageNormalizer } from "../transform/responses-api-stream" import { getModelParams } from "../transform/model-params" -import { DEFAULT_HEADERS } from "./constants" +import { DEFAULT_HEADERS, NOT_PROVIDED } from "./constants" import { BaseProvider } from "./base-provider" import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata, CompletePromptOptions } from "../index" import { handleOpenAIError } from "./utils/error-handler" @@ -28,7 +28,7 @@ export class XAIHandler extends BaseProvider implements SingleCompletionHandler super() this.options = options - const apiKey = this.options.xaiApiKey ?? "not-provided" + const apiKey = this.options.xaiApiKey ?? NOT_PROVIDED this.client = new OpenAI({ baseURL: "https://api.x.ai/v1", diff --git a/src/api/providers/zai.ts b/src/api/providers/zai.ts index 5ebc0e19a3..c53a434e38 100644 --- a/src/api/providers/zai.ts +++ b/src/api/providers/zai.ts @@ -15,6 +15,7 @@ import { convertToZAiFormat } from "../transform/zai-format" import type { ApiHandlerCreateMessageMetadata, CompletePromptOptions } from "../index" import { BaseOpenAiCompatibleProvider } from "./base-openai-compatible-provider" +import { NOT_PROVIDED } from "./constants" import { handleOpenAIError } from "./utils/error-handler" // Custom interface for Z.ai params to support thinking mode and reasoning effort tiers. @@ -37,7 +38,7 @@ export class ZAiHandler extends BaseOpenAiCompatibleProvider { ...options, providerName: "Z.ai", baseURL: zaiApiLineConfigs[apiLine].baseUrl, - apiKey: options.zaiApiKey ?? "not-provided", + apiKey: options.zaiApiKey ?? NOT_PROVIDED, defaultProviderModelId: defaultModelId, providerModels: models, defaultTemperature: ZAI_DEFAULT_TEMPERATURE, diff --git a/src/api/providers/zoo-gateway.ts b/src/api/providers/zoo-gateway.ts index cea410bb2e..4ff059df61 100644 --- a/src/api/providers/zoo-gateway.ts +++ b/src/api/providers/zoo-gateway.ts @@ -7,6 +7,7 @@ import { zooGatewayDefaultModelInfo, ZOO_GATEWAY_DEFAULT_TEMPERATURE, VERCEL_AI_GATEWAY_PROMPT_CACHING_MODELS, + providerIdentifiers, } from "@roo-code/types" import { ApiHandlerOptions } from "../../shared/api" @@ -19,6 +20,7 @@ import { convertToOpenAiMessages } from "../transform/openai-format" import { addCacheBreakpoints } from "../transform/caching/vercel-ai-gateway" import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata, CompletePromptOptions } from "../index" +import { NOT_PROVIDED } from "./constants" import { RouterProvider } from "./router-provider" function getApiErrorStatus(error: unknown): number | undefined { @@ -159,9 +161,9 @@ export class ZooGatewayHandler extends RouterProvider implements SingleCompletio ...(options.openAiHeaders || {}), }, }, - name: "zoo-gateway", + name: providerIdentifiers.zooGateway, baseURL, - apiKey: sessionToken || "not-provided", + apiKey: sessionToken || NOT_PROVIDED, modelId: options.zooGatewayModelId, defaultModelId: zooGatewayDefaultModelId, defaultModelInfo: zooGatewayDefaultModelInfo, diff --git a/src/core/webview/__tests__/webviewMessageHandler.routerModels.spec.ts b/src/core/webview/__tests__/webviewMessageHandler.routerModels.spec.ts index 3ceeb2f895..1ba578a894 100644 --- a/src/core/webview/__tests__/webviewMessageHandler.routerModels.spec.ts +++ b/src/core/webview/__tests__/webviewMessageHandler.routerModels.spec.ts @@ -1,7 +1,22 @@ import { describe, it, expect, vi, beforeEach } from "vitest" + +import { kimiCodeAuthMethodSchema, providerIdentifiers, RouterModelsMessageType } from "@roo-code/types" + import { webviewMessageHandler } from "../webviewMessageHandler" import type { ClineProvider } from "../ClineProvider" +const [kimiCodeOAuthAuthMethod, kimiCodeApiKeyAuthMethod] = kimiCodeAuthMethodSchema.options + +const { getKimiCodeAccessTokenMock } = vi.hoisted(() => ({ + getKimiCodeAccessTokenMock: vi.fn(), +})) + +vi.mock("../../../integrations/kimi-code/oauth", () => ({ + kimiCodeOAuthManager: { + getAccessToken: getKimiCodeAccessTokenMock, + }, +})) + // Mock vscode (minimal) vi.mock("vscode", () => ({ window: { @@ -68,13 +83,13 @@ describe("webviewMessageHandler - requestRouterModels provider filter", () => { // Default mock: return distinct model maps per provider so we can verify keys getModelsMock.mockImplementation(async (options: any) => { switch (options?.provider) { - case "openrouter": + case providerIdentifiers.openrouter: return { "openrouter/qwen2.5": { contextWindow: 32768, supportsPromptCache: false } } - case "requesty": + case providerIdentifiers.requesty: return { "requesty/model": { contextWindow: 8192, supportsPromptCache: false } } - case "vercel-ai-gateway": + case providerIdentifiers.vercelAiGateway: return { "vercel/model": { contextWindow: 8192, supportsPromptCache: false } } - case "litellm": + case providerIdentifiers.litellm: return { "litellm/model": { contextWindow: 8192, supportsPromptCache: false } } default: return {} @@ -86,7 +101,7 @@ describe("webviewMessageHandler - requestRouterModels provider filter", () => { await webviewMessageHandler(mockProvider as any, { type: "requestRooModels" } as any) expect(mockProvider.postMessageToWebview).toHaveBeenCalledWith({ - type: "singleRouterModelFetchResponse", + type: RouterModelsMessageType.singleRouterModelFetchResponse, success: false, error: "Roo Code Router has been removed. Please select and configure a different provider.", values: { provider: "roo" }, @@ -97,25 +112,29 @@ describe("webviewMessageHandler - requestRouterModels provider filter", () => { await webviewMessageHandler( mockProvider as any, { - type: "requestRouterModels", + type: RouterModelsMessageType.requestRouterModels, } as any, ) const call = (mockProvider.postMessageToWebview as any).mock.calls.find( - (c: any[]) => c[0]?.type === "routerModels", + (c: any[]) => c[0]?.type === RouterModelsMessageType.routerModels, ) expect(call).toBeTruthy() const routerModels = call[0].routerModels as Record> // Aggregate handler initializes many known routers - ensure a few expected keys exist - expect(routerModels).toHaveProperty("openrouter") - expect(routerModels).toHaveProperty("requesty") - expect(routerModels).toHaveProperty("deepseek") - expect(routerModels).toHaveProperty("moonshot") + expect(routerModels).toHaveProperty(providerIdentifiers.openrouter) + expect(routerModels).toHaveProperty(providerIdentifiers.requesty) + expect(routerModels).toHaveProperty(providerIdentifiers.deepseek) + expect(routerModels).toHaveProperty(providerIdentifiers.moonshot) expect(routerModels.deepseek).toEqual({}) expect(routerModels.moonshot).toEqual({}) - expect(getModelsMock).not.toHaveBeenCalledWith(expect.objectContaining({ provider: "deepseek" })) - expect(getModelsMock).not.toHaveBeenCalledWith(expect.objectContaining({ provider: "moonshot" })) + expect(getModelsMock).not.toHaveBeenCalledWith( + expect.objectContaining({ provider: providerIdentifiers.deepseek }), + ) + expect(getModelsMock).not.toHaveBeenCalledWith( + expect.objectContaining({ provider: providerIdentifiers.moonshot }), + ) }) it("fetches DeepSeek models when stored DeepSeek credentials exist", async () => { @@ -127,18 +146,18 @@ describe("webviewMessageHandler - requestRouterModels provider filter", () => { }) getModelsMock.mockImplementation(async (options: any) => { - if (options?.provider === "deepseek") { + if (options?.provider === providerIdentifiers.deepseek) { return { "deepseek-v4-flash": { contextWindow: 1_000_000, supportsPromptCache: true } } } switch (options?.provider) { - case "openrouter": + case providerIdentifiers.openrouter: return { "openrouter/qwen2.5": { contextWindow: 32768, supportsPromptCache: false } } - case "requesty": + case providerIdentifiers.requesty: return { "requesty/model": { contextWindow: 8192, supportsPromptCache: false } } - case "vercel-ai-gateway": + case providerIdentifiers.vercelAiGateway: return { "vercel/model": { contextWindow: 8192, supportsPromptCache: false } } - case "litellm": + case providerIdentifiers.litellm: return { "litellm/model": { contextWindow: 8192, supportsPromptCache: false } } default: return {} @@ -148,18 +167,18 @@ describe("webviewMessageHandler - requestRouterModels provider filter", () => { await webviewMessageHandler( mockProvider as any, { - type: "requestRouterModels", + type: RouterModelsMessageType.requestRouterModels, } as any, ) expect(getModelsMock).toHaveBeenCalledWith({ - provider: "deepseek", + provider: providerIdentifiers.deepseek, apiKey: "stored-deepseek-key", baseUrl: "https://deepseek.example.com", }) const call = (mockProvider.postMessageToWebview as any).mock.calls.find( - (c: any[]) => c[0]?.type === "routerModels", + (c: any[]) => c[0]?.type === RouterModelsMessageType.routerModels, ) expect(call).toBeTruthy() expect(call[0].routerModels.deepseek).toEqual({ @@ -175,18 +194,18 @@ describe("webviewMessageHandler - requestRouterModels provider filter", () => { }) getModelsMock.mockImplementation(async (options: any) => { - if (options?.provider === "deepseek") { + if (options?.provider === providerIdentifiers.deepseek) { throw new Error("DeepSeek API error") } switch (options?.provider) { - case "openrouter": + case providerIdentifiers.openrouter: return { "openrouter/qwen2.5": { contextWindow: 32768, supportsPromptCache: false } } - case "requesty": + case providerIdentifiers.requesty: return { "requesty/model": { contextWindow: 8192, supportsPromptCache: false } } - case "vercel-ai-gateway": + case providerIdentifiers.vercelAiGateway: return { "vercel/model": { contextWindow: 8192, supportsPromptCache: false } } - case "litellm": + case providerIdentifiers.litellm: return { "litellm/model": { contextWindow: 8192, supportsPromptCache: false } } default: return {} @@ -196,19 +215,19 @@ describe("webviewMessageHandler - requestRouterModels provider filter", () => { await webviewMessageHandler( mockProvider as any, { - type: "requestRouterModels", + type: RouterModelsMessageType.requestRouterModels, } as any, ) expect(mockProvider.postMessageToWebview).toHaveBeenCalledWith({ - type: "singleRouterModelFetchResponse", + type: RouterModelsMessageType.singleRouterModelFetchResponse, success: false, error: "DeepSeek API error", - values: { provider: "deepseek" }, + values: { provider: providerIdentifiers.deepseek }, }) const call = (mockProvider.postMessageToWebview as any).mock.calls.find( - (c: any[]) => c[0]?.type === "routerModels", + (c: any[]) => c[0]?.type === RouterModelsMessageType.routerModels, ) expect(call).toBeTruthy() expect(call[0].routerModels.deepseek).toEqual({}) @@ -218,23 +237,92 @@ describe("webviewMessageHandler - requestRouterModels provider filter", () => { await webviewMessageHandler( mockProvider as any, { - type: "requestRouterModels", - values: { provider: "openrouter" }, + type: RouterModelsMessageType.requestRouterModels, + values: { provider: providerIdentifiers.openrouter }, } as any, ) const call = (mockProvider.postMessageToWebview as any).mock.calls.find( - (c: any[]) => c[0]?.type === "routerModels", + (c: any[]) => c[0]?.type === RouterModelsMessageType.routerModels, ) expect(call).toBeTruthy() const routerModels = call[0].routerModels as Record> const keys = Object.keys(routerModels) - expect(keys).toEqual(["openrouter"]) + expect(keys).toEqual([providerIdentifiers.openrouter]) expect(Object.keys(routerModels.openrouter || {})).toContain("openrouter/qwen2.5") const providersCalled = getModelsMock.mock.calls.map((c: any[]) => c[0]?.provider) - expect(providersCalled).toEqual(["openrouter"]) + expect(providersCalled).toEqual([providerIdentifiers.openrouter]) + }) + + it("filters to Kimi Code and dispatches an explicit API key without reading the OAuth token", async () => { + const kimiModels = { "kimi-for-coding": { contextWindow: 262_144, supportsPromptCache: true } } + getModelsMock.mockResolvedValue(kimiModels) + + await webviewMessageHandler(mockProvider, { + type: RouterModelsMessageType.requestRouterModels, + values: { + provider: providerIdentifiers.kimiCode, + kimiCodeAuthMethod: kimiCodeApiKeyAuthMethod, + kimiCodeApiKey: "preview-kimi-api-key", + }, + }) + + expect(getKimiCodeAccessTokenMock).not.toHaveBeenCalled() + expect(getModelsMock).toHaveBeenCalledTimes(1) + expect(getModelsMock).toHaveBeenCalledWith({ + provider: providerIdentifiers.kimiCode, + apiKey: "preview-kimi-api-key", + }) + + const response = mockProvider.postMessageToWebview.mock.calls.find( + (call) => call[0]?.type === RouterModelsMessageType.routerModels, + ) + expect(response).toBeDefined() + if (!response) throw new Error("Expected routerModels response") + expect(response[0].routerModels).toEqual({ [providerIdentifiers.kimiCode]: kimiModels }) + }) + + it("filters to Kimi Code and dispatches the OAuth access token", async () => { + getKimiCodeAccessTokenMock.mockResolvedValue("kimi-oauth-token") + + await webviewMessageHandler(mockProvider, { + type: RouterModelsMessageType.requestRouterModels, + values: { + provider: providerIdentifiers.kimiCode, + kimiCodeAuthMethod: kimiCodeOAuthAuthMethod, + }, + }) + + expect(getKimiCodeAccessTokenMock).toHaveBeenCalledTimes(1) + expect(getModelsMock).toHaveBeenCalledTimes(1) + expect(getModelsMock).toHaveBeenCalledWith({ + provider: providerIdentifiers.kimiCode, + apiKey: "kimi-oauth-token", + }) + }) + + it("excludes Kimi Code from model fetching when OAuth has no access token", async () => { + getKimiCodeAccessTokenMock.mockResolvedValue(null) + + await webviewMessageHandler(mockProvider, { + type: RouterModelsMessageType.requestRouterModels, + values: { + provider: providerIdentifiers.kimiCode, + kimiCodeAuthMethod: kimiCodeOAuthAuthMethod, + }, + }) + + expect(getKimiCodeAccessTokenMock).toHaveBeenCalledTimes(1) + expect(getModelsMock).not.toHaveBeenCalled() + + const response = mockProvider.postMessageToWebview.mock.calls.find( + (call) => call[0]?.type === RouterModelsMessageType.routerModels, + ) + expect(response).toBeDefined() + if (!response) throw new Error("Expected routerModels response") + expect(response[0].routerModels).toEqual({}) }) it("flushes cache when LiteLLM credentials are provided in message values", async () => { @@ -242,7 +330,7 @@ describe("webviewMessageHandler - requestRouterModels provider filter", () => { await webviewMessageHandler( mockProvider as any, { - type: "requestRouterModels", + type: RouterModelsMessageType.requestRouterModels, values: { litellmApiKey: "test-api-key", litellmBaseUrl: "http://localhost:4000", @@ -252,15 +340,17 @@ describe("webviewMessageHandler - requestRouterModels provider filter", () => { // flushModels should have been called for litellm with refresh=true and credentials expect(flushModelsMock).toHaveBeenCalledWith( - { provider: "litellm", apiKey: "test-api-key", baseUrl: "http://localhost:4000" }, + { provider: providerIdentifiers.litellm, apiKey: "test-api-key", baseUrl: "http://localhost:4000" }, true, ) // getModels should have been called with the provided credentials - const litellmCalls = getModelsMock.mock.calls.filter((c: any[]) => c[0]?.provider === "litellm") + const litellmCalls = getModelsMock.mock.calls.filter( + (c: any[]) => c[0]?.provider === providerIdentifiers.litellm, + ) expect(litellmCalls.length).toBe(1) expect(litellmCalls[0][0]).toEqual({ - provider: "litellm", + provider: providerIdentifiers.litellm, apiKey: "test-api-key", baseUrl: "http://localhost:4000", }) @@ -278,24 +368,80 @@ describe("webviewMessageHandler - requestRouterModels provider filter", () => { await webviewMessageHandler( mockProvider as any, { - type: "requestRouterModels", + type: RouterModelsMessageType.requestRouterModels, } as any, ) // flushModels should NOT have been called for litellm - const litellmFlushCalls = flushModelsMock.mock.calls.filter((c: any[]) => c[0] === "litellm") + const litellmFlushCalls = flushModelsMock.mock.calls.filter( + (c: any[]) => c[0]?.provider === providerIdentifiers.litellm, + ) expect(litellmFlushCalls.length).toBe(0) // getModels should still have been called with stored credentials - const litellmCalls = getModelsMock.mock.calls.filter((c: any[]) => c[0]?.provider === "litellm") + const litellmCalls = getModelsMock.mock.calls.filter( + (c: any[]) => c[0]?.provider === providerIdentifiers.litellm, + ) expect(litellmCalls.length).toBe(1) expect(litellmCalls[0][0]).toEqual({ - provider: "litellm", + provider: providerIdentifiers.litellm, apiKey: "stored-api-key", baseUrl: "http://stored:4000", }) }) + it("flushes and fetches Poe models with explicit unsaved credentials", async () => { + const poeModels = { "claude-sonnet": { contextWindow: 200_000, supportsPromptCache: false } } + getModelsMock.mockImplementation(async (options: { provider?: string }) => + options.provider === providerIdentifiers.poe ? poeModels : {}, + ) + + await webviewMessageHandler(mockProvider, { + type: RouterModelsMessageType.requestRouterModels, + values: { + poeApiKey: "new-poe-key", + poeBaseUrl: "https://poe.example.com/v1", + }, + }) + + const poeOptions = { + provider: providerIdentifiers.poe, + apiKey: "new-poe-key", + baseUrl: "https://poe.example.com/v1", + } + expect(flushModelsMock).toHaveBeenCalledWith(poeOptions, true) + expect(getModelsMock).toHaveBeenCalledWith(poeOptions) + + const response = mockProvider.postMessageToWebview.mock.calls.find( + (call) => call[0]?.type === RouterModelsMessageType.routerModels, + ) + expect(response).toBeDefined() + if (!response) throw new Error("Expected routerModels response") + expect(response[0].routerModels.poe).toEqual(poeModels) + }) + + it("flushes DeepSeek models when an unsaved base URL is paired with the stored API key", async () => { + mockProvider.getState.mockResolvedValue({ + apiConfiguration: { + deepSeekApiKey: "stored-deepseek-key", + deepSeekBaseUrl: "https://stored.deepseek.example.com", + }, + }) + + await webviewMessageHandler(mockProvider, { + type: RouterModelsMessageType.requestRouterModels, + values: { deepSeekBaseUrl: "https://preview.deepseek.example.com" }, + }) + + const deepSeekOptions = { + provider: providerIdentifiers.deepseek, + apiKey: "stored-deepseek-key", + baseUrl: "https://preview.deepseek.example.com", + } + expect(flushModelsMock).toHaveBeenCalledWith(deepSeekOptions, true) + expect(getModelsMock).toHaveBeenCalledWith(deepSeekOptions) + }) + it("fetches Moonshot models when stored Moonshot credentials exist", async () => { mockProvider.getState.mockResolvedValue({ apiConfiguration: { @@ -305,18 +451,18 @@ describe("webviewMessageHandler - requestRouterModels provider filter", () => { }) getModelsMock.mockImplementation(async (options: any) => { - if (options?.provider === "moonshot") { + if (options?.provider === providerIdentifiers.moonshot) { return { "kimi-k2-0905-preview": { contextWindow: 262144, supportsPromptCache: true } } } switch (options?.provider) { - case "openrouter": + case providerIdentifiers.openrouter: return { "openrouter/qwen2.5": { contextWindow: 32768, supportsPromptCache: false } } - case "requesty": + case providerIdentifiers.requesty: return { "requesty/model": { contextWindow: 8192, supportsPromptCache: false } } - case "vercel-ai-gateway": + case providerIdentifiers.vercelAiGateway: return { "vercel/model": { contextWindow: 8192, supportsPromptCache: false } } - case "litellm": + case providerIdentifiers.litellm: return { "litellm/model": { contextWindow: 8192, supportsPromptCache: false } } default: return {} @@ -326,18 +472,18 @@ describe("webviewMessageHandler - requestRouterModels provider filter", () => { await webviewMessageHandler( mockProvider as any, { - type: "requestRouterModels", + type: RouterModelsMessageType.requestRouterModels, } as any, ) expect(getModelsMock).toHaveBeenCalledWith({ - provider: "moonshot", + provider: providerIdentifiers.moonshot, apiKey: "stored-moonshot-key", baseUrl: "https://api.moonshot.ai/v1", }) const call = (mockProvider.postMessageToWebview as any).mock.calls.find( - (c: any[]) => c[0]?.type === "routerModels", + (c: any[]) => c[0]?.type === RouterModelsMessageType.routerModels, ) expect(call).toBeTruthy() expect(call[0].routerModels.moonshot).toEqual({ @@ -353,7 +499,7 @@ describe("webviewMessageHandler - requestRouterModels provider filter", () => { await webviewMessageHandler( mockProvider as any, { - type: "requestRouterModels", + type: RouterModelsMessageType.requestRouterModels, values: { moonshotApiKey: "new-moonshot-key", moonshotBaseUrl: "https://api.moonshot.cn/v1", @@ -362,19 +508,23 @@ describe("webviewMessageHandler - requestRouterModels provider filter", () => { ) // flushModels should have been called for moonshot - const moonshotFlushCalls = flushModelsMock.mock.calls.filter((c: any[]) => c[0]?.provider === "moonshot") + const moonshotFlushCalls = flushModelsMock.mock.calls.filter( + (c: any[]) => c[0]?.provider === providerIdentifiers.moonshot, + ) expect(moonshotFlushCalls.length).toBe(1) expect(moonshotFlushCalls[0][0]).toEqual({ - provider: "moonshot", + provider: providerIdentifiers.moonshot, apiKey: "new-moonshot-key", baseUrl: "https://api.moonshot.cn/v1", }) // getModels should use the provided credentials - const moonshotCalls = getModelsMock.mock.calls.filter((c: any[]) => c[0]?.provider === "moonshot") + const moonshotCalls = getModelsMock.mock.calls.filter( + (c: any[]) => c[0]?.provider === providerIdentifiers.moonshot, + ) expect(moonshotCalls.length).toBe(1) expect(moonshotCalls[0][0]).toEqual({ - provider: "moonshot", + provider: providerIdentifiers.moonshot, apiKey: "new-moonshot-key", baseUrl: "https://api.moonshot.cn/v1", }) @@ -388,18 +538,18 @@ describe("webviewMessageHandler - requestRouterModels provider filter", () => { }) getModelsMock.mockImplementation(async (options: any) => { - if (options?.provider === "moonshot") { + if (options?.provider === providerIdentifiers.moonshot) { return { "kimi-k2-0905-preview": { contextWindow: 262144, supportsPromptCache: true } } } switch (options?.provider) { - case "openrouter": + case providerIdentifiers.openrouter: return { "openrouter/qwen2.5": { contextWindow: 32768, supportsPromptCache: false } } - case "requesty": + case providerIdentifiers.requesty: return { "requesty/model": { contextWindow: 8192, supportsPromptCache: false } } - case "vercel-ai-gateway": + case providerIdentifiers.vercelAiGateway: return { "vercel/model": { contextWindow: 8192, supportsPromptCache: false } } - case "litellm": + case providerIdentifiers.litellm: return { "litellm/model": { contextWindow: 8192, supportsPromptCache: false } } default: return {} @@ -409,19 +559,23 @@ describe("webviewMessageHandler - requestRouterModels provider filter", () => { await webviewMessageHandler( mockProvider as any, { - type: "requestRouterModels", + type: RouterModelsMessageType.requestRouterModels, } as any, ) // flushModels should NOT have been called for moonshot - const moonshotFlushCalls = flushModelsMock.mock.calls.filter((c: any[]) => c[0]?.provider === "moonshot") + const moonshotFlushCalls = flushModelsMock.mock.calls.filter( + (c: any[]) => c[0]?.provider === providerIdentifiers.moonshot, + ) expect(moonshotFlushCalls.length).toBe(0) // getModels should still have been called with stored credentials - const moonshotCalls = getModelsMock.mock.calls.filter((c: any[]) => c[0]?.provider === "moonshot") + const moonshotCalls = getModelsMock.mock.calls.filter( + (c: any[]) => c[0]?.provider === providerIdentifiers.moonshot, + ) expect(moonshotCalls.length).toBe(1) expect(moonshotCalls[0][0]).toEqual({ - provider: "moonshot", + provider: providerIdentifiers.moonshot, apiKey: "stored-moonshot-key", baseUrl: undefined, }) @@ -435,18 +589,18 @@ describe("webviewMessageHandler - requestRouterModels provider filter", () => { }) getModelsMock.mockImplementation(async (options: any) => { - if (options?.provider === "moonshot") { + if (options?.provider === providerIdentifiers.moonshot) { throw new Error("Moonshot API error") } switch (options?.provider) { - case "openrouter": + case providerIdentifiers.openrouter: return { "openrouter/qwen2.5": { contextWindow: 32768, supportsPromptCache: false } } - case "requesty": + case providerIdentifiers.requesty: return { "requesty/model": { contextWindow: 8192, supportsPromptCache: false } } - case "vercel-ai-gateway": + case providerIdentifiers.vercelAiGateway: return { "vercel/model": { contextWindow: 8192, supportsPromptCache: false } } - case "litellm": + case providerIdentifiers.litellm: return { "litellm/model": { contextWindow: 8192, supportsPromptCache: false } } default: return {} @@ -456,20 +610,22 @@ describe("webviewMessageHandler - requestRouterModels provider filter", () => { await webviewMessageHandler( mockProvider as any, { - type: "requestRouterModels", + type: RouterModelsMessageType.requestRouterModels, } as any, ) // Should have posted an error for moonshot const errorCall = (mockProvider.postMessageToWebview as any).mock.calls.find( - (c: any[]) => c[0]?.type === "singleRouterModelFetchResponse" && c[0]?.values?.provider === "moonshot", + (c: any[]) => + c[0]?.type === RouterModelsMessageType.singleRouterModelFetchResponse && + c[0]?.values?.provider === providerIdentifiers.moonshot, ) expect(errorCall).toBeTruthy() expect(errorCall[0].success).toBe(false) // Aggregate entry should still be empty const call = (mockProvider.postMessageToWebview as any).mock.calls.find( - (c: any[]) => c[0]?.type === "routerModels", + (c: any[]) => c[0]?.type === RouterModelsMessageType.routerModels, ) expect(call).toBeTruthy() expect(call[0].routerModels.moonshot).toEqual({}) diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index e88fd864cd..e75620e6c1 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -1068,21 +1068,21 @@ export const webviewMessageHandler = async ( const routerModels: Record = providerFilter ? ({} as Record) : { - openrouter: {}, - "vercel-ai-gateway": {}, - "zoo-gateway": {}, - litellm: {}, - requesty: {}, - unbound: {}, - ollama: {}, - lmstudio: {}, - poe: {}, - deepseek: {}, - moonshot: {}, - "opencode-go": {}, - kenari: {}, - nanogpt: {}, - "kimi-code": {}, + [providerIdentifiers.openrouter]: {}, + [providerIdentifiers.vercelAiGateway]: {}, + [providerIdentifiers.zooGateway]: {}, + [providerIdentifiers.litellm]: {}, + [providerIdentifiers.requesty]: {}, + [providerIdentifiers.unbound]: {}, + [providerIdentifiers.ollama]: {}, + [providerIdentifiers.lmstudio]: {}, + [providerIdentifiers.poe]: {}, + [providerIdentifiers.deepseek]: {}, + [providerIdentifiers.moonshot]: {}, + [providerIdentifiers.opencodeGo]: {}, + [providerIdentifiers.kenari]: {}, + [providerIdentifiers.nanogpt]: {}, + [providerIdentifiers.kimiCode]: {}, } const safeGetModels = async (options: GetModelsOptions): Promise => { @@ -1100,27 +1100,33 @@ export const webviewMessageHandler = async ( // Base candidates (only those handled by this aggregate fetcher) const candidates: { key: RouterName; options: GetModelsOptions }[] = [ - { key: "openrouter", options: { provider: "openrouter" } }, { - key: "requesty", + key: providerIdentifiers.openrouter, + options: { provider: providerIdentifiers.openrouter }, + }, + { + key: providerIdentifiers.requesty, options: { - provider: "requesty", + provider: providerIdentifiers.requesty, apiKey: apiConfiguration.requestyApiKey, baseUrl: apiConfiguration.requestyBaseUrl, }, }, { - key: "unbound", + key: providerIdentifiers.unbound, options: { - provider: "unbound", + provider: providerIdentifiers.unbound, apiKey: apiConfiguration.unboundApiKey, }, }, - { key: "vercel-ai-gateway", options: { provider: "vercel-ai-gateway" } }, { - key: "zoo-gateway", + key: providerIdentifiers.vercelAiGateway, + options: { provider: providerIdentifiers.vercelAiGateway }, + }, + { + key: providerIdentifiers.zooGateway, options: { - provider: "zoo-gateway", + provider: providerIdentifiers.zooGateway, apiKey: apiConfiguration.zooSessionToken, baseUrl: apiConfiguration.zooGatewayBaseUrl, }, @@ -1137,12 +1143,15 @@ export const webviewMessageHandler = async ( // If explicit credentials are provided in message.values (from Refresh Models button), // flush the cache first to ensure we fetch fresh data with the new credentials if (message?.values?.litellmApiKey || message?.values?.litellmBaseUrl) { - await flushModels({ provider: "litellm", apiKey: litellmApiKey, baseUrl: litellmBaseUrl }, true) + await flushModels( + { provider: providerIdentifiers.litellm, apiKey: litellmApiKey, baseUrl: litellmBaseUrl }, + true, + ) } candidates.push({ - key: "litellm", - options: { provider: "litellm", apiKey: litellmApiKey, baseUrl: litellmBaseUrl }, + key: providerIdentifiers.litellm, + options: { provider: providerIdentifiers.litellm, apiKey: litellmApiKey, baseUrl: litellmBaseUrl }, }) } @@ -1152,12 +1161,15 @@ export const webviewMessageHandler = async ( if (poeApiKey) { if (message?.values?.poeApiKey || message?.values?.poeBaseUrl) { - await flushModels({ provider: "poe", apiKey: poeApiKey, baseUrl: poeBaseUrl }, true) + await flushModels( + { provider: providerIdentifiers.poe, apiKey: poeApiKey, baseUrl: poeBaseUrl }, + true, + ) } candidates.push({ - key: "poe", - options: { provider: "poe", apiKey: poeApiKey, baseUrl: poeBaseUrl }, + key: providerIdentifiers.poe, + options: { provider: providerIdentifiers.poe, apiKey: poeApiKey, baseUrl: poeBaseUrl }, }) } @@ -1167,12 +1179,19 @@ export const webviewMessageHandler = async ( if (deepSeekApiKey) { if (message?.values?.deepSeekApiKey || message?.values?.deepSeekBaseUrl) { - await flushModels({ provider: "deepseek", apiKey: deepSeekApiKey, baseUrl: deepSeekBaseUrl }, true) + await flushModels( + { provider: providerIdentifiers.deepseek, apiKey: deepSeekApiKey, baseUrl: deepSeekBaseUrl }, + true, + ) } candidates.push({ - key: "deepseek", - options: { provider: "deepseek", apiKey: deepSeekApiKey, baseUrl: deepSeekBaseUrl }, + key: providerIdentifiers.deepseek, + options: { + provider: providerIdentifiers.deepseek, + apiKey: deepSeekApiKey, + baseUrl: deepSeekBaseUrl, + }, }) } @@ -1182,12 +1201,19 @@ export const webviewMessageHandler = async ( if (moonshotApiKey) { if (message?.values?.moonshotApiKey || message?.values?.moonshotBaseUrl) { - await flushModels({ provider: "moonshot", apiKey: moonshotApiKey, baseUrl: moonshotBaseUrl }, true) + await flushModels( + { provider: providerIdentifiers.moonshot, apiKey: moonshotApiKey, baseUrl: moonshotBaseUrl }, + true, + ) } candidates.push({ - key: "moonshot", - options: { provider: "moonshot", apiKey: moonshotApiKey, baseUrl: moonshotBaseUrl }, + key: providerIdentifiers.moonshot, + options: { + provider: providerIdentifiers.moonshot, + apiKey: moonshotApiKey, + baseUrl: moonshotBaseUrl, + }, }) } @@ -1200,12 +1226,12 @@ export const webviewMessageHandler = async ( // Refresh the cache when a new key is explicitly provided (e.g. the Refresh Models button). if (message?.values?.opencodeGoApiKey) { - await flushModels({ provider: "opencode-go", apiKey: opencodeGoApiKey }, true) + await flushModels({ provider: providerIdentifiers.opencodeGo, apiKey: opencodeGoApiKey }, true) } candidates.push({ - key: "opencode-go", - options: { provider: "opencode-go", apiKey: opencodeGoApiKey }, + key: providerIdentifiers.opencodeGo, + options: { provider: providerIdentifiers.opencodeGo, apiKey: opencodeGoApiKey }, }) // Kenari's /models endpoint is public — it returns the full model list with no @@ -1217,12 +1243,12 @@ export const webviewMessageHandler = async ( // Refresh the cache when a new key is explicitly provided (e.g. the Refresh Models button). if (message?.values?.kenariApiKey) { - await flushModels({ provider: "kenari", apiKey: kenariApiKey }, true) + await flushModels({ provider: providerIdentifiers.kenari, apiKey: kenariApiKey }, true) } candidates.push({ - key: "kenari", - options: { provider: "kenari", apiKey: kenariApiKey }, + key: providerIdentifiers.kenari, + options: { provider: providerIdentifiers.kenari, apiKey: kenariApiKey }, }) // NanoGPT's detailed catalog is public, while an optional key can expose a @@ -1238,7 +1264,7 @@ export const webviewMessageHandler = async ( options: { provider: providerIdentifiers.nanogpt, apiKey: nanoGptApiKey }, }) - if (!providerFilter || providerFilter === "kimi-code") { + if (!providerFilter || providerFilter === providerIdentifiers.kimiCode) { const { kimiCodeOAuthManager } = await import("../../integrations/kimi-code/oauth") const kimiCodeAuthMethod = message?.values?.kimiCodeAuthMethod ?? apiConfiguration.kimiCodeAuthMethod ?? "oauth" @@ -1248,8 +1274,8 @@ export const webviewMessageHandler = async ( : await kimiCodeOAuthManager.getAccessToken() if (kimiCodeApiKey) { candidates.push({ - key: "kimi-code", - options: { provider: "kimi-code", apiKey: kimiCodeApiKey }, + key: providerIdentifiers.kimiCode, + options: { provider: providerIdentifiers.kimiCode, apiKey: kimiCodeApiKey }, }) } } @@ -1313,7 +1339,7 @@ export const webviewMessageHandler = async ( const apiKey = message.values?.apiKey ?? ollamaApiConfig.ollamaApiKey const logBaseUrl = baseUrl || "http://localhost:11434" const ollamaOptions = { - provider: "ollama" as const, + provider: providerIdentifiers.ollama, baseUrl, apiKey, } @@ -1361,7 +1387,7 @@ export const webviewMessageHandler = async ( lmStudioModels = await getLMStudioModels(requestedBaseUrl) } else { const lmStudioOptions = { - provider: "lmstudio" as const, + provider: providerIdentifiers.lmstudio, baseUrl: lmStudioApiConfig.lmStudioBaseUrl, } // Flush cache and refresh to ensure fresh models. From 252c69b520825ae6cc3c9f3aec5671520c85037f Mon Sep 17 00:00:00 2001 From: dw <41457565+daewoongoh@users.noreply.github.com> Date: Thu, 20 Aug 2026 01:52:56 +0000 Subject: [PATCH 34/66] fix: stream reasoning_content in LM Studio provider (#1175) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: stream reasoning_content in LM Studio provider The LM Studio handler only read `delta.content` and relied on TagMatcher to extract / tags. Reasoning models served by LM Studio (Qwen3, DeepSeek-R1, QwQ) stream thinking in a dedicated `reasoning_content` field, which TagMatcher never sees, so the whole thought stream was dropped. The same model via the OpenAI Compatible provider worked because that handler already calls the shared `extractReasoningFromDelta` helper — LM Studio was the last provider missing it. Reasoning text is now also counted toward output tokens; thinking models previously reported ~0 output tokens for turns that were mostly reasoning. Fixes #1075 * test(lmstudio): assert reasoning_content wins over reasoning Add the both-fields-present case for the LM Studio stream handler, mirroring the existing test in openai.spec.ts. The handler calls extractReasoningFromDelta once per delta, so a delta carrying both reasoning_content and reasoning must yield exactly one reasoning chunk. The helper's own unit tests cover the precedence rule in isolation, but no provider-level test pinned it end-to-end here. Asserting on the filtered array rather than a single membership check fixes the chunk count too, so a regression that emits both fields is caught. Signed-off-by: daewoongoh --------- Signed-off-by: daewoongoh --- src/api/providers/__tests__/lmstudio.spec.ts | 83 ++++++++++++++++++++ src/api/providers/lm-studio.ts | 15 +++- 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/src/api/providers/__tests__/lmstudio.spec.ts b/src/api/providers/__tests__/lmstudio.spec.ts index 0fde087957..7ab674a0a9 100644 --- a/src/api/providers/__tests__/lmstudio.spec.ts +++ b/src/api/providers/__tests__/lmstudio.spec.ts @@ -112,6 +112,89 @@ describe("LmStudioHandler", () => { expect(textChunks[0].text).toBe("Test response") }) + it("streams reasoning chunks from delta.reasoning_content", async () => { + // Regression: Qwen3 / DeepSeek-R1 style models served by LM Studio emit + // thinking via reasoning_content, not tags inside content. + mockCreate.mockImplementationOnce(async () => + asyncStreamFrom([ + { choices: [{ delta: { reasoning_content: "thinking..." }, index: 0 }] }, + { choices: [{ delta: { content: "answer" }, index: 0 }] }, + { + choices: [{ delta: {}, index: 0 }], + usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 }, + }, + ]), + ) + + const chunks = await collectStream(handler.createMessage(systemPrompt, messages)) + + expect(chunks).toContainEqual({ type: "reasoning", text: "thinking..." }) + expect(chunks).toContainEqual({ type: "text", text: "answer" }) + }) + + it("falls back to delta.reasoning when reasoning_content is absent", async () => { + mockCreate.mockImplementationOnce(async () => + asyncStreamFrom([ + { choices: [{ delta: { reasoning: "router-style thought" }, index: 0 }] }, + { + choices: [{ delta: {}, index: 0 }], + usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 }, + }, + ]), + ) + + const chunks = await collectStream(handler.createMessage(systemPrompt, messages)) + + expect(chunks).toContainEqual({ type: "reasoning", text: "router-style thought" }) + }) + + it("prefers delta.reasoning_content over delta.reasoning when both are present", async () => { + // When both reasoning_content and reasoning are set, only reasoning_content + // should be emitted as a reasoning chunk (not both). + mockCreate.mockImplementationOnce(async () => + asyncStreamFrom([ + { + choices: [ + { + delta: { + reasoning_content: "primary thought", + reasoning: "fallback thought", + }, + index: 0, + }, + ], + }, + { + choices: [{ delta: {}, index: 0 }], + usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 }, + }, + ]), + ) + + const chunks = await collectStream(handler.createMessage(systemPrompt, messages)) + + const reasoningChunks = chunks.filter((chunk) => chunk.type === "reasoning") + + expect(reasoningChunks).toEqual([{ type: "reasoning", text: "primary thought" }]) + }) + + it("still parses tags embedded in content", async () => { + mockCreate.mockImplementationOnce(async () => + asyncStreamFrom([ + { choices: [{ delta: { content: "tagged thoughtvisible" }, index: 0 }] }, + { + choices: [{ delta: {}, index: 0 }], + usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 }, + }, + ]), + ) + + const chunks = await collectStream(handler.createMessage(systemPrompt, messages)) + + expect(chunks).toContainEqual({ type: "reasoning", text: "tagged thought" }) + expect(chunks).toContainEqual({ type: "text", text: "visible" }) + }) + it("should handle API errors", async () => { mockCreate.mockRejectedValueOnce(new Error("API Error")) diff --git a/src/api/providers/lm-studio.ts b/src/api/providers/lm-studio.ts index be752ac887..0c828984bc 100644 --- a/src/api/providers/lm-studio.ts +++ b/src/api/providers/lm-studio.ts @@ -21,6 +21,7 @@ import { BaseProvider } from "./base-provider" import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata, CompletePromptOptions } from "../index" import { getModelsFromCache } from "./fetchers/modelCache" import { handleOpenAIError } from "./utils/error-handler" +import { extractReasoningFromDelta } from "./utils/extract-reasoning" export class LmStudioHandler extends BaseProvider implements SingleCompletionHandler { protected options: ApiHandlerOptions @@ -85,6 +86,7 @@ export class LmStudioHandler extends BaseProvider implements SingleCompletionHan } let assistantText = "" + let reasoningOutput = "" try { const params: OpenAI.Chat.ChatCompletionCreateParamsStreaming & { draft_model?: string } = { @@ -128,6 +130,15 @@ export class LmStudioHandler extends BaseProvider implements SingleCompletionHan } } + // Reasoning models served by LM Studio (Qwen3, DeepSeek-R1, QwQ, ...) stream + // their thinking in a dedicated `reasoning_content`/`reasoning` delta field + // rather than as tags inside `content`, so TagMatcher never sees it. + const reasoningText = extractReasoningFromDelta(delta) + if (reasoningText) { + reasoningOutput += reasoningText + yield { type: "reasoning", text: reasoningText } + } + // Handle tool calls in stream - emit partial chunks for NativeToolCallParser if (delta?.tool_calls) { for (const toolCall of delta.tool_calls) { @@ -156,7 +167,9 @@ export class LmStudioHandler extends BaseProvider implements SingleCompletionHan let outputTokens = 0 try { - outputTokens = await this.countTokens([{ type: "text", text: assistantText }]) + // Reasoning tokens are billed as output, so count them alongside the + // visible text — otherwise thinking models under-report usage entirely. + outputTokens = await this.countTokens([{ type: "text", text: reasoningOutput + assistantText }]) } catch (err) { console.error("[LmStudio] Failed to count output tokens:", err) outputTokens = 0 From afdede5b9d2e536aa1640d6d90522904b2518936 Mon Sep 17 00:00:00 2001 From: Alexei Gubin <36731953+WebMad@users.noreply.github.com> Date: Thu, 20 Aug 2026 13:16:01 +0000 Subject: [PATCH 35/66] lint(providers): enforce canonical identifiers (#1297) * lint(providers): enforce canonical identifiers Add a focused ESLint rule for canonical providerIdentifiers usage, migrate remaining provider and embedding literals, and update production and test coverage. * fix(eslint): reject raw retired provider identifiers --- pnpm-lock.yaml | 3 + .../no-raw-provider-identifiers.spec.mjs | 137 ++++++++++ src/__tests__/single-open-invariant.spec.ts | 13 +- .../__tests__/bedrock-reasoning.spec.ts | 13 +- src/api/providers/__tests__/friendli.spec.ts | 9 +- .../__tests__/gemini-handler.spec.ts | 39 +-- src/api/providers/__tests__/kimi-code.spec.ts | 3 +- src/api/transform/__tests__/reasoning.spec.ts | 31 ++- .../config/__tests__/ContextProxy.spec.ts | 13 +- .../__tests__/ProviderSettingsManager.spec.ts | 154 ++++++----- .../config/__tests__/importExport.spec.ts | 257 +++++++++--------- src/core/task/__tests__/Task.dispose.test.ts | 5 +- .../task/__tests__/Task.persistence.spec.ts | 3 +- .../Task.resume-eviction-race.spec.ts | 3 +- src/core/task/__tests__/Task.spec.ts | 2 +- .../Task.sticky-profile-race.spec.ts | 3 +- src/core/task/__tests__/Task.throttle.test.ts | 3 +- .../__tests__/apiConversationHistory.spec.ts | 15 +- .../flushPendingToolResultsToHistory.spec.ts | 3 +- .../task/__tests__/grace-retry-errors.spec.ts | 3 +- .../task/__tests__/grounding-sources.test.ts | 3 +- .../__tests__/reasoning-preservation.test.ts | 3 +- src/core/tools/GenerateImageTool.ts | 3 +- src/core/webview/ClineProvider.ts | 6 +- .../ClineProvider.apiHandlerRebuild.spec.ts | 105 +++---- .../ClineProvider.flicker-free-cancel.spec.ts | 3 +- .../ClineProvider.lockApiConfig.spec.ts | 19 +- .../webview/__tests__/ClineProvider.spec.ts | 154 +++++++---- .../ClineProvider.sticky-mode.spec.ts | 17 +- .../ClineProvider.sticky-profile.spec.ts | 41 +-- .../webview/__tests__/messageEnhancer.test.ts | 7 +- ...webviewMessageHandler.routerModels.spec.ts | 9 +- .../__tests__/webviewMessageHandler.spec.ts | 119 ++++---- src/core/webview/webviewMessageHandler.ts | 3 +- .../no-raw-provider-identifiers.mjs | 122 +++++++++ .../no-raw-provider-identifiers.test.mjs | 39 +++ src/eslint.config.mjs | 18 ++ src/package.json | 1 + .../__tests__/config-manager.spec.ts | 165 +++++------ .../code-index/__tests__/manager.spec.ts | 11 +- .../__tests__/service-factory.spec.ts | 49 ++-- src/services/code-index/config-manager.ts | 43 +-- .../embedders/__tests__/openrouter.spec.ts | 3 +- src/services/code-index/service-factory.ts | 15 +- src/shared/__tests__/ProfileValidator.spec.ts | 28 +- src/shared/__tests__/api.spec.ts | 69 +++-- .../__tests__/checkExistApiConfig.spec.ts | 22 +- src/shared/embeddingModels.ts | 15 +- .../__tests__/autoImportSettings.spec.ts | 7 +- src/utils/__tests__/enhance-prompt.spec.ts | 5 +- src/vitest.config.ts | 2 +- 51 files changed, 1145 insertions(+), 673 deletions(-) create mode 100644 src/__tests__/no-raw-provider-identifiers.spec.mjs create mode 100644 src/eslint-rules/no-raw-provider-identifiers.mjs create mode 100644 src/eslint-rules/no-raw-provider-identifiers.test.mjs diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 393c6ac143..bbe101f0c1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -668,6 +668,9 @@ importers: '@types/vscode': specifier: 1.100.0 version: 1.100.0 + '@typescript-eslint/parser': + specifier: 8.32.1 + version: 8.32.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) '@vitest/coverage-v8': specifier: 4.1.9 version: 4.1.9(vitest@4.1.9) diff --git a/src/__tests__/no-raw-provider-identifiers.spec.mjs b/src/__tests__/no-raw-provider-identifiers.spec.mjs new file mode 100644 index 0000000000..46d981b791 --- /dev/null +++ b/src/__tests__/no-raw-provider-identifiers.spec.mjs @@ -0,0 +1,137 @@ +import { Linter } from "eslint" +import typescriptParser from "@typescript-eslint/parser" +import { describe, expect, it } from "vitest" + +import { noRawProviderIdentifiers } from "../eslint-rules/no-raw-provider-identifiers.mjs" + +const linter = new Linter({ configType: "eslintrc" }) + +linter.defineRule("zoo/no-raw-provider-identifiers", noRawProviderIdentifiers) +linter.defineParser("@typescript-eslint/parser", typescriptParser) + +function lint(code) { + return linter.verify(code, { + parserOptions: { ecmaVersion: 2022, sourceType: "module" }, + rules: { "zoo/no-raw-provider-identifiers": "error" }, + }) +} + +function lintTypeScript(code) { + return linter.verify(code, { + parser: "@typescript-eslint/parser", + parserOptions: { + ecmaVersion: 2022, + sourceType: "module", + warnOnUnsupportedTypeScriptVersion: false, + }, + rules: { "zoo/no-raw-provider-identifiers": "error" }, + }) +} + +describe("no-raw-provider-identifiers", () => { + it("rejects a canonical provider literal in an apiProvider property", () => { + const messages = lint('const config = { apiProvider: "poe" }') + + expect(messages).toHaveLength(1) + expect(messages[0]).toMatchObject({ + ruleId: "zoo/no-raw-provider-identifiers", + message: 'Use providerIdentifiers.poe instead of the raw provider identifier "poe".', + }) + }) + + it("allows a non-canonical literal and a canonical registry member", () => { + expect(lint('const config = { apiProvider: "external-provider" }')).toHaveLength(0) + expect(lint("const config = { apiProvider: providerIdentifiers.poe }")).toHaveLength(0) + }) + + it("matches provider-like property names and static template literals", () => { + const messages = lint('const config = { provider: "poe", imageProvider: `openrouter` }') + + expect(messages).toHaveLength(2) + }) + + it("allows an empty static template in a provider-like context", () => { + expect(lint("const config = { apiProvider: `` }")).toHaveLength(0) + }) + + it("rejects canonical literals in provider-like variable declarations", () => { + const messages = lint(` + const apiProvider = "poe" + let fallbackProvider = \`openrouter\` + const label = "poe" + `) + + expect(messages.map(({ message }) => message)).toEqual([ + 'Use providerIdentifiers.poe instead of the raw provider identifier "poe".', + 'Use providerIdentifiers.openrouter instead of the raw provider identifier "openrouter".', + ]) + }) + + it("rejects canonical provider literals wrapped in TypeScript expressions", () => { + const messages = lintTypeScript(` + const apiProvider = "poe" as ApiProvider + const fallbackProvider = "openrouter" satisfies ApiProvider + const imageProvider = "openai-native" + const nestedProvider = ("anthropic" as ApiProvider)! + `) + + expect(messages.map(({ message }) => message)).toEqual([ + 'Use providerIdentifiers.poe instead of the raw provider identifier "poe".', + 'Use providerIdentifiers.openrouter instead of the raw provider identifier "openrouter".', + 'Use providerIdentifiers.openaiNative instead of the raw provider identifier "openai-native".', + 'Use providerIdentifiers.anthropic instead of the raw provider identifier "anthropic".', + ]) + }) + + it("rejects canonical literals in provider-like class fields", () => { + const messages = lintTypeScript(` + class Settings { + apiProvider = "poe" + label = "openrouter" + } + `) + + expect(messages.map(({ message }) => message)).toEqual([ + 'Use providerIdentifiers.poe instead of the raw provider identifier "poe".', + ]) + }) + + it("rejects canonical literals in provider-like assignments and comparisons", () => { + const messages = lint(` + config["apiProvider"] = "poe" + if (imageProvider === "openrouter") {} + if ("openai-native" !== config.fallbackProvider) {} + `) + + expect(messages.map(({ message }) => message)).toEqual([ + 'Use providerIdentifiers.poe instead of the raw provider identifier "poe".', + 'Use providerIdentifiers.openrouter instead of the raw provider identifier "openrouter".', + 'Use providerIdentifiers.openaiNative instead of the raw provider identifier "openai-native".', + ]) + }) + + it("rejects canonical literals in provider-like switch cases", () => { + const messages = lint(` + switch (config.apiProvider) { + case "poe": break + case providerIdentifiers.openrouter: break + } + `) + + expect(messages).toHaveLength(1) + expect(messages[0].message).toContain("providerIdentifiers.poe") + }) + + it("does not report canonical values outside provider-like contexts", () => { + const messages = lint(` + const label = "poe" + const config = { protocol: "anthropic", format: "openai" } + config[dynamicKey] = "poe" + if (apiProtocol === "anthropic") {} + if (provider > "poe") {} + switch (format) { case "openai": break } + `) + + expect(messages).toHaveLength(0) + }) +}) diff --git a/src/__tests__/single-open-invariant.spec.ts b/src/__tests__/single-open-invariant.spec.ts index 954261b145..af1631df9c 100644 --- a/src/__tests__/single-open-invariant.spec.ts +++ b/src/__tests__/single-open-invariant.spec.ts @@ -8,6 +8,7 @@ import { TaskScheduler } from "../core/task/TaskScheduler" import { type Task } from "../core/task/Task" import { API } from "../extension/api" import * as ProfileValidatorMod from "../shared/ProfileValidator" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" type PrivateClineProviderMethods = { createTask: ( @@ -45,7 +46,7 @@ vi.mock("../core/task/Task", () => { }) { this.taskId = opts.historyItem?.id ?? `task-${Math.random().toString(36).slice(2, 8)}` this.parentTask = opts.parentTask - this.apiConfiguration = opts.apiConfiguration ?? { apiProvider: "anthropic" } + this.apiConfiguration = opts.apiConfiguration ?? { apiProvider: providerIdentifiers.anthropic } opts.onCreated?.(this) } start() {} @@ -86,7 +87,7 @@ describe("Single-open-task invariant", () => { }, setValues: vi.fn(), getState: vi.fn().mockResolvedValue({ - apiConfiguration: { apiProvider: "anthropic", consecutiveMistakeLimit: 0 }, + apiConfiguration: { apiProvider: providerIdentifiers.anthropic, consecutiveMistakeLimit: 0 }, organizationAllowList: "*", enableCheckpoints: true, checkpointTimeout: 60, @@ -130,7 +131,7 @@ describe("Single-open-task invariant", () => { taskScheduler: new TaskScheduler(), setValues: vi.fn(), getState: vi.fn().mockResolvedValue({ - apiConfiguration: { apiProvider: "anthropic", consecutiveMistakeLimit: 0 }, + apiConfiguration: { apiProvider: providerIdentifiers.anthropic, consecutiveMistakeLimit: 0 }, organizationAllowList: "*", enableCheckpoints: true, checkpointTimeout: 60, @@ -182,7 +183,7 @@ describe("Single-open-task invariant", () => { listConfig: vi.fn().mockResolvedValue([]), }, getState: vi.fn().mockResolvedValue({ - apiConfiguration: { apiProvider: "anthropic", consecutiveMistakeLimit: 0 }, + apiConfiguration: { apiProvider: providerIdentifiers.anthropic, consecutiveMistakeLimit: 0 }, enableCheckpoints: true, checkpointTimeout: 60, experiments: {}, @@ -256,7 +257,7 @@ describe("Single-open-task invariant", () => { listConfig: vi.fn().mockResolvedValue([]), }, getState: vi.fn().mockResolvedValue({ - apiConfiguration: { apiProvider: "anthropic", consecutiveMistakeLimit: 0 }, + apiConfiguration: { apiProvider: providerIdentifiers.anthropic, consecutiveMistakeLimit: 0 }, enableCheckpoints: true, checkpointTimeout: 60, experiments: {}, @@ -328,7 +329,7 @@ describe("Single-open-task invariant", () => { listConfig: vi.fn().mockResolvedValue([]), }, getState: vi.fn().mockResolvedValue({ - apiConfiguration: { apiProvider: "anthropic", consecutiveMistakeLimit: 0 }, + apiConfiguration: { apiProvider: providerIdentifiers.anthropic, consecutiveMistakeLimit: 0 }, enableCheckpoints: true, checkpointTimeout: 60, experiments: {}, diff --git a/src/api/providers/__tests__/bedrock-reasoning.spec.ts b/src/api/providers/__tests__/bedrock-reasoning.spec.ts index 1577d51f93..d0ee0b8169 100644 --- a/src/api/providers/__tests__/bedrock-reasoning.spec.ts +++ b/src/api/providers/__tests__/bedrock-reasoning.spec.ts @@ -5,6 +5,7 @@ import { BedrockRuntimeClient, ConverseStreamCommand } from "@aws-sdk/client-bed import { logger } from "../../../utils/logging" import { clearAllMocks } from "../../../test-utils/reset" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" // Mock the AWS SDK vi.mock("@aws-sdk/client-bedrock-runtime") @@ -45,7 +46,7 @@ describe("AwsBedrockHandler - Extended Thinking", () => { describe("Extended Thinking Support", () => { it("should include thinking parameter for Claude Sonnet 4 when reasoning is enabled", async () => { handler = new AwsBedrockHandler({ - apiProvider: "bedrock", + apiProvider: providerIdentifiers.bedrock, apiModelId: "anthropic.claude-sonnet-4-20250514-v1:0", awsRegion: "us-east-1", enableReasoningEffort: true, @@ -113,7 +114,7 @@ describe("AwsBedrockHandler - Extended Thinking", () => { it("should pass thinking parameters from metadata", async () => { handler = new AwsBedrockHandler({ - apiProvider: "bedrock", + apiProvider: providerIdentifiers.bedrock, apiModelId: "anthropic.claude-3-7-sonnet-20250219-v1:0", awsRegion: "us-east-1", }) @@ -156,7 +157,7 @@ describe("AwsBedrockHandler - Extended Thinking", () => { it("should log when extended thinking is enabled", async () => { handler = new AwsBedrockHandler({ - apiProvider: "bedrock", + apiProvider: providerIdentifiers.bedrock, apiModelId: "anthropic.claude-opus-4-20250514-v1:0", awsRegion: "us-east-1", enableReasoningEffort: true, @@ -188,7 +189,7 @@ describe("AwsBedrockHandler - Extended Thinking", () => { it("should not include topP when thinking is disabled (global removal)", async () => { handler = new AwsBedrockHandler({ - apiProvider: "bedrock", + apiProvider: providerIdentifiers.bedrock, apiModelId: "anthropic.claude-3-7-sonnet-20250219-v1:0", awsRegion: "us-east-1", // Note: no enableReasoningEffort = true, so thinking is disabled @@ -234,7 +235,7 @@ describe("AwsBedrockHandler - Extended Thinking", () => { it("should enable reasoning when enableReasoningEffort is true in settings", async () => { handler = new AwsBedrockHandler({ - apiProvider: "bedrock", + apiProvider: providerIdentifiers.bedrock, apiModelId: "anthropic.claude-sonnet-4-20250514-v1:0", awsRegion: "us-east-1", enableReasoningEffort: true, // This should trigger reasoning @@ -288,7 +289,7 @@ describe("AwsBedrockHandler - Extended Thinking", () => { it("should support API key authentication", async () => { handler = new AwsBedrockHandler({ - apiProvider: "bedrock", + apiProvider: providerIdentifiers.bedrock, apiModelId: "anthropic.claude-3-5-sonnet-20241022-v2:0", awsRegion: "us-east-1", awsUseApiKey: true, diff --git a/src/api/providers/__tests__/friendli.spec.ts b/src/api/providers/__tests__/friendli.spec.ts index 0e6b21c5e5..6ac7d9c1fe 100644 --- a/src/api/providers/__tests__/friendli.spec.ts +++ b/src/api/providers/__tests__/friendli.spec.ts @@ -10,6 +10,7 @@ import { getModelMaxOutputTokens } from "../../../shared/api" import { FriendliHandler } from "../friendli" import { asyncStreamFrom, collectStream } from "../../../test-utils/stream" import { clearAllMocks } from "../../../test-utils/reset" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" // Create mock functions const mockCreate = vi.fn() @@ -324,7 +325,7 @@ describe("FriendliHandler", () => { describe("buildApiHandler friendli wiring", () => { it("returns a FriendliHandler for apiProvider='friendli'", () => { - const handler = buildApiHandler({ apiProvider: "friendli", friendliApiKey: "test-key" }) + const handler = buildApiHandler({ apiProvider: providerIdentifiers.friendli, friendliApiKey: "test-key" }) expect(handler).toBeInstanceOf(FriendliHandler) }) }) @@ -335,7 +336,7 @@ describe("Friendli model max output tokens (clamping behavior)", () => { const result = getModelMaxOutputTokens({ modelId: "zai-org/GLM-5.2", model, - settings: { apiProvider: "friendli" }, + settings: { apiProvider: providerIdentifiers.friendli }, format: "openai", }) // 1_000_000 * 0.2 = 200_000 > 131_072 → no clamping @@ -347,7 +348,7 @@ describe("Friendli model max output tokens (clamping behavior)", () => { const result = getModelMaxOutputTokens({ modelId: "zai-org/GLM-5.1", model, - settings: { apiProvider: "friendli" }, + settings: { apiProvider: providerIdentifiers.friendli }, format: "openai", }) // 200_000 * 0.2 = 40_000 < 131_072 → clamped to 40_000 @@ -359,7 +360,7 @@ describe("Friendli model max output tokens (clamping behavior)", () => { const result = getModelMaxOutputTokens({ modelId: "zai-org/GLM-5.1", model, - settings: { apiProvider: "friendli", modelMaxTokens: 80_000 }, + settings: { apiProvider: providerIdentifiers.friendli, modelMaxTokens: 80_000 }, format: "openai", }) // supportsMaxTokens=true, user set 80k, model ceiling 131072 → min(80000, 131072) = 80000 diff --git a/src/api/providers/__tests__/gemini-handler.spec.ts b/src/api/providers/__tests__/gemini-handler.spec.ts index 110f60289c..4f2ec12295 100644 --- a/src/api/providers/__tests__/gemini-handler.spec.ts +++ b/src/api/providers/__tests__/gemini-handler.spec.ts @@ -13,6 +13,7 @@ vi.mock("@roo-code/telemetry", () => ({ import { GeminiHandler } from "../gemini" import type { ApiHandlerOptions } from "../../../shared/api" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" describe("GeminiHandler backend support", () => { beforeEach(() => { @@ -24,7 +25,7 @@ describe("GeminiHandler backend support", () => { // in Gemini API, so createMessage only uses function declarations. // URL context/grounding are only added in completePrompt. const options = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, enableUrlContext: true, enableGrounding: true, } as ApiHandlerOptions @@ -41,7 +42,7 @@ describe("GeminiHandler backend support", () => { it("completePrompt passes config overrides without tools when URL context and grounding disabled", async () => { const options = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, enableUrlContext: false, enableGrounding: false, } as ApiHandlerOptions @@ -58,7 +59,7 @@ describe("GeminiHandler backend support", () => { describe("error scenarios", () => { it("should handle grounding metadata extraction failure gracefully", async () => { const options = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, enableGrounding: true, } as ApiHandlerOptions const handler = new GeminiHandler(options) @@ -93,7 +94,7 @@ describe("GeminiHandler backend support", () => { it("should handle malformed grounding metadata", async () => { const options = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, enableGrounding: true, } as ApiHandlerOptions const handler = new GeminiHandler(options) @@ -144,7 +145,7 @@ describe("GeminiHandler backend support", () => { it("should handle API errors when tools are enabled", async () => { const options = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, enableUrlContext: true, enableGrounding: true, } as ApiHandlerOptions @@ -192,7 +193,7 @@ describe("GeminiHandler backend support", () => { it("should ignore allowedFunctionNames because Gemini rejects larger restriction lists", async () => { const options = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, } as ApiHandlerOptions const handler = new GeminiHandler(options) const stub = vi.fn().mockReturnValue((async function* () {})()) @@ -213,7 +214,7 @@ describe("GeminiHandler backend support", () => { it("should include all tools when allowedFunctionNames is provided", async () => { const options = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, } as ApiHandlerOptions const handler = new GeminiHandler(options) const stub = vi.fn().mockReturnValue((async function* () {})()) @@ -236,7 +237,7 @@ describe("GeminiHandler backend support", () => { it("should not pass large allowedFunctionNames lists to Gemini", async () => { const options = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, } as ApiHandlerOptions const handler = new GeminiHandler(options) const stub = vi.fn().mockReturnValue((async function* () {})()) @@ -267,7 +268,7 @@ describe("GeminiHandler backend support", () => { it("should not pass allowedFunctionNames even when history includes tool calls", async () => { const options = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, } as ApiHandlerOptions const handler = new GeminiHandler(options) const stub = vi.fn().mockReturnValue((async function* () {})()) @@ -304,7 +305,7 @@ describe("GeminiHandler backend support", () => { it("should fall back to tool_choice when allowedFunctionNames is provided", async () => { const options = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, } as ApiHandlerOptions const handler = new GeminiHandler(options) const stub = vi.fn().mockReturnValue((async function* () {})()) @@ -327,7 +328,7 @@ describe("GeminiHandler backend support", () => { it("should fall back to tool_choice when allowedFunctionNames is empty", async () => { const options = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, } as ApiHandlerOptions const handler = new GeminiHandler(options) const stub = vi.fn().mockReturnValue((async function* () {})()) @@ -351,7 +352,7 @@ describe("GeminiHandler backend support", () => { it("should not set toolConfig when allowedFunctionNames is undefined and no tool_choice", async () => { const options = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, } as ApiHandlerOptions const handler = new GeminiHandler(options) const stub = vi.fn().mockReturnValue((async function* () {})()) @@ -374,7 +375,7 @@ describe("GeminiHandler backend support", () => { describe("Gemini schema compatibility", () => { it("should strip broad JSON Schema metadata from function declarations", async () => { const options = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, } as ApiHandlerOptions const handler = new GeminiHandler(options) const stub = vi.fn().mockReturnValue((async function* () {})()) @@ -435,7 +436,7 @@ describe("GeminiHandler backend support", () => { it("should collapse composition and type arrays in function declaration schemas", async () => { const options = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, } as ApiHandlerOptions const handler = new GeminiHandler(options) const stub = vi.fn().mockReturnValue((async function* () {})()) @@ -495,7 +496,7 @@ describe("GeminiHandler backend support", () => { }) it("should deep-merge allOf fragments instead of overwriting earlier properties", async () => { - const options = { apiProvider: "gemini" } as ApiHandlerOptions + const options = { apiProvider: providerIdentifiers.gemini } as ApiHandlerOptions const handler = new GeminiHandler(options) const stub = vi.fn().mockReturnValue((async function* () {})()) // @ts-ignore access private client @@ -540,7 +541,7 @@ describe("GeminiHandler backend support", () => { }) it("should resolve $ref entries before dropping $defs", async () => { - const options = { apiProvider: "gemini" } as ApiHandlerOptions + const options = { apiProvider: providerIdentifiers.gemini } as ApiHandlerOptions const handler = new GeminiHandler(options) const stub = vi.fn().mockReturnValue((async function* () {})()) // @ts-ignore access private client @@ -589,7 +590,7 @@ describe("GeminiHandler backend support", () => { }) it("should preserve top-level properties and required entries when allOf is also present", async () => { - const options = { apiProvider: "gemini" } as ApiHandlerOptions + const options = { apiProvider: providerIdentifiers.gemini } as ApiHandlerOptions const handler = new GeminiHandler(options) const stub = vi.fn().mockReturnValue((async function* () {})()) // @ts-ignore access private client @@ -631,7 +632,7 @@ describe("GeminiHandler backend support", () => { }) it("should stop recursive $ref expansion before the sanitized schema becomes cyclic", async () => { - const options = { apiProvider: "gemini" } as ApiHandlerOptions + const options = { apiProvider: providerIdentifiers.gemini } as ApiHandlerOptions const handler = new GeminiHandler(options) const stub = vi.fn().mockReturnValue((async function* () {})()) // @ts-ignore access private client @@ -683,7 +684,7 @@ describe("GeminiHandler backend support", () => { }) it("should preserve parameter names that collide with stripped schema keywords", async () => { - const options = { apiProvider: "gemini" } as ApiHandlerOptions + const options = { apiProvider: providerIdentifiers.gemini } as ApiHandlerOptions const handler = new GeminiHandler(options) const stub = vi.fn().mockReturnValue((async function* () {})()) // @ts-ignore access private client diff --git a/src/api/providers/__tests__/kimi-code.spec.ts b/src/api/providers/__tests__/kimi-code.spec.ts index df909d57d4..c8343f7bc4 100644 --- a/src/api/providers/__tests__/kimi-code.spec.ts +++ b/src/api/providers/__tests__/kimi-code.spec.ts @@ -2,6 +2,7 @@ import { buildApiHandler } from "../../index" import { KimiCodeHandler } from "../kimi-code" import { clearAllMocks } from "../../../test-utils/reset" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" const { mockGetAccessToken, mockForceRefreshAccessToken, mockGetModels } = vi.hoisted(() => ({ mockGetAccessToken: vi.fn(), @@ -28,7 +29,7 @@ describe("KimiCodeHandler", () => { it("is dispatched separately from Moonshot and preserves an unknown selected model", () => { const handler = buildApiHandler({ - apiProvider: "kimi-code", + apiProvider: providerIdentifiers.kimiCode, kimiCodeAuthMethod: "api-key", kimiCodeApiKey: "kimi-key", apiModelId: "future-kimi-model", diff --git a/src/api/transform/__tests__/reasoning.spec.ts b/src/api/transform/__tests__/reasoning.spec.ts index a14fffe550..004df4e60c 100644 --- a/src/api/transform/__tests__/reasoning.spec.ts +++ b/src/api/transform/__tests__/reasoning.spec.ts @@ -1,6 +1,7 @@ // npx vitest run src/api/transform/__tests__/reasoning.spec.ts import type { ModelInfo, ProviderSettings, ReasoningEffortWithMinimal } from "@roo-code/types" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" import { getOpenRouterReasoning, @@ -703,7 +704,7 @@ describe("reasoning.ts", () => { } const settings: ProviderSettings = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, enableReasoningEffort: true, reasoningEffort: "high", } @@ -730,7 +731,7 @@ describe("reasoning.ts", () => { } const settings: ProviderSettings = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, // Even with this flag false, an explicit effort selection should win enableReasoningEffort: false, reasoningEffort: "high", @@ -755,7 +756,7 @@ describe("reasoning.ts", () => { } const settings: ProviderSettings = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, reasoningEffort: "minimal", } @@ -778,7 +779,7 @@ describe("reasoning.ts", () => { } const settings: ProviderSettings = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, reasoningEffort: "medium", } @@ -809,7 +810,7 @@ describe("reasoning.ts", () => { } const settings: ProviderSettings = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, reasoningEffort: level, } @@ -833,7 +834,7 @@ describe("reasoning.ts", () => { } const settings: ProviderSettings = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, reasoningEffort: "disable", } @@ -856,7 +857,7 @@ describe("reasoning.ts", () => { } const settings: ProviderSettings = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, reasoningEffort: "none", } @@ -880,7 +881,7 @@ describe("reasoning.ts", () => { } const settings: ProviderSettings = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, enableReasoningEffort: true, } @@ -904,7 +905,7 @@ describe("reasoning.ts", () => { } const settings: ProviderSettings = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, enableReasoningEffort: true, reasoningEffort: "high", } @@ -929,7 +930,7 @@ describe("reasoning.ts", () => { } const settings: ProviderSettings = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, } const options: GetModelReasoningOptions = { @@ -953,7 +954,7 @@ describe("reasoning.ts", () => { } const settings: ProviderSettings = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, reasoningEffort: "medium", } @@ -977,7 +978,7 @@ describe("reasoning.ts", () => { } const settings: ProviderSettings = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, reasoningEffort: "medium", } @@ -1001,7 +1002,7 @@ describe("reasoning.ts", () => { } const settings: ProviderSettings = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, reasoningEffort: "high", } @@ -1025,7 +1026,7 @@ describe("reasoning.ts", () => { } const settings: ProviderSettings = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, reasoningEffort: "medium", } @@ -1049,7 +1050,7 @@ describe("reasoning.ts", () => { } const settings: ProviderSettings = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, reasoningEffort: "minimal", } diff --git a/src/core/config/__tests__/ContextProxy.spec.ts b/src/core/config/__tests__/ContextProxy.spec.ts index d4cae48177..2319a6b1a5 100644 --- a/src/core/config/__tests__/ContextProxy.spec.ts +++ b/src/core/config/__tests__/ContextProxy.spec.ts @@ -8,6 +8,7 @@ import { clearAllMocks } from "../../../test-utils/reset" import { makeExtensionContext, makeUri } from "../../../test-utils/vscode" import { ContextProxy } from "../ContextProxy" +import { providerIdentifiers, retiredProviderIdentifiers } from "@roo-code/types/provider-identifiers" vi.mock("vscode", () => ({ Uri: { @@ -270,7 +271,7 @@ describe("ContextProxy", () => { // Test with multiple values await proxy.setValues({ apiModelId: "gpt-4", - apiProvider: "openai", + apiProvider: providerIdentifiers.openai, mode: "test-mode", }) @@ -310,7 +311,7 @@ describe("ContextProxy", () => { describe("setProviderSettings", () => { it("stores and returns the complete NanoGPT configuration across secret and global state", async () => { await proxy.setProviderSettings({ - apiProvider: "nanogpt", + apiProvider: providerIdentifiers.nanogpt, nanoGptApiKey: "nanogpt-secret", nanoGptModelId: "openai/model", nanoGptRoutingPreference: "throughput", @@ -320,7 +321,7 @@ describe("ContextProxy", () => { expect(mockGlobalState.update).toHaveBeenCalledWith("nanoGptModelId", "openai/model") expect(mockGlobalState.update).toHaveBeenCalledWith("nanoGptRoutingPreference", "throughput") expect(proxy.getProviderSettings()).toMatchObject({ - apiProvider: "nanogpt", + apiProvider: providerIdentifiers.nanogpt, nanoGptApiKey: "nanogpt-secret", nanoGptModelId: "openai/model", nanoGptRoutingPreference: "throughput", @@ -339,7 +340,7 @@ describe("ContextProxy", () => { // Call setProviderSettings with new configuration await proxy.setProviderSettings({ apiModelId: "new-model", - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, // Note: openAiBaseUrl is not included in the new config }) @@ -349,7 +350,7 @@ describe("ContextProxy", () => { expect(setValuesSpy).toHaveBeenCalledWith( expect.objectContaining({ apiModelId: "new-model", - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, openAiBaseUrl: undefined, modelTemperature: undefined, }), @@ -565,7 +566,7 @@ describe("ContextProxy", () => { it("should preserve retired apiProvider and provider fields", async () => { await proxy.setValues({ - apiProvider: "groq", + apiProvider: retiredProviderIdentifiers.groq, apiModelId: "llama3-70b", openAiBaseUrl: "https://api.retired-provider.example/v1", apiKey: "retired-provider-key", diff --git a/src/core/config/__tests__/ProviderSettingsManager.spec.ts b/src/core/config/__tests__/ProviderSettingsManager.spec.ts index 56d4a6951b..b7a0a9595c 100644 --- a/src/core/config/__tests__/ProviderSettingsManager.spec.ts +++ b/src/core/config/__tests__/ProviderSettingsManager.spec.ts @@ -4,6 +4,7 @@ import { OPEN_AI_CODEX_SERVICE_TIER_KEY, OpenAiCodexServiceTier, providerIdentifiers, + retiredProviderIdentifiers, type ProviderSettings, } from "@roo-code/types" @@ -119,7 +120,7 @@ describe("ProviderSettingsManager", () => { config: {}, }, test: { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, }, }, migrations: { @@ -151,11 +152,11 @@ describe("ProviderSettingsManager", () => { rateLimitSeconds: undefined, }, test: { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, rateLimitSeconds: undefined, }, existing: { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, // this should not really be possible, unless someone has loaded a hand edited config, // but we don't overwrite so we'll check that rateLimitSeconds: 43, @@ -188,11 +189,11 @@ describe("ProviderSettingsManager", () => { consecutiveMistakeLimit: undefined, }, test: { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, consecutiveMistakeLimit: undefined, }, existing: { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, // this should not really be possible, unless someone has loaded a hand edited config, // but we don't overwrite so we'll check that consecutiveMistakeLimit: 5, @@ -228,11 +229,11 @@ describe("ProviderSettingsManager", () => { todoListEnabled: undefined, }, test: { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, todoListEnabled: undefined, }, existing: { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, // this should not really be possible, unless someone has loaded a hand edited config, // but we don't overwrite so we'll check that todoListEnabled: false, @@ -266,19 +267,19 @@ describe("ProviderSettingsManager", () => { default: { config: {}, id: "default", - apiProvider: "roo", + apiProvider: retiredProviderIdentifiers.roo, apiModelId: "roo/code-supernova", // Old model ID }, test: { - apiProvider: "roo", + apiProvider: retiredProviderIdentifiers.roo, apiModelId: "roo/code-supernova", // Old model ID }, existing: { - apiProvider: "roo", + apiProvider: retiredProviderIdentifiers.roo, apiModelId: "roo/code-supernova-1-million", // Already migrated }, otherProvider: { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiModelId: "roo/code-supernova", // Should not be migrated (different provider) }, noProvider: { @@ -329,7 +330,7 @@ describe("ProviderSettingsManager", () => { await providerSettingsManager.saveConfig("router-profile", { id: "router-id", - apiProvider: "roo", + apiProvider: retiredProviderIdentifiers.roo, apiModelId: "roo/code-supernova", rooApiKey: "router-key", } as any) @@ -357,7 +358,7 @@ describe("ProviderSettingsManager", () => { id: "default", }, test: { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, id: "test-id", }, }, @@ -376,7 +377,7 @@ describe("ProviderSettingsManager", () => { const configs = await providerSettingsManager.listConfig() expect(configs).toEqual([ { name: "default", id: "default", apiProvider: undefined }, - { name: "test", id: "test-id", apiProvider: "anthropic" }, + { name: "test", id: "test-id", apiProvider: providerIdentifiers.anthropic }, ]) }) @@ -426,7 +427,7 @@ describe("ProviderSettingsManager", () => { ) const newConfig: ProviderSettings = { - apiProvider: "vertex", + apiProvider: providerIdentifiers.vertex, apiModelId: "gemini-2.5-flash-preview-05-20", vertexKeyFile: "test-key-file", } @@ -499,7 +500,7 @@ describe("ProviderSettingsManager", () => { ) const newConfig: ProviderSettings = { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiKey: "test-key", } const newConfigWithExtra: ProviderSettings = { @@ -538,7 +539,7 @@ describe("ProviderSettingsManager", () => { currentApiConfigName: "default", apiConfigs: { test: { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiKey: "old-key", id: "test-id", }, @@ -551,7 +552,7 @@ describe("ProviderSettingsManager", () => { mockSecrets.get.mockResolvedValue(JSON.stringify(existingConfig)) const updatedConfig: ProviderSettings = { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiKey: "new-key", } @@ -561,7 +562,7 @@ describe("ProviderSettingsManager", () => { currentApiConfigName: "default", apiConfigs: { test: { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiKey: "new-key", id: "test-id", }, @@ -614,7 +615,7 @@ describe("ProviderSettingsManager", () => { // Include a legacy provider-specific field (groqApiKey) that is no // longer in the schema — passthrough() must keep it. const retiredConfig = { - apiProvider: "groq", + apiProvider: retiredProviderIdentifiers.groq, apiKey: "legacy-key", apiModelId: "legacy-model", openAiBaseUrl: "https://legacy.example/v1", @@ -647,7 +648,7 @@ describe("ProviderSettingsManager", () => { id: "default", }, test: { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, id: "test-id", }, }, @@ -704,7 +705,7 @@ describe("ProviderSettingsManager", () => { currentApiConfigName: "default", apiConfigs: { test: { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiKey: "test-key", id: "test-id", }, @@ -720,7 +721,11 @@ describe("ProviderSettingsManager", () => { const { name, ...providerSettings } = await providerSettingsManager.activateProfile({ name: "test" }) expect(name).toBe("test") - expect(providerSettings).toEqual({ apiProvider: "anthropic", apiKey: "test-key", id: "test-id" }) + expect(providerSettings).toEqual({ + apiProvider: providerIdentifiers.anthropic, + apiKey: "test-key", + id: "test-id", + }) // Get the stored config to check the structure. const calls = mockSecrets.store.mock.calls @@ -728,7 +733,7 @@ describe("ProviderSettingsManager", () => { expect(storedConfig.currentApiConfigName).toBe("test") expect(storedConfig.apiConfigs.test).toEqual({ - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiKey: "test-key", id: "test-id", }) @@ -751,7 +756,7 @@ describe("ProviderSettingsManager", () => { mockSecrets.get.mockResolvedValue( JSON.stringify({ currentApiConfigName: "default", - apiConfigs: { test: { apiProvider: "anthropic", id: "test-id" } }, + apiConfigs: { test: { apiProvider: providerIdentifiers.anthropic, id: "test-id" } }, migrations: { rateLimitSecondsMigrated: true, openAiHeadersMigrated: true, @@ -771,7 +776,7 @@ describe("ProviderSettingsManager", () => { currentApiConfigName: "valid", apiConfigs: { valid: { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiKey: "valid-key", apiModelId: "claude-3-opus-20240229", id: "valid-id", @@ -818,7 +823,7 @@ describe("ProviderSettingsManager", () => { apiConfigs: { retiredProvider: { id: "retired-id", - apiProvider: "groq", + apiProvider: retiredProviderIdentifiers.groq, apiKey: "legacy-key", apiModelId: "legacy-model", openAiBaseUrl: "https://legacy.example/v1", @@ -861,7 +866,7 @@ describe("ProviderSettingsManager", () => { currentApiConfigName: "valid", apiConfigs: { valid: { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiKey: "valid-key", apiModelId: "claude-3-opus-20240229", rateLimitSeconds: 0, @@ -912,7 +917,7 @@ describe("ProviderSettingsManager", () => { apiConfigs: { retired: { id: "retired-id", - apiProvider: "groq", + apiProvider: retiredProviderIdentifiers.groq, apiKey: "legacy-key", apiModelId: "legacy-model", openAiBaseUrl: "https://legacy.example/v1", @@ -940,7 +945,7 @@ describe("ProviderSettingsManager", () => { apiConfigs: { glm: { id: "glm-id", - apiProvider: "zai", + apiProvider: providerIdentifiers.zai, apiModelId: "glm-5.1", modelMaxTokens: 8192, modelMaxThinkingTokens: 2048, @@ -964,7 +969,7 @@ describe("ProviderSettingsManager", () => { apiConfigs: { anthropic: { id: "anthropic-id", - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiModelId: "claude-3-5-haiku-20241022", modelMaxTokens: 8192, modelMaxThinkingTokens: 2048, @@ -987,7 +992,7 @@ describe("ProviderSettingsManager", () => { mockSecrets.get.mockResolvedValue( JSON.stringify({ currentApiConfigName: "test", - apiConfigs: { test: { apiProvider: "anthropic", id: "test-id" } }, + apiConfigs: { test: { apiProvider: providerIdentifiers.anthropic, id: "test-id" } }, }), ) @@ -1002,7 +1007,10 @@ describe("ProviderSettingsManager", () => { it("should return true for existing config", async () => { const existingConfig: ProviderProfiles = { currentApiConfigName: "default", - apiConfigs: { default: { id: "default" }, test: { apiProvider: "anthropic", id: "test-id" } }, + apiConfigs: { + default: { id: "default" }, + test: { apiProvider: providerIdentifiers.anthropic, id: "test-id" }, + }, migrations: { rateLimitSecondsMigrated: false }, } @@ -1045,7 +1053,7 @@ describe("ProviderSettingsManager", () => { const cloudProfiles = { "cloud-profile": { id: "cloud-id-1", - apiProvider: "anthropic" as const, + apiProvider: providerIdentifiers.anthropic, apiKey: "secret-key", // This should be removed apiModelId: "claude-3-opus-20240229", }, @@ -1060,7 +1068,7 @@ describe("ProviderSettingsManager", () => { const storedConfig = JSON.parse(mockSecrets.store.mock.calls[0][1]) expect(storedConfig.apiConfigs["cloud-profile"]).toEqual({ id: "cloud-id-1", - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiModelId: "claude-3-opus-20240229", // apiKey should be removed }) @@ -1074,7 +1082,7 @@ describe("ProviderSettingsManager", () => { default: { id: "default-id" }, "existing-cloud": { id: "cloud-id-1", - apiProvider: "anthropic" as const, + apiProvider: providerIdentifiers.anthropic, apiKey: "existing-secret", apiModelId: "claude-3-haiku-20240307", }, @@ -1087,7 +1095,7 @@ describe("ProviderSettingsManager", () => { const cloudProfiles = { "updated-name": { id: "cloud-id-1", - apiProvider: "anthropic" as const, + apiProvider: providerIdentifiers.anthropic, apiKey: "new-secret", // Should be ignored apiModelId: "claude-3-opus-20240229", }, @@ -1102,7 +1110,7 @@ describe("ProviderSettingsManager", () => { const storedConfig = JSON.parse(mockSecrets.store.mock.calls[0][1]) expect(storedConfig.apiConfigs["updated-name"]).toEqual({ id: "cloud-id-1", - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiKey: "existing-secret", // Preserved apiModelId: "claude-3-opus-20240229", // Updated }) @@ -1115,8 +1123,8 @@ describe("ProviderSettingsManager", () => { currentApiConfigName: "default", apiConfigs: { default: { id: "default-id" }, - "cloud-profile-1": { id: "cloud-id-1", apiProvider: "anthropic" as const }, - "cloud-profile-2": { id: "cloud-id-2", apiProvider: "openai" as const }, + "cloud-profile-1": { id: "cloud-id-1", apiProvider: providerIdentifiers.anthropic }, + "cloud-profile-2": { id: "cloud-id-2", apiProvider: providerIdentifiers.openai }, }, cloudProfileIds: ["cloud-id-1", "cloud-id-2"], } @@ -1126,7 +1134,7 @@ describe("ProviderSettingsManager", () => { const cloudProfiles = { "cloud-profile-1": { id: "cloud-id-1", - apiProvider: "anthropic" as const, + apiProvider: providerIdentifiers.anthropic, }, // cloud-profile-2 is missing, should be deleted } @@ -1148,7 +1156,7 @@ describe("ProviderSettingsManager", () => { currentApiConfigName: "default", apiConfigs: { default: { id: "default-id" }, - "conflict-name": { id: "local-id", apiProvider: "openai" as const }, + "conflict-name": { id: "local-id", apiProvider: providerIdentifiers.openai }, }, cloudProfileIds: [], } @@ -1158,7 +1166,7 @@ describe("ProviderSettingsManager", () => { const cloudProfiles = { "conflict-name": { id: "cloud-id-1", - apiProvider: "anthropic" as const, + apiProvider: providerIdentifiers.anthropic, }, } @@ -1171,11 +1179,11 @@ describe("ProviderSettingsManager", () => { const storedConfig = JSON.parse(mockSecrets.store.mock.calls[0][1]) expect(storedConfig.apiConfigs["conflict-name"]).toEqual({ id: "cloud-id-1", - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, }) expect(storedConfig.apiConfigs["conflict-name_local"]).toEqual({ id: "local-id", - apiProvider: "openai", + apiProvider: providerIdentifiers.openai, }) expect(storedConfig.cloudProfileIds).toEqual(["cloud-id-1"]) }) @@ -1185,8 +1193,8 @@ describe("ProviderSettingsManager", () => { currentApiConfigName: "default", apiConfigs: { default: { id: "default-id" }, - "conflict-name": { id: "local-id-1", apiProvider: "openai" as const }, - "conflict-name_local": { id: "local-id-2", apiProvider: "vertex" as const }, + "conflict-name": { id: "local-id-1", apiProvider: providerIdentifiers.openai }, + "conflict-name_local": { id: "local-id-2", apiProvider: providerIdentifiers.vertex }, }, cloudProfileIds: [], } @@ -1196,7 +1204,7 @@ describe("ProviderSettingsManager", () => { const cloudProfiles = { "conflict-name": { id: "cloud-id-1", - apiProvider: "anthropic" as const, + apiProvider: providerIdentifiers.anthropic, }, } @@ -1209,15 +1217,15 @@ describe("ProviderSettingsManager", () => { const storedConfig = JSON.parse(mockSecrets.store.mock.calls[0][1]) expect(storedConfig.apiConfigs["conflict-name"]).toEqual({ id: "cloud-id-1", - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, }) expect(storedConfig.apiConfigs["conflict-name_1"]).toEqual({ id: "local-id-1", - apiProvider: "openai", + apiProvider: providerIdentifiers.openai, }) expect(storedConfig.apiConfigs["conflict-name_local"]).toEqual({ id: "local-id-2", - apiProvider: "vertex", + apiProvider: providerIdentifiers.vertex, }) }) @@ -1226,8 +1234,8 @@ describe("ProviderSettingsManager", () => { currentApiConfigName: "default", apiConfigs: { default: { id: "default-id" }, - "cloud-profile-1": { id: "cloud-id-1", apiProvider: "anthropic" as const }, - "cloud-profile-2": { id: "cloud-id-2", apiProvider: "openai" as const }, + "cloud-profile-1": { id: "cloud-id-1", apiProvider: providerIdentifiers.anthropic }, + "cloud-profile-2": { id: "cloud-id-2", apiProvider: providerIdentifiers.openai }, }, cloudProfileIds: ["cloud-id-1", "cloud-id-2"], } @@ -1263,11 +1271,11 @@ describe("ProviderSettingsManager", () => { const cloudProfiles = { "valid-profile": { id: "cloud-id-1", - apiProvider: "anthropic" as const, + apiProvider: providerIdentifiers.anthropic, }, "invalid-profile": { // Missing id - apiProvider: "openai" as const, + apiProvider: providerIdentifiers.openai, }, } @@ -1288,9 +1296,9 @@ describe("ProviderSettingsManager", () => { currentApiConfigName: "default", apiConfigs: { default: { id: "default-id" }, - "keep-cloud": { id: "cloud-id-1", apiProvider: "anthropic" as const, apiKey: "secret1" }, - "delete-cloud": { id: "cloud-id-2", apiProvider: "openai" as const }, - "rename-me": { id: "local-id", apiProvider: "vertex" as const }, + "keep-cloud": { id: "cloud-id-1", apiProvider: providerIdentifiers.anthropic, apiKey: "secret1" }, + "delete-cloud": { id: "cloud-id-2", apiProvider: providerIdentifiers.openai }, + "rename-me": { id: "local-id", apiProvider: providerIdentifiers.vertex }, }, cloudProfileIds: ["cloud-id-1", "cloud-id-2"], } @@ -1300,19 +1308,19 @@ describe("ProviderSettingsManager", () => { const cloudProfiles = { "updated-keep": { id: "cloud-id-1", - apiProvider: "anthropic" as const, + apiProvider: providerIdentifiers.anthropic, apiKey: "new-secret", // Should be ignored apiModelId: "claude-3-opus-20240229", }, "rename-me": { id: "cloud-id-3", - apiProvider: "openai" as const, + apiProvider: providerIdentifiers.openai, }, // delete-cloud is missing (should be deleted) // new profile "new-cloud": { id: "cloud-id-4", - apiProvider: "vertex" as const, + apiProvider: providerIdentifiers.vertex, }, } @@ -1331,7 +1339,7 @@ describe("ProviderSettingsManager", () => { // Check updates expect(storedConfig.apiConfigs["updated-keep"]).toEqual({ id: "cloud-id-1", - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiKey: "secret1", // preserved apiModelId: "claude-3-opus-20240229", }) @@ -1339,17 +1347,17 @@ describe("ProviderSettingsManager", () => { // Check renames expect(storedConfig.apiConfigs["rename-me_local"]).toEqual({ id: "local-id", - apiProvider: "vertex", + apiProvider: providerIdentifiers.vertex, }) expect(storedConfig.apiConfigs["rename-me"]).toEqual({ id: "cloud-id-3", - apiProvider: "openai", + apiProvider: providerIdentifiers.openai, }) // Check new additions expect(storedConfig.apiConfigs["new-cloud"]).toEqual({ id: "cloud-id-4", - apiProvider: "vertex", + apiProvider: providerIdentifiers.vertex, }) expect(storedConfig.cloudProfileIds).toEqual(["cloud-id-1", "cloud-id-3", "cloud-id-4"]) @@ -1376,7 +1384,7 @@ describe("ProviderSettingsManager", () => { apiConfigs: { "active-profile": { id: "active-id", - apiProvider: "anthropic" as const, + apiProvider: providerIdentifiers.anthropic, apiKey: "old-key", }, }, @@ -1388,7 +1396,7 @@ describe("ProviderSettingsManager", () => { const cloudProfiles = { "active-profile": { id: "active-id", - apiProvider: "anthropic" as const, + apiProvider: providerIdentifiers.anthropic, apiModelId: "claude-3-opus-20240229", // Updated setting }, } @@ -1404,8 +1412,8 @@ describe("ProviderSettingsManager", () => { const existingConfig: ProviderProfiles = { currentApiConfigName: "active-profile", apiConfigs: { - "active-profile": { id: "active-id", apiProvider: "anthropic" as const }, - "backup-profile": { id: "backup-id", apiProvider: "openai" as const }, + "active-profile": { id: "active-id", apiProvider: providerIdentifiers.anthropic }, + "backup-profile": { id: "backup-id", apiProvider: providerIdentifiers.openai }, }, cloudProfileIds: ["active-id"], } @@ -1425,7 +1433,7 @@ describe("ProviderSettingsManager", () => { const existingConfig: ProviderProfiles = { currentApiConfigName: "only-profile", apiConfigs: { - "only-profile": { id: "only-id", apiProvider: "anthropic" as const }, + "only-profile": { id: "only-id", apiProvider: providerIdentifiers.anthropic }, }, cloudProfileIds: ["only-id"], } @@ -1449,8 +1457,8 @@ describe("ProviderSettingsManager", () => { const existingConfig: ProviderProfiles = { currentApiConfigName: "local-profile", apiConfigs: { - "local-profile": { id: "local-id", apiProvider: "anthropic" as const }, - "cloud-profile": { id: "cloud-id", apiProvider: "openai" as const }, + "local-profile": { id: "local-id", apiProvider: providerIdentifiers.anthropic }, + "cloud-profile": { id: "cloud-id", apiProvider: providerIdentifiers.openai }, }, cloudProfileIds: ["cloud-id"], } @@ -1460,7 +1468,7 @@ describe("ProviderSettingsManager", () => { const cloudProfiles = { "cloud-profile": { id: "cloud-id", - apiProvider: "openai" as const, + apiProvider: providerIdentifiers.openai, apiModelId: "gpt-4", // Updated cloud profile }, } diff --git a/src/core/config/__tests__/importExport.spec.ts b/src/core/config/__tests__/importExport.spec.ts index 78e6afca75..58104009d8 100644 --- a/src/core/config/__tests__/importExport.spec.ts +++ b/src/core/config/__tests__/importExport.spec.ts @@ -18,6 +18,7 @@ import { CustomModesManager } from "../CustomModesManager" import { safeWriteJson } from "../../../utils/safeWriteJson" import type { Mock } from "vitest" +import { providerIdentifiers, retiredProviderIdentifiers } from "@roo-code/types/provider-identifiers" vi.mock("vscode", () => ({ workspace: { @@ -72,7 +73,10 @@ vi.mock("../../../api", () => ({ buildApiHandler: vi.fn().mockImplementation((config) => { // Return different model info based on the provider and model const getModelInfo = () => { - if (config.apiProvider === "anthropic" && config.apiModelId === "claude-3-5-sonnet-20241022") { + if ( + config.apiProvider === providerIdentifiers.anthropic && + config.apiModelId === "claude-3-5-sonnet-20241022" + ) { return { id: "claude-3-5-sonnet-20241022", info: { @@ -177,7 +181,9 @@ describe("importExport", () => { const mockFileContent = JSON.stringify({ providerProfiles: { currentApiConfigName: "test", - apiConfigs: { test: { apiProvider: "openai" as ProviderName, apiKey: "test-key", id: "test-id" } }, + apiConfigs: { + test: { apiProvider: providerIdentifiers.openai, apiKey: "test-key", id: "test-id" }, + }, }, globalSettings: { mode: "code", autoApprovalEnabled: true }, }) @@ -186,14 +192,14 @@ describe("importExport", () => { const previousProviderProfiles = { currentApiConfigName: "default", - apiConfigs: { default: { apiProvider: "anthropic" as ProviderName, id: "default-id" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" } }, } mockProviderSettingsManager.export.mockResolvedValue(previousProviderProfiles) mockProviderSettingsManager.listConfig.mockResolvedValue([ - { name: "test", id: "test-id", apiProvider: "openai" as ProviderName }, - { name: "default", id: "default-id", apiProvider: "anthropic" as ProviderName }, + { name: "test", id: "test-id", apiProvider: providerIdentifiers.openai }, + { name: "default", id: "default-id", apiProvider: providerIdentifiers.anthropic }, ]) mockContextProxy.export.mockResolvedValue({ mode: "code" }) @@ -211,8 +217,8 @@ describe("importExport", () => { expect(mockProviderSettingsManager.import).toHaveBeenCalledWith({ currentApiConfigName: "test", apiConfigs: { - default: { apiProvider: "anthropic" as ProviderName, id: "default-id" }, - test: { apiProvider: "openai" as ProviderName, apiKey: "test-key", id: "test-id" }, + default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" }, + test: { apiProvider: providerIdentifiers.openai, apiKey: "test-key", id: "test-id" }, }, modeApiConfigs: {}, }) @@ -221,8 +227,8 @@ describe("importExport", () => { expect(mockContextProxy.setValue).toHaveBeenCalledWith("currentApiConfigName", "test") expect(mockContextProxy.setValue).toHaveBeenCalledWith("listApiConfigMeta", [ - { name: "test", id: "test-id", apiProvider: "openai" as ProviderName }, - { name: "default", id: "default-id", apiProvider: "anthropic" as ProviderName }, + { name: "test", id: "test-id", apiProvider: providerIdentifiers.openai }, + { name: "default", id: "default-id", apiProvider: providerIdentifiers.anthropic }, ]) }) @@ -255,7 +261,9 @@ describe("importExport", () => { const mockFileContent = JSON.stringify({ providerProfiles: { currentApiConfigName: "test", - apiConfigs: { test: { apiProvider: "openai" as ProviderName, apiKey: "test-key", id: "test-id" } }, + apiConfigs: { + test: { apiProvider: providerIdentifiers.openai, apiKey: "test-key", id: "test-id" }, + }, }, }) @@ -263,14 +271,14 @@ describe("importExport", () => { const previousProviderProfiles = { currentApiConfigName: "default", - apiConfigs: { default: { apiProvider: "anthropic" as ProviderName, id: "default-id" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" } }, } mockProviderSettingsManager.export.mockResolvedValue(previousProviderProfiles) mockProviderSettingsManager.listConfig.mockResolvedValue([ - { name: "test", id: "test-id", apiProvider: "openai" as ProviderName }, - { name: "default", id: "default-id", apiProvider: "anthropic" as ProviderName }, + { name: "test", id: "test-id", apiProvider: providerIdentifiers.openai }, + { name: "default", id: "default-id", apiProvider: providerIdentifiers.anthropic }, ]) mockContextProxy.export.mockResolvedValue({ mode: "code" }) @@ -287,8 +295,8 @@ describe("importExport", () => { expect(mockProviderSettingsManager.import).toHaveBeenCalledWith({ currentApiConfigName: "test", apiConfigs: { - default: { apiProvider: "anthropic" as ProviderName, id: "default-id" }, - test: { apiProvider: "openai" as ProviderName, apiKey: "test-key", id: "test-id" }, + default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" }, + test: { apiProvider: providerIdentifiers.openai, apiKey: "test-key", id: "test-id" }, }, modeApiConfigs: {}, }) @@ -297,8 +305,8 @@ describe("importExport", () => { expect(mockContextProxy.setValues).toHaveBeenCalledWith({}) expect(mockContextProxy.setValue).toHaveBeenCalledWith("currentApiConfigName", "test") expect(mockContextProxy.setValue).toHaveBeenCalledWith("listApiConfigMeta", [ - { name: "test", id: "test-id", apiProvider: "openai" as ProviderName }, - { name: "default", id: "default-id", apiProvider: "anthropic" as ProviderName }, + { name: "test", id: "test-id", apiProvider: providerIdentifiers.openai }, + { name: "default", id: "default-id", apiProvider: providerIdentifiers.anthropic }, ]) }) @@ -338,7 +346,10 @@ describe("importExport", () => { it("should not clobber existing api configs", async () => { const providerSettingsManager = new ProviderSettingsManager(mockExtensionContext) - await providerSettingsManager.saveConfig("openai", { apiProvider: "openai", id: "openai" }) + await providerSettingsManager.saveConfig("openai", { + apiProvider: providerIdentifiers.openai, + id: "openai", + }) const configs = await providerSettingsManager.listConfig() expect(configs[0].name).toBe("default") @@ -349,7 +360,7 @@ describe("importExport", () => { globalSettings: { mode: "code" }, providerProfiles: { currentApiConfigName: "anthropic", - apiConfigs: { default: { apiProvider: "anthropic" as const, id: "anthropic" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "anthropic" } }, }, }) @@ -412,7 +423,9 @@ describe("importExport", () => { const mockFileContent = JSON.stringify({ providerProfiles: { currentApiConfigName: "test", - apiConfigs: { test: { apiProvider: "openai" as ProviderName, apiKey: "test-key", id: "test-id" } }, + apiConfigs: { + test: { apiProvider: providerIdentifiers.openai, apiKey: "test-key", id: "test-id" }, + }, }, globalSettings: { mode: "code", autoApprovalEnabled: true }, }) @@ -422,13 +435,13 @@ describe("importExport", () => { const previousProviderProfiles = { currentApiConfigName: "default", - apiConfigs: { default: { apiProvider: "anthropic" as ProviderName, id: "default-id" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" } }, } mockProviderSettingsManager.export.mockResolvedValue(previousProviderProfiles) mockProviderSettingsManager.listConfig.mockResolvedValue([ - { name: "test", id: "test-id", apiProvider: "openai" as ProviderName }, - { name: "default", id: "default-id", apiProvider: "anthropic" as ProviderName }, + { name: "test", id: "test-id", apiProvider: providerIdentifiers.openai }, + { name: "default", id: "default-id", apiProvider: providerIdentifiers.anthropic }, ]) mockContextProxy.export.mockResolvedValue({ mode: "code" }) @@ -447,8 +460,8 @@ describe("importExport", () => { expect(mockProviderSettingsManager.import).toHaveBeenCalledWith({ currentApiConfigName: "test", apiConfigs: { - default: { apiProvider: "anthropic" as ProviderName, id: "default-id" }, - test: { apiProvider: "openai" as ProviderName, apiKey: "test-key", id: "test-id" }, + default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" }, + test: { apiProvider: providerIdentifiers.openai, apiKey: "test-key", id: "test-id" }, }, modeApiConfigs: {}, }) @@ -499,7 +512,7 @@ describe("importExport", () => { currentApiConfigName: "openai-provider", apiConfigs: { "openai-provider": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, apiModelId: "gpt-4", id: "openai-id", apiKey: "test-key", @@ -514,13 +527,13 @@ describe("importExport", () => { const previousProviderProfiles = { currentApiConfigName: "default", - apiConfigs: { default: { apiProvider: "anthropic" as ProviderName, id: "default-id" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" } }, } mockProviderSettingsManager.export.mockResolvedValue(previousProviderProfiles) mockProviderSettingsManager.listConfig.mockResolvedValue([ - { name: "openai-provider", id: "openai-id", apiProvider: "openai" as ProviderName }, - { name: "default", id: "default-id", apiProvider: "anthropic" as ProviderName }, + { name: "openai-provider", id: "openai-id", apiProvider: providerIdentifiers.openai }, + { name: "default", id: "default-id", apiProvider: providerIdentifiers.anthropic }, ]) mockContextProxy.export.mockResolvedValue({ mode: "code" }) @@ -538,9 +551,9 @@ describe("importExport", () => { expect(mockProviderSettingsManager.import).toHaveBeenCalledWith({ currentApiConfigName: "openai-provider", apiConfigs: { - default: { apiProvider: "anthropic" as ProviderName, id: "default-id" }, + default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" }, "openai-provider": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, apiModelId: "gpt-4", apiKey: "test-key", id: "openai-id", @@ -563,7 +576,7 @@ describe("importExport", () => { currentApiConfigName: "valid-profile", apiConfigs: { "valid-profile": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, apiKey: "test-key", id: "valid-id", }, @@ -581,11 +594,11 @@ describe("importExport", () => { mockProviderSettingsManager.export.mockResolvedValue({ currentApiConfigName: "default", - apiConfigs: { default: { apiProvider: "anthropic" as ProviderName, id: "default-id" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" } }, }) mockProviderSettingsManager.listConfig.mockResolvedValue([ - { name: "valid-profile", id: "valid-id", apiProvider: "openai" as ProviderName }, - { name: "default", id: "default-id", apiProvider: "anthropic" as ProviderName }, + { name: "valid-profile", id: "valid-id", apiProvider: providerIdentifiers.openai }, + { name: "default", id: "default-id", apiProvider: providerIdentifiers.anthropic }, ]) const result = await importSettings({ @@ -623,7 +636,7 @@ describe("importExport", () => { currentApiConfigName: "valid-profile", apiConfigs: { "valid-profile": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, apiKey: "test-key", id: "valid-id", }, @@ -641,10 +654,10 @@ describe("importExport", () => { mockProviderSettingsManager.export.mockResolvedValue({ currentApiConfigName: "default", - apiConfigs: { default: { apiProvider: "anthropic" as ProviderName, id: "default-id" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" } }, }) mockProviderSettingsManager.listConfig.mockResolvedValue([ - { name: "valid-profile", id: "valid-id", apiProvider: "openai" as ProviderName }, + { name: "valid-profile", id: "valid-id", apiProvider: providerIdentifiers.openai }, ]) const result = await importSettings({ @@ -695,7 +708,7 @@ describe("importExport", () => { mockProviderSettingsManager.export.mockResolvedValue({ currentApiConfigName: "default", - apiConfigs: { default: { apiProvider: "anthropic" as ProviderName, id: "default-id" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" } }, }) const result = await importSettings({ @@ -719,7 +732,7 @@ describe("importExport", () => { currentApiConfigName: "valid-profile", apiConfigs: { "valid-profile": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, apiKey: "test-key", id: "valid-id", }, @@ -738,10 +751,10 @@ describe("importExport", () => { mockProviderSettingsManager.export.mockResolvedValue({ currentApiConfigName: "default", - apiConfigs: { default: { apiProvider: "anthropic" as ProviderName, id: "default-id" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" } }, }) mockProviderSettingsManager.listConfig.mockResolvedValue([ - { name: "valid-profile", id: "valid-id", apiProvider: "openai" as ProviderName }, + { name: "valid-profile", id: "valid-id", apiProvider: providerIdentifiers.openai }, ]) const seenImportedAt: Array = [] @@ -800,7 +813,7 @@ describe("importExport", () => { currentApiConfigName: "valid-profile", apiConfigs: { "valid-profile": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, apiKey: "test-key", id: "valid-id", }, @@ -814,10 +827,10 @@ describe("importExport", () => { mockProviderSettingsManager.export.mockResolvedValue({ currentApiConfigName: "default", - apiConfigs: { default: { apiProvider: "anthropic" as ProviderName, id: "default-id" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" } }, }) mockProviderSettingsManager.listConfig.mockResolvedValue([ - { name: "valid-profile", id: "valid-id", apiProvider: "openai" as ProviderName }, + { name: "valid-profile", id: "valid-id", apiProvider: providerIdentifiers.openai }, ]) const seenImportedAt: Array = [] @@ -851,12 +864,12 @@ describe("importExport", () => { currentApiConfigName: "anthropic-profile", apiConfigs: { "anthropic-profile": { - apiProvider: "anthropic" as ProviderName, + apiProvider: providerIdentifiers.anthropic, anthropicApiKey: "key-1", id: "anthropic-id", }, "openai-profile": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, apiKey: "key-2", id: "openai-id", }, @@ -879,11 +892,11 @@ describe("importExport", () => { mockProviderSettingsManager.export.mockResolvedValue({ currentApiConfigName: "default", - apiConfigs: { default: { apiProvider: "anthropic" as ProviderName, id: "default-id" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" } }, }) mockProviderSettingsManager.listConfig.mockResolvedValue([ - { name: "anthropic-profile", id: "anthropic-id", apiProvider: "anthropic" as ProviderName }, - { name: "openai-profile", id: "openai-id", apiProvider: "openai" as ProviderName }, + { name: "anthropic-profile", id: "anthropic-id", apiProvider: providerIdentifiers.anthropic }, + { name: "openai-profile", id: "openai-id", apiProvider: providerIdentifiers.openai }, ]) const result = await importSettings({ @@ -919,7 +932,7 @@ describe("importExport", () => { currentApiConfigName: "router-profile", apiConfigs: { "router-profile": { - apiProvider: "roo", + apiProvider: retiredProviderIdentifiers.roo, apiModelId: "roo/code-supernova", rooApiKey: "router-key", id: "router-id", @@ -933,7 +946,7 @@ describe("importExport", () => { mockProviderSettingsManager.export.mockResolvedValue({ currentApiConfigName: "default", - apiConfigs: { default: { apiProvider: "anthropic" as ProviderName, id: "default-id" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" } }, }) const result = await importSettings({ @@ -964,7 +977,7 @@ describe("importExport", () => { id: "invalid-current-id", }, "valid-fallback-profile": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, apiKey: "test-key", id: "fallback-id", }, @@ -977,10 +990,10 @@ describe("importExport", () => { mockProviderSettingsManager.export.mockResolvedValue({ currentApiConfigName: "default", - apiConfigs: { default: { apiProvider: "anthropic" as ProviderName, id: "default-id" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" } }, }) mockProviderSettingsManager.listConfig.mockResolvedValue([ - { name: "valid-fallback-profile", id: "fallback-id", apiProvider: "openai" as ProviderName }, + { name: "valid-fallback-profile", id: "fallback-id", apiProvider: providerIdentifiers.openai }, ]) const result = await importSettings({ @@ -1040,7 +1053,7 @@ describe("importExport", () => { mockProviderSettingsManager.export.mockResolvedValue({ currentApiConfigName: "existing-profile", apiConfigs: { - "existing-profile": { apiProvider: "anthropic" as ProviderName, id: "existing-id" }, + "existing-profile": { apiProvider: providerIdentifiers.anthropic, id: "existing-id" }, }, }) @@ -1062,7 +1075,7 @@ describe("importExport", () => { currentApiConfigName: "valid-profile", apiConfigs: { "valid-profile": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, apiKey: "test-key", id: "valid-id", }, @@ -1086,10 +1099,10 @@ describe("importExport", () => { mockProviderSettingsManager.export.mockResolvedValue({ currentApiConfigName: "default", - apiConfigs: { default: { apiProvider: "anthropic" as ProviderName, id: "default-id" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" } }, }) mockProviderSettingsManager.listConfig.mockResolvedValue([ - { name: "valid-profile", id: "valid-id", apiProvider: "openai" as ProviderName }, + { name: "valid-profile", id: "valid-id", apiProvider: providerIdentifiers.openai }, ]) const mockProvider = { @@ -1135,14 +1148,14 @@ describe("importExport", () => { currentApiConfigName: "valid-profile", apiConfigs: { "valid-profile": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, apiKey: "test-key", id: "valid-id", }, }, }, globalSettings: { - imageGenerationProvider: "roo", + imageGenerationProvider: retiredProviderIdentifiers.roo, openRouterImageGenerationSelectedModel: "openrouter/model-1", customInstructions: "Keep this setting", }, @@ -1151,10 +1164,10 @@ describe("importExport", () => { ;(fs.readFile as Mock).mockResolvedValue(mockFileContent) mockProviderSettingsManager.export.mockResolvedValue({ currentApiConfigName: "default", - apiConfigs: { default: { apiProvider: "anthropic" as ProviderName, id: "default-id" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" } }, }) mockProviderSettingsManager.listConfig.mockResolvedValue([ - { name: "valid-profile", id: "valid-id", apiProvider: "openai" as ProviderName }, + { name: "valid-profile", id: "valid-id", apiProvider: providerIdentifiers.openai }, ]) const result = await importSettings({ @@ -1185,7 +1198,7 @@ describe("importExport", () => { currentApiConfigName: "valid-profile", apiConfigs: { "valid-profile": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, apiKey: "test-key", id: "valid-id", }, @@ -1202,10 +1215,10 @@ describe("importExport", () => { ;(fs.readFile as Mock).mockResolvedValue(mockFileContent) mockProviderSettingsManager.export.mockResolvedValue({ currentApiConfigName: "default", - apiConfigs: { default: { apiProvider: "anthropic" as ProviderName, id: "default-id" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" } }, }) mockProviderSettingsManager.listConfig.mockResolvedValue([ - { name: "valid-profile", id: "valid-id", apiProvider: "openai" as ProviderName }, + { name: "valid-profile", id: "valid-id", apiProvider: providerIdentifiers.openai }, ]) const result = await importSettings({ @@ -1237,7 +1250,7 @@ describe("importExport", () => { currentApiConfigName: "valid-profile", apiConfigs: { "valid-profile": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, apiKey: "test-key", id: "valid-id", }, @@ -1259,10 +1272,10 @@ describe("importExport", () => { ;(fs.readFile as Mock).mockResolvedValue(mockFileContent) mockProviderSettingsManager.export.mockResolvedValue({ currentApiConfigName: "default", - apiConfigs: { default: { apiProvider: "anthropic" as ProviderName, id: "default-id" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" } }, }) mockProviderSettingsManager.listConfig.mockResolvedValue([ - { name: "valid-profile", id: "valid-id", apiProvider: "openai" as ProviderName }, + { name: "valid-profile", id: "valid-id", apiProvider: providerIdentifiers.openai }, ]) const result = await importSettings({ @@ -1288,7 +1301,7 @@ describe("importExport", () => { currentApiConfigName: "valid-profile", apiConfigs: { "valid-profile": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, apiKey: "test-key", id: "valid-id", }, @@ -1303,10 +1316,10 @@ describe("importExport", () => { ;(fs.access as Mock).mockResolvedValue(undefined) mockProviderSettingsManager.export.mockResolvedValue({ currentApiConfigName: "default", - apiConfigs: { default: { apiProvider: "anthropic" as ProviderName, id: "default-id" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" } }, }) mockProviderSettingsManager.listConfig.mockResolvedValue([ - { name: "valid-profile", id: "valid-id", apiProvider: "openai" as ProviderName }, + { name: "valid-profile", id: "valid-id", apiProvider: providerIdentifiers.openai }, ]) const mockProvider = { @@ -1368,7 +1381,7 @@ describe("importExport", () => { const mockProviderProfiles = { currentApiConfigName: "test", - apiConfigs: { test: { apiProvider: "openai" as ProviderName, id: "test-id" } }, + apiConfigs: { test: { apiProvider: providerIdentifiers.openai, id: "test-id" } }, migrations: { rateLimitSecondsMigrated: false }, } @@ -1403,7 +1416,7 @@ describe("importExport", () => { const mockProviderProfiles = { currentApiConfigName: "test", - apiConfigs: { test: { apiProvider: "openai" as ProviderName, id: "test-id" } }, + apiConfigs: { test: { apiProvider: providerIdentifiers.openai, id: "test-id" } }, migrations: { rateLimitSecondsMigrated: false }, } @@ -1435,7 +1448,7 @@ describe("importExport", () => { mockProviderSettingsManager.export.mockResolvedValue({ currentApiConfigName: "test", - apiConfigs: { test: { apiProvider: "openai" as ProviderName, id: "test-id" } }, + apiConfigs: { test: { apiProvider: providerIdentifiers.openai, id: "test-id" } }, migrations: { rateLimitSecondsMigrated: false }, }) @@ -1465,7 +1478,7 @@ describe("importExport", () => { mockProviderSettingsManager.export.mockResolvedValue({ currentApiConfigName: "test", - apiConfigs: { test: { apiProvider: "openai" as ProviderName, id: "test-id" } }, + apiConfigs: { test: { apiProvider: providerIdentifiers.openai, id: "test-id" } }, migrations: { rateLimitSecondsMigrated: false }, }) @@ -1510,12 +1523,12 @@ describe("importExport", () => { currentApiConfigName: "openai-compatible-provider", apiConfigs: { "openai-compatible-provider": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, id: "openai-compatible-id", // Remove OpenAI Compatible settings from provider profile }, "ollama-provider": { - apiProvider: "ollama" as ProviderName, + apiProvider: providerIdentifiers.ollama, id: "ollama-id", codebaseIndexOllamaBaseUrl: "http://localhost:11434", }, @@ -1560,7 +1573,7 @@ describe("importExport", () => { currentApiConfigName: "test-provider", apiConfigs: { "test-provider": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, id: "test-id", // Remove OpenAI Compatible settings from provider profile }, @@ -1607,17 +1620,17 @@ describe("importExport", () => { currentApiConfigName: "openai-compatible-provider", apiConfigs: { "openai-compatible-provider": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, id: "openai-compatible-id", // Remove OpenAI Compatible settings from provider profile }, "ollama-provider": { - apiProvider: "ollama" as ProviderName, + apiProvider: providerIdentifiers.ollama, id: "ollama-id", codebaseIndexOllamaBaseUrl: "http://localhost:11434", }, "anthropic-provider": { - apiProvider: "anthropic" as ProviderName, + apiProvider: providerIdentifiers.anthropic, id: "anthropic-id", }, }, @@ -1667,7 +1680,7 @@ describe("importExport", () => { currentApiConfigName: "incomplete-provider", apiConfigs: { "incomplete-provider": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, id: "incomplete-id", // Missing codebaseIndexOpenAiCompatibleBaseUrl and dimension }, @@ -1713,7 +1726,7 @@ describe("importExport", () => { currentApiConfigName: "openai-provider", apiConfigs: { "openai-provider": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, id: "openai-id", // Regular OpenAI provider without OpenAI Compatible settings }, @@ -1725,7 +1738,7 @@ describe("importExport", () => { mode: "code", codebaseIndexConfig: { codebaseIndexEnabled: true, - codebaseIndexEmbedderProvider: "openai" as const, // Not openai-compatible + codebaseIndexEmbedderProvider: providerIdentifiers.openai, // Not openai-compatible codebaseIndexEmbedderModelId: "text-embedding-ada-002", codebaseIndexEmbedderBaseUrl: "https://api.openai.com/v1", }, @@ -1756,7 +1769,7 @@ describe("importExport", () => { currentApiConfigName: "nonexistent-provider", apiConfigs: { "other-provider": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, id: "other-id", }, }, @@ -1802,7 +1815,7 @@ describe("importExport", () => { currentApiConfigName: "openai-compatible-provider", apiConfigs: { "openai-compatible-provider": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, id: "openai-compatible-id", // Provider-specific settings remain in provider profile codebaseIndexOpenAiCompatibleBaseUrl: "https://old-url.example.com/v1", @@ -1829,7 +1842,7 @@ describe("importExport", () => { const previousProviderProfiles = { currentApiConfigName: "default", - apiConfigs: { default: { apiProvider: "anthropic" as ProviderName, id: "default-id" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" } }, } mockProviderSettingsManager.export.mockResolvedValue(previousProviderProfiles) @@ -1837,9 +1850,9 @@ describe("importExport", () => { { name: "openai-compatible-provider", id: "openai-compatible-id", - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, }, - { name: "default", id: "default-id", apiProvider: "anthropic" as ProviderName }, + { name: "default", id: "default-id", apiProvider: providerIdentifiers.anthropic }, ]) const result = await importSettings({ @@ -1877,7 +1890,7 @@ describe("importExport", () => { currentApiConfigName: "openai-compatible-provider", apiConfigs: { "openai-compatible-provider": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, id: "openai-compatible-id", }, }, @@ -1898,7 +1911,7 @@ describe("importExport", () => { const previousProviderProfiles = { currentApiConfigName: "default", - apiConfigs: { default: { apiProvider: "anthropic" as ProviderName, id: "default-id" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" } }, } mockProviderSettingsManager.export.mockResolvedValue(previousProviderProfiles) @@ -1906,7 +1919,7 @@ describe("importExport", () => { { name: "openai-compatible-provider", id: "openai-compatible-id", - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, }, ]) @@ -1928,7 +1941,7 @@ describe("importExport", () => { currentApiConfigName: "anthropic-provider", apiConfigs: { "anthropic-provider": { - apiProvider: "anthropic" as ProviderName, + apiProvider: providerIdentifiers.anthropic, id: "anthropic-id", }, }, @@ -1938,7 +1951,7 @@ describe("importExport", () => { mode: "code", codebaseIndexConfig: { codebaseIndexEnabled: true, - codebaseIndexEmbedderProvider: "openai" as const, // Not openai-compatible + codebaseIndexEmbedderProvider: providerIdentifiers.openai, // Not openai-compatible codebaseIndexEmbedderModelId: "text-embedding-ada-002", codebaseIndexEmbedderBaseUrl: "https://api.openai.com/v1", codebaseIndexEmbedderModelDimension: 1536, @@ -1950,12 +1963,12 @@ describe("importExport", () => { const previousProviderProfiles = { currentApiConfigName: "default", - apiConfigs: { default: { apiProvider: "anthropic" as ProviderName, id: "default-id" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" } }, } mockProviderSettingsManager.export.mockResolvedValue(previousProviderProfiles) mockProviderSettingsManager.listConfig.mockResolvedValue([ - { name: "anthropic-provider", id: "anthropic-id", apiProvider: "anthropic" as ProviderName }, + { name: "anthropic-provider", id: "anthropic-id", apiProvider: providerIdentifiers.anthropic }, ]) const result = await importSettings({ @@ -1986,7 +1999,7 @@ describe("importExport", () => { currentApiConfigName: "test-openai-compatible", apiConfigs: { "test-openai-compatible": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, id: "test-id", // Remove OpenAI Compatible settings from provider profile }, @@ -2040,10 +2053,10 @@ describe("importExport", () => { clearAllMocks() mockProviderSettingsManager.export.mockResolvedValue({ currentApiConfigName: "default", - apiConfigs: { default: { apiProvider: "anthropic" as ProviderName, id: "default-id" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" } }, }) mockProviderSettingsManager.listConfig.mockResolvedValue([ - { name: "test-openai-compatible", id: "test-id", apiProvider: "openai" as ProviderName }, + { name: "test-openai-compatible", id: "test-id", apiProvider: providerIdentifiers.openai }, ]) // Step 7: Import the settings back @@ -2079,7 +2092,7 @@ describe("importExport", () => { currentApiConfigName: "test-openai-compatible", apiConfigs: { "test-openai-compatible": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, id: "test-id", // Remove OpenAI Compatible settings from provider profile }, @@ -2128,10 +2141,10 @@ describe("importExport", () => { clearAllMocks() mockProviderSettingsManager.export.mockResolvedValue({ currentApiConfigName: "default", - apiConfigs: { default: { apiProvider: "anthropic" as ProviderName, id: "default-id" } }, + apiConfigs: { default: { apiProvider: providerIdentifiers.anthropic, id: "default-id" } }, }) mockProviderSettingsManager.listConfig.mockResolvedValue([ - { name: "test-openai-compatible", id: "test-id", apiProvider: "openai" as ProviderName }, + { name: "test-openai-compatible", id: "test-id", apiProvider: providerIdentifiers.openai }, ]) // Import the settings back @@ -2154,7 +2167,7 @@ describe("importExport", () => { currentApiConfigName: "test-openai-compatible", apiConfigs: { "test-openai-compatible": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, id: "test-id", // Remove OpenAI Compatible settings from provider profile }, @@ -2213,13 +2226,13 @@ describe("importExport", () => { currentApiConfigName: "provider-a", apiConfigs: { "provider-a": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, id: "provider-a-id", codebaseIndexOpenAiCompatibleBaseUrl: "https://api-a.example.com/v1", codebaseIndexOpenAiCompatibleModelDimension: 1536, }, "provider-b": { - apiProvider: "anthropic" as ProviderName, + apiProvider: providerIdentifiers.anthropic, id: "provider-b-id", }, }, @@ -2242,7 +2255,7 @@ describe("importExport", () => { currentApiConfigName: "provider-b", // Different from exported settings! apiConfigs: { "provider-b": { - apiProvider: "anthropic" as ProviderName, + apiProvider: providerIdentifiers.anthropic, id: "provider-b-id", }, }, @@ -2254,8 +2267,8 @@ describe("importExport", () => { mockProviderSettingsManager.export.mockResolvedValue(currentProviderProfiles) mockProviderSettingsManager.listConfig.mockResolvedValue([ - { name: "provider-a", id: "provider-a-id", apiProvider: "openai" as ProviderName }, - { name: "provider-b", id: "provider-b-id", apiProvider: "anthropic" as ProviderName }, + { name: "provider-a", id: "provider-a-id", apiProvider: providerIdentifiers.openai }, + { name: "provider-b", id: "provider-b-id", apiProvider: providerIdentifiers.anthropic }, ]) // Step 4: Import the settings @@ -2292,12 +2305,12 @@ describe("importExport", () => { currentApiConfigName: "openai-compatible-provider", apiConfigs: { "openai-compatible-provider": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, id: "openai-compatible-id", // NO OpenAI Compatible settings here in the fixed version }, "anthropic-provider": { - apiProvider: "anthropic" as ProviderName, + apiProvider: providerIdentifiers.anthropic, id: "anthropic-id", }, }, @@ -2322,7 +2335,7 @@ describe("importExport", () => { currentApiConfigName: "anthropic-provider", apiConfigs: { "anthropic-provider": { - apiProvider: "anthropic" as ProviderName, + apiProvider: providerIdentifiers.anthropic, id: "anthropic-id", }, }, @@ -2336,9 +2349,9 @@ describe("importExport", () => { { name: "openai-compatible-provider", id: "openai-compatible-id", - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, }, - { name: "anthropic-provider", id: "anthropic-id", apiProvider: "anthropic" as ProviderName }, + { name: "anthropic-provider", id: "anthropic-id", apiProvider: providerIdentifiers.anthropic }, ]) const importResult = await importSettings({ @@ -2377,11 +2390,11 @@ describe("importExport", () => { currentApiConfigName: "anthropic-provider", apiConfigs: { "anthropic-provider": { - apiProvider: "anthropic" as ProviderName, + apiProvider: providerIdentifiers.anthropic, id: "anthropic-id", }, "openai-compatible-provider": { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, id: "openai-compatible-id", // NO OpenAI Compatible settings in provider profiles }, @@ -2407,7 +2420,7 @@ describe("importExport", () => { currentApiConfigName: "default", apiConfigs: { default: { - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, id: "default-id", }, }, @@ -2418,13 +2431,13 @@ describe("importExport", () => { mockProviderSettingsManager.export.mockResolvedValue(currentProviderProfiles) mockProviderSettingsManager.listConfig.mockResolvedValue([ - { name: "anthropic-provider", id: "anthropic-id", apiProvider: "anthropic" as ProviderName }, + { name: "anthropic-provider", id: "anthropic-id", apiProvider: providerIdentifiers.anthropic }, { name: "openai-compatible-provider", id: "openai-compatible-id", - apiProvider: "openai" as ProviderName, + apiProvider: providerIdentifiers.openai, }, - { name: "default", id: "default-id", apiProvider: "openai" as ProviderName }, + { name: "default", id: "default-id", apiProvider: providerIdentifiers.openai }, ]) const importResult = await importSettings({ @@ -2469,7 +2482,7 @@ describe("importExport", () => { currentApiConfigName: "openrouter-provider", // Current provider is OpenRouter apiConfigs: { "openrouter-provider": { - apiProvider: "openrouter" as ProviderName, + apiProvider: providerIdentifiers.openrouter, id: "openrouter-id", // OpenRouter doesn't have OpenAI Compatible fields }, @@ -2544,7 +2557,7 @@ describe("importExport", () => { // Save a deepseek provider config with token fields await realProviderSettingsManager.saveConfig(providerName, { - apiProvider: "deepseek" as ProviderName, + apiProvider: providerIdentifiers.deepseek, apiModelId: modelId, id: providerId, deepSeekApiKey: "test-key", diff --git a/src/core/task/__tests__/Task.dispose.test.ts b/src/core/task/__tests__/Task.dispose.test.ts index bc14edb366..9f00e9d852 100644 --- a/src/core/task/__tests__/Task.dispose.test.ts +++ b/src/core/task/__tests__/Task.dispose.test.ts @@ -2,6 +2,7 @@ import { type ProviderSettings, RooCodeEventName } from "@roo-code/types" import { Task } from "../Task" import { ClineProvider } from "../../webview/ClineProvider" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" // Mock dependencies vi.mock("../../webview/ClineProvider") @@ -67,7 +68,7 @@ describe("Task dispose method", () => { // Mock API configuration mockApiConfiguration = { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiKey: "test-key", } as ProviderSettings @@ -226,7 +227,7 @@ describe("Task.run() idempotency", () => { beforeEach(() => { vi.clearAllMocks() mockProvider = buildMockProvider() - mockApiConfiguration = { apiProvider: "anthropic", apiKey: "test-key" } as ProviderSettings + mockApiConfiguration = { apiProvider: providerIdentifiers.anthropic, apiKey: "test-key" } as ProviderSettings }) test("run() does not invoke startTask when task was already started by constructor", async () => { diff --git a/src/core/task/__tests__/Task.persistence.spec.ts b/src/core/task/__tests__/Task.persistence.spec.ts index 60510a71d1..19bd0c7f34 100644 --- a/src/core/task/__tests__/Task.persistence.spec.ts +++ b/src/core/task/__tests__/Task.persistence.spec.ts @@ -10,6 +10,7 @@ import { TelemetryService } from "@roo-code/telemetry" import { Task } from "../Task" import { ClineProvider } from "../../webview/ClineProvider" import { ContextProxy } from "../../config/ContextProxy" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" type TaskPersistenceAccess = { resumeTaskFromHistory: () => Promise @@ -272,7 +273,7 @@ describe("Task persistence", () => { ) as ClineProvider & Record mockApiConfig = { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiModelId: "claude-3-5-sonnet-20241022", apiKey: "test-api-key", } diff --git a/src/core/task/__tests__/Task.resume-eviction-race.spec.ts b/src/core/task/__tests__/Task.resume-eviction-race.spec.ts index 31e532e0e9..8766f38d5b 100644 --- a/src/core/task/__tests__/Task.resume-eviction-race.spec.ts +++ b/src/core/task/__tests__/Task.resume-eviction-race.spec.ts @@ -19,6 +19,7 @@ import { TelemetryService } from "@roo-code/telemetry" import { Task } from "../Task" import { ClineProvider } from "../../webview/ClineProvider" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" // ─── Hoisted mocks ─────────────────────────────────────────────────────────── @@ -161,7 +162,7 @@ describe("Task resume/eviction race (Work #1 (no message) regression)", () => { } mockApiConfig = { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiModelId: "claude-3-5-sonnet-20241022", apiKey: "test-api-key", } diff --git a/src/core/task/__tests__/Task.spec.ts b/src/core/task/__tests__/Task.spec.ts index 163da0c478..37e228f887 100644 --- a/src/core/task/__tests__/Task.spec.ts +++ b/src/core/task/__tests__/Task.spec.ts @@ -3895,7 +3895,7 @@ describe("Telemetry installments (idle/shutdown flush)", () => { mockProvider.postStateToWebview = vi.fn().mockResolvedValue(undefined) mockApiConfig = { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiModelId: "claude-3-5-sonnet-20241022", apiKey: "test-api-key", } diff --git a/src/core/task/__tests__/Task.sticky-profile-race.spec.ts b/src/core/task/__tests__/Task.sticky-profile-race.spec.ts index ea0cd2cffc..d0b4e4cdde 100644 --- a/src/core/task/__tests__/Task.sticky-profile-race.spec.ts +++ b/src/core/task/__tests__/Task.sticky-profile-race.spec.ts @@ -5,6 +5,7 @@ import * as vscode from "vscode" import type { ProviderSettings } from "@roo-code/types" import { Task } from "../Task" import { ClineProvider } from "../../webview/ClineProvider" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" vi.mock("@roo-code/telemetry", () => ({ TelemetryService: { @@ -104,7 +105,7 @@ vi.mock("delay", () => ({ describe("Task - sticky provider profile init race", () => { it("does not overwrite task apiConfigName if set during async initialization", async () => { const apiConfig: ProviderSettings = { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiModelId: "claude-3-5-sonnet-20241022", apiKey: "test-api-key", } as any diff --git a/src/core/task/__tests__/Task.throttle.test.ts b/src/core/task/__tests__/Task.throttle.test.ts index 0eac687e64..eaacb32faf 100644 --- a/src/core/task/__tests__/Task.throttle.test.ts +++ b/src/core/task/__tests__/Task.throttle.test.ts @@ -3,6 +3,7 @@ import { RooCodeEventName, ProviderSettings, TokenUsage, ToolUsage } from "@roo- import { Task } from "../Task" import { ClineProvider } from "../../webview/ClineProvider" import { hasToolUsageChanged, hasTokenUsageChanged } from "../../../shared/getApiMetrics" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" // Mock dependencies vi.mock("../../webview/ClineProvider") @@ -86,7 +87,7 @@ describe("Task token usage throttling", () => { // Mock API configuration mockApiConfiguration = { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiKey: "test-key", } as ProviderSettings diff --git a/src/core/task/__tests__/apiConversationHistory.spec.ts b/src/core/task/__tests__/apiConversationHistory.spec.ts index 76a3ac69fd..7313e4fa1c 100644 --- a/src/core/task/__tests__/apiConversationHistory.spec.ts +++ b/src/core/task/__tests__/apiConversationHistory.spec.ts @@ -1,6 +1,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest" import { prepareApiConversationMessage } from "../apiConversationHistory.js" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" describe("prepareApiConversationMessage", () => { beforeEach(() => { @@ -20,7 +21,7 @@ describe("prepareApiConversationMessage", () => { getResponseId: () => "response-1", getThoughtSignature: () => "signature-1", } as any, - apiConfiguration: { apiProvider: "anthropic", apiModelId: "claude-3-5-sonnet" } as any, + apiConfiguration: { apiProvider: providerIdentifiers.anthropic, apiModelId: "claude-3-5-sonnet" } as any, apiConversationHistory: [], }) as any @@ -40,7 +41,7 @@ describe("prepareApiConversationMessage", () => { message: { role: "assistant", content: "answer" }, reasoning: "visible reasoning", api: {} as any, - apiConfiguration: { apiProvider: "openrouter", openRouterModelId: "openai/gpt-4" } as any, + apiConfiguration: { apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4" } as any, apiConversationHistory: [], }) as any @@ -55,7 +56,7 @@ describe("prepareApiConversationMessage", () => { message: { role: "assistant", content: "answer" }, reasoning: "private reasoning", api: {} as any, - apiConfiguration: { apiProvider: "anthropic", apiModelId: "claude-3-5-sonnet" } as any, + apiConfiguration: { apiProvider: providerIdentifiers.anthropic, apiModelId: "claude-3-5-sonnet" } as any, apiConversationHistory: [], }) as any @@ -72,7 +73,7 @@ describe("prepareApiConversationMessage", () => { api: { getEncryptedContent: () => ({ encrypted_content: "encrypted", id: "reasoning-1" }), } as any, - apiConfiguration: { apiProvider: "openrouter", openRouterModelId: "openai/gpt-4" } as any, + apiConfiguration: { apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4" } as any, apiConversationHistory: [], }) as any @@ -89,7 +90,7 @@ describe("prepareApiConversationMessage", () => { getThoughtSignature: () => "signature-1", getReasoningDetails: () => [{ type: "reasoning", text: "detail" }], } as any, - apiConfiguration: { apiProvider: "openrouter", openRouterModelId: "openai/gpt-4" } as any, + apiConfiguration: { apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4" } as any, apiConversationHistory: [], }) as any @@ -107,7 +108,7 @@ describe("prepareApiConversationMessage", () => { content: [{ type: "tool_result", tool_use_id: "wrong-id", content: "done" }], }, api: {} as any, - apiConfiguration: { apiProvider: "openrouter", openRouterModelId: "openai/gpt-4" } as any, + apiConfiguration: { apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4" } as any, apiConversationHistory: [ { role: "assistant", @@ -130,7 +131,7 @@ describe("prepareApiConversationMessage", () => { ], }, api: {} as any, - apiConfiguration: { apiProvider: "openrouter", openRouterModelId: "openai/gpt-4" } as any, + apiConfiguration: { apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4" } as any, apiConversationHistory: [{ role: "user", content: "previous user message" } as any], }) as any diff --git a/src/core/task/__tests__/flushPendingToolResultsToHistory.spec.ts b/src/core/task/__tests__/flushPendingToolResultsToHistory.spec.ts index 285f22189e..80c5163c8e 100644 --- a/src/core/task/__tests__/flushPendingToolResultsToHistory.spec.ts +++ b/src/core/task/__tests__/flushPendingToolResultsToHistory.spec.ts @@ -10,6 +10,7 @@ import { TelemetryService } from "@roo-code/telemetry" import { Task } from "../Task" import { ClineProvider } from "../../webview/ClineProvider" import { ContextProxy } from "../../config/ContextProxy" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" // Mock delay before any imports that might use it vi.mock("delay", () => ({ @@ -213,7 +214,7 @@ describe("flushPendingToolResultsToHistory", () => { ) as any mockApiConfig = { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiModelId: "claude-3-5-sonnet-20241022", apiKey: "test-api-key", } diff --git a/src/core/task/__tests__/grace-retry-errors.spec.ts b/src/core/task/__tests__/grace-retry-errors.spec.ts index 45c86d92ec..9584559c8f 100644 --- a/src/core/task/__tests__/grace-retry-errors.spec.ts +++ b/src/core/task/__tests__/grace-retry-errors.spec.ts @@ -10,6 +10,7 @@ import { TelemetryService } from "@roo-code/telemetry" import { Task } from "../Task" import { ClineProvider } from "../../webview/ClineProvider" import { ContextProxy } from "../../config/ContextProxy" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" // Mock @roo-code/core vi.mock("@roo-code/core", () => ({ @@ -201,7 +202,7 @@ describe("Grace Retry Error Handling", () => { ) as any mockApiConfig = { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiModelId: "claude-3-5-sonnet-20241022", apiKey: "test-api-key", } diff --git a/src/core/task/__tests__/grounding-sources.test.ts b/src/core/task/__tests__/grounding-sources.test.ts index dcb1408baf..d392c90437 100644 --- a/src/core/task/__tests__/grounding-sources.test.ts +++ b/src/core/task/__tests__/grounding-sources.test.ts @@ -155,6 +155,7 @@ vi.mock("../../../utils/fs", () => ({ // Import Task AFTER all vi.mock() calls - Vitest hoists mocks so this works import { Task } from "../Task" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" describe("Task grounding sources handling", () => { let mockProvider: Partial @@ -179,7 +180,7 @@ describe("Task grounding sources handling", () => { } mockApiConfiguration = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, geminiApiKey: "test-key", } as ProviderSettings }) diff --git a/src/core/task/__tests__/reasoning-preservation.test.ts b/src/core/task/__tests__/reasoning-preservation.test.ts index cd4c3958a3..f34cea1bdc 100644 --- a/src/core/task/__tests__/reasoning-preservation.test.ts +++ b/src/core/task/__tests__/reasoning-preservation.test.ts @@ -155,6 +155,7 @@ vi.mock("../../../utils/fs", () => ({ // Import Task AFTER all vi.mock() calls - Vitest hoists mocks so this works import { Task } from "../Task" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" describe("Task reasoning preservation", () => { let mockProvider: Partial @@ -179,7 +180,7 @@ describe("Task reasoning preservation", () => { } mockApiConfiguration = { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiKey: "test-key", } as ProviderSettings }) diff --git a/src/core/tools/GenerateImageTool.ts b/src/core/tools/GenerateImageTool.ts index b036a71977..99a0a8f5b1 100644 --- a/src/core/tools/GenerateImageTool.ts +++ b/src/core/tools/GenerateImageTool.ts @@ -6,6 +6,7 @@ import { IMAGE_GENERATION_MODEL_IDS, IMAGE_GENERATION_MODELS, getImageGenerationProvider, + providerIdentifiers, } from "@roo-code/types" import { Task } from "../task/Task" import { formatResponse } from "../prompts/responses" @@ -155,7 +156,7 @@ export class GenerateImageTool extends BaseTool<"generate_image"> { // Validate API key for OpenRouter const openRouterApiKey = state?.openRouterImageApiKey - if (imageProvider === "openrouter" && !openRouterApiKey) { + if (imageProvider === providerIdentifiers.openrouter && !openRouterApiKey) { const errorMessage = t("tools:generateImage.openRouterApiKeyRequired") await task.say("error", errorMessage) pushToolResult(formatResponse.toolError(errorMessage)) diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 6f70a19946..021a2fba91 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -2013,7 +2013,7 @@ export class ClineProvider const newConfiguration: ProviderSettings = { ...apiConfiguration, - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterApiKey: apiKey, openRouterModelId: apiConfiguration?.openRouterModelId || openRouterDefaultModelId, } @@ -2059,7 +2059,7 @@ export class ClineProvider if (zooProfiles.length === 0) { // No existing zoo-gateway profile — create the canonical default. const newConfiguration: ProviderSettings = { - apiProvider: "zoo-gateway", + apiProvider: providerIdentifiers.zooGateway, zooSessionToken: token, zooGatewayModelId: apiConfiguration.zooGatewayModelId, zooGatewayBaseUrl: derivedGatewayBaseUrl, @@ -2107,7 +2107,7 @@ export class ClineProvider const newConfiguration: ProviderSettings = { ...apiConfiguration, - apiProvider: "requesty", + apiProvider: providerIdentifiers.requesty, requestyApiKey: code, requestyModelId: apiConfiguration?.requestyModelId || requestyDefaultModelId, } diff --git a/src/core/webview/__tests__/ClineProvider.apiHandlerRebuild.spec.ts b/src/core/webview/__tests__/ClineProvider.apiHandlerRebuild.spec.ts index ec64a1adb0..99d254cb9a 100644 --- a/src/core/webview/__tests__/ClineProvider.apiHandlerRebuild.spec.ts +++ b/src/core/webview/__tests__/ClineProvider.apiHandlerRebuild.spec.ts @@ -9,6 +9,7 @@ import { ContextProxy } from "../../config/ContextProxy" import type { Mode } from "../../../shared/modes" import { Task, TaskOptions } from "../../task/Task" import { ClineProvider } from "../ClineProvider" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" // Mock setup vi.mock("fs/promises", () => ({ @@ -118,7 +119,10 @@ vi.mock("../../task/Task", () => ({ } // Define apiConfiguration as a property so tests can read it Object.defineProperty(mockTask, "apiConfiguration", { - value: options?.apiConfiguration || { apiProvider: "openrouter", openRouterModelId: "openai/gpt-4" }, + value: options?.apiConfiguration || { + apiProvider: providerIdentifiers.openrouter, + openRouterModelId: "openai/gpt-4", + }, writable: true, configurable: true, }) @@ -231,23 +235,26 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { // Mock providerSettingsManager ;(provider as any).providerSettingsManager = { saveConfig: vi.fn().mockResolvedValue("test-id"), - listConfig: vi - .fn() - .mockResolvedValue([ - { name: "test-config", id: "test-id", apiProvider: "openrouter", modelId: "openai/gpt-4" }, - ]), + listConfig: vi.fn().mockResolvedValue([ + { + name: "test-config", + id: "test-id", + apiProvider: providerIdentifiers.openrouter, + modelId: "openai/gpt-4", + }, + ]), setModeConfig: vi.fn(), getModeConfigId: vi.fn().mockResolvedValue(undefined), activateProfile: vi.fn().mockResolvedValue({ name: "test-config", id: "test-id", - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4", }), getProfile: vi.fn().mockResolvedValue({ name: "test-config", id: "test-id", - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4", }), } @@ -267,7 +274,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { defaultTaskOptions = { provider, apiConfiguration: { - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4", }, } @@ -281,7 +288,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { const mockTask = new Task({ ...defaultTaskOptions, apiConfiguration: { - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4", }, }) @@ -298,7 +305,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { await provider.upsertProviderProfile( "test-config", { - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4", // Other settings that might change rateLimitSeconds: 5, @@ -310,7 +317,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { // Verify updateApiConfiguration was called because we force rebuild on explicit save/switch expect(mockTask.updateApiConfiguration).toHaveBeenCalledWith( expect.objectContaining({ - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4", rateLimitSeconds: 5, modelTemperature: 0.7, @@ -326,7 +333,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { const mockTask = new Task({ ...defaultTaskOptions, apiConfiguration: { - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4", }, }) @@ -343,7 +350,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { await provider.upsertProviderProfile( "test-config", { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiModelId: "claude-3-5-sonnet-20241022", }, true, @@ -352,7 +359,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { // Verify updateApiConfiguration was called since provider changed expect(mockTask.updateApiConfiguration).toHaveBeenCalledWith( expect.objectContaining({ - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiModelId: "claude-3-5-sonnet-20241022", }), ) @@ -362,7 +369,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { const mockTask = new Task({ ...defaultTaskOptions, apiConfiguration: { - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4", }, }) @@ -379,7 +386,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { await provider.upsertProviderProfile( "test-config", { - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "anthropic/claude-3-5-sonnet-20241022", }, true, @@ -388,7 +395,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { // Verify updateApiConfiguration was called since model changed expect(mockTask.updateApiConfiguration).toHaveBeenCalledWith( expect.objectContaining({ - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "anthropic/claude-3-5-sonnet-20241022", }), ) @@ -401,7 +408,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { await provider.upsertProviderProfile( "test-config", { - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4", }, true, @@ -428,7 +435,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { return { name: "first-profile", id: "first-id", - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4", } }) @@ -437,7 +444,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { return { name: "second-profile", id: "second-id", - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4.1-mini", } }) @@ -465,7 +472,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { .mockResolvedValueOnce({ name: "second-profile", id: "second-id", - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4.1-mini", }) @@ -489,14 +496,14 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { return { name: "first-profile", id: "first-id", - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4", } }) .mockResolvedValueOnce({ name: "second-profile", id: "second-id", - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4.1-mini", }) @@ -535,7 +542,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { return { name: "first-profile", id: "first-id", - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4", } }) @@ -564,7 +571,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { const mockTask = new Task({ ...defaultTaskOptions, apiConfiguration: { - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4", }, }) @@ -572,17 +579,17 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { provider["providerSettingsManager"].getModeConfigId = vi.fn().mockResolvedValue("ask-id") provider["providerSettingsManager"].listConfig = vi .fn() - .mockResolvedValue([{ name: "ask-profile", id: "ask-id", apiProvider: "openrouter" }]) + .mockResolvedValue([{ name: "ask-profile", id: "ask-id", apiProvider: providerIdentifiers.openrouter }]) provider["providerSettingsManager"].getProfile = vi.fn().mockResolvedValue({ name: "ask-profile", id: "ask-id", - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4.1-mini", }) provider["providerSettingsManager"].activateProfile = vi.fn().mockResolvedValue({ name: "ask-profile", id: "ask-id", - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4.1-mini", }) const emitSpy = vi.spyOn(provider, "emit") @@ -609,7 +616,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { const mockTask = new Task({ ...defaultTaskOptions, apiConfiguration: { - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4", modelTemperature: 0.3, }, @@ -627,7 +634,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { ;(provider as any).providerSettingsManager.activateProfile = vi.fn().mockResolvedValue({ name: "test-config", id: "test-id", - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4", modelTemperature: 0.9, rateLimitSeconds: 7, @@ -638,7 +645,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { // Verify updateApiConfiguration was called due to forced rebuild on explicit switch expect(mockTask.updateApiConfiguration).toHaveBeenCalledWith( expect.objectContaining({ - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4", }), ) @@ -652,7 +659,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { const mockTask = new Task({ ...defaultTaskOptions, apiConfiguration: { - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4", }, }) @@ -669,7 +676,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { ;(provider as any).providerSettingsManager.activateProfile = vi.fn().mockResolvedValue({ name: "anthropic-config", id: "anthropic-id", - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiModelId: "claude-3-5-sonnet-20241022", }) @@ -678,7 +685,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { // Verify updateApiConfiguration was called expect(mockTask.updateApiConfiguration).toHaveBeenCalledWith( expect.objectContaining({ - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiModelId: "claude-3-5-sonnet-20241022", }), ) @@ -691,7 +698,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { const mockTask = new Task({ ...defaultTaskOptions, apiConfiguration: { - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4", }, }) @@ -708,7 +715,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { ;(provider as any).providerSettingsManager.activateProfile = vi.fn().mockResolvedValue({ name: "test-config", id: "test-id", - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "anthropic/claude-3-5-sonnet-20241022", }) @@ -717,7 +724,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { // Verify updateApiConfiguration was called expect(mockTask.updateApiConfiguration).toHaveBeenCalledWith( expect.objectContaining({ - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "anthropic/claude-3-5-sonnet-20241022", }), ) @@ -732,7 +739,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { const mockTask = new Task({ ...defaultTaskOptions, apiConfiguration: { - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4", }, }) @@ -749,7 +756,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { ;(provider as any).providerSettingsManager.activateProfile = vi.fn().mockResolvedValue({ name: "anthropic-config", id: "anthropic-id", - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiModelId: "claude-3-5-sonnet-20241022", }) await provider.activateProviderProfile({ name: "anthropic-config" }) @@ -763,7 +770,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { ;(provider as any).providerSettingsManager.activateProfile = vi.fn().mockResolvedValue({ name: "test-config", id: "test-id", - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4", }) await provider.activateProviderProfile({ name: "test-config" }) @@ -777,18 +784,22 @@ describe("ClineProvider - API Handler Rebuild Guard", () => { describe("getModelId helper", () => { test("correctly extracts model ID from different provider configurations", () => { - expect(getModelId({ apiProvider: "openrouter", openRouterModelId: "openai/gpt-4" })).toBe("openai/gpt-4") - expect(getModelId({ apiProvider: "anthropic", apiModelId: "claude-3-5-sonnet-20241022" })).toBe( - "claude-3-5-sonnet-20241022", + expect(getModelId({ apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openai/gpt-4" })).toBe( + "openai/gpt-4", + ) + expect( + getModelId({ apiProvider: providerIdentifiers.anthropic, apiModelId: "claude-3-5-sonnet-20241022" }), + ).toBe("claude-3-5-sonnet-20241022") + expect(getModelId({ apiProvider: providerIdentifiers.openai, openAiModelId: "gpt-4-turbo" })).toBe( + "gpt-4-turbo", ) - expect(getModelId({ apiProvider: "openai", openAiModelId: "gpt-4-turbo" })).toBe("gpt-4-turbo") - expect(getModelId({ apiProvider: "bedrock", apiModelId: "anthropic.claude-v2" })).toBe( + expect(getModelId({ apiProvider: providerIdentifiers.bedrock, apiModelId: "anthropic.claude-v2" })).toBe( "anthropic.claude-v2", ) }) test("returns undefined when no model ID is present", () => { - expect(getModelId({ apiProvider: "anthropic" })).toBeUndefined() + expect(getModelId({ apiProvider: providerIdentifiers.anthropic })).toBeUndefined() expect(getModelId({})).toBeUndefined() }) }) diff --git a/src/core/webview/__tests__/ClineProvider.flicker-free-cancel.spec.ts b/src/core/webview/__tests__/ClineProvider.flicker-free-cancel.spec.ts index 3513bd3bd5..e0ece4f9f7 100644 --- a/src/core/webview/__tests__/ClineProvider.flicker-free-cancel.spec.ts +++ b/src/core/webview/__tests__/ClineProvider.flicker-free-cancel.spec.ts @@ -6,6 +6,7 @@ import { Task } from "../../task/Task" import { TaskRegistry } from "../../task/TaskRegistry" import { ContextProxy } from "../../config/ContextProxy" import type { ProviderSettings, HistoryItem } from "@roo-code/types" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" type MockTask = Partial & Pick & { @@ -284,7 +285,7 @@ describe("ClineProvider flicker-free cancel", () => { let consoleErrorSpy: ReturnType const mockApiConfig: ProviderSettings = { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiKey: "test-key", } as ProviderSettings diff --git a/src/core/webview/__tests__/ClineProvider.lockApiConfig.spec.ts b/src/core/webview/__tests__/ClineProvider.lockApiConfig.spec.ts index 07e6b82a64..f42eb401f2 100644 --- a/src/core/webview/__tests__/ClineProvider.lockApiConfig.spec.ts +++ b/src/core/webview/__tests__/ClineProvider.lockApiConfig.spec.ts @@ -4,6 +4,7 @@ import * as vscode from "vscode" import { TelemetryService } from "@roo-code/telemetry" import { ClineProvider } from "../ClineProvider" import { ContextProxy } from "../../config/ContextProxy" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" vi.mock("vscode", () => ({ ExtensionContext: vi.fn(), @@ -344,11 +345,13 @@ describe("ClineProvider - Lock API Config Across Modes", () => { const getModeConfigIdSpy = vi .spyOn(provider.providerSettingsManager, "getModeConfigId") .mockResolvedValue("architect-profile-id") - const listConfigSpy = vi - .spyOn(provider.providerSettingsManager, "listConfig") - .mockResolvedValue([ - { name: "architect-profile", id: "architect-profile-id", apiProvider: "anthropic" }, - ]) + const listConfigSpy = vi.spyOn(provider.providerSettingsManager, "listConfig").mockResolvedValue([ + { + name: "architect-profile", + id: "architect-profile-id", + apiProvider: providerIdentifiers.anthropic, + }, + ]) const activateProviderProfileSpy = vi .spyOn(provider, "activateProviderProfile") .mockResolvedValue(undefined) @@ -367,16 +370,16 @@ describe("ClineProvider - Lock API Config Across Modes", () => { .spyOn(provider.providerSettingsManager, "getModeConfigId") .mockResolvedValue("architect-profile-id") vi.spyOn(provider.providerSettingsManager, "listConfig").mockResolvedValue([ - { name: "architect-profile", id: "architect-profile-id", apiProvider: "anthropic" }, + { name: "architect-profile", id: "architect-profile-id", apiProvider: providerIdentifiers.anthropic }, ]) vi.spyOn(provider.providerSettingsManager, "getProfile").mockResolvedValue({ name: "architect-profile", - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, }) const activateProfileSpy = vi.spyOn(provider.providerSettingsManager, "activateProfile").mockResolvedValue({ name: "architect-profile", - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, }) await provider.handleModeSwitch("architect") diff --git a/src/core/webview/__tests__/ClineProvider.spec.ts b/src/core/webview/__tests__/ClineProvider.spec.ts index e336ac8fac..fec6cef265 100644 --- a/src/core/webview/__tests__/ClineProvider.spec.ts +++ b/src/core/webview/__tests__/ClineProvider.spec.ts @@ -537,7 +537,7 @@ describe("ClineProvider", () => { defaultTaskOptions = { provider, apiConfiguration: { - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, }, } @@ -700,7 +700,7 @@ describe("ClineProvider", () => { taskHistory: [], shouldShowAnnouncement: false, apiConfiguration: { - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, }, customInstructions: undefined, alwaysAllowReadOnly: false, @@ -709,7 +709,7 @@ describe("ClineProvider", () => { codebaseIndexConfig: { codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderBaseUrl: "", codebaseIndexEmbedderModelId: "", }, @@ -1231,7 +1231,7 @@ describe("ClineProvider", () => { test("getState and getStateToPostToWebview return the complete NanoGPT configuration", async () => { await provider.resolveWebviewView(mockWebviewView) await provider.contextProxy.setProviderSettings({ - apiProvider: "nanogpt", + apiProvider: providerIdentifiers.nanogpt, nanoGptApiKey: "nanogpt-secret", nanoGptModelId: "openai/model", nanoGptRoutingPreference: "latency", @@ -1240,7 +1240,7 @@ describe("ClineProvider", () => { const state = await provider.getState() const postedState = await provider.getStateToPostToWebview() const expectedConfiguration = { - apiProvider: "nanogpt", + apiProvider: providerIdentifiers.nanogpt, nanoGptApiKey: "nanogpt-secret", nanoGptModelId: "openai/model", nanoGptRoutingPreference: "latency", @@ -1478,7 +1478,11 @@ describe("ClineProvider", () => { await provider.resolveWebviewView(mockWebviewView) const messageHandler = (mockWebviewView.webview.onDidReceiveMessage as any).mock.calls[0][0] - const profile: ProviderSettingsEntry = { name: "test-config", id: "test-id", apiProvider: "anthropic" } + const profile: ProviderSettingsEntry = { + name: "test-config", + id: "test-id", + apiProvider: providerIdentifiers.anthropic, + } ;(provider as any).providerSettingsManager = { getModeConfigId: vi.fn().mockResolvedValue("test-id"), @@ -1505,7 +1509,9 @@ describe("ClineProvider", () => { getModeConfigId: vi.fn().mockResolvedValue(undefined), listConfig: vi .fn() - .mockResolvedValue([{ name: "current-config", id: "current-id", apiProvider: "anthropic" }]), + .mockResolvedValue([ + { name: "current-config", id: "current-id", apiProvider: providerIdentifiers.anthropic }, + ]), setModeConfig: vi.fn(), } as any @@ -1522,7 +1528,11 @@ describe("ClineProvider", () => { await provider.resolveWebviewView(mockWebviewView) const messageHandler = (mockWebviewView.webview.onDidReceiveMessage as any).mock.calls[0][0] - const profile: ProviderSettingsEntry = { apiProvider: "anthropic", id: "new-id", name: "new-config" } + const profile: ProviderSettingsEntry = { + apiProvider: providerIdentifiers.anthropic, + id: "new-id", + name: "new-config", + } ;(provider as any).providerSettingsManager = { activateProfile: vi.fn().mockResolvedValue(profile), @@ -1548,7 +1558,7 @@ describe("ClineProvider", () => { const profile: ProviderSettingsEntry = { name: "config-by-id", id: "config-id-123", - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, } ;(provider as any).providerSettingsManager = { @@ -1722,7 +1732,11 @@ describe("ClineProvider", () => { const messageHandler = (mockWebviewView.webview.onDidReceiveMessage as any).mock.calls[0][0] ;(provider as any).providerSettingsManager = { - listConfig: vi.fn().mockResolvedValue([{ name: "test-config", id: "test-id", apiProvider: "anthropic" }]), + listConfig: vi + .fn() + .mockResolvedValue([ + { name: "test-config", id: "test-id", apiProvider: providerIdentifiers.anthropic }, + ]), saveConfig: vi.fn().mockResolvedValue("test-id"), setModeConfig: vi.fn(), } as any @@ -1731,7 +1745,7 @@ describe("ClineProvider", () => { await messageHandler({ type: "upsertApiConfiguration", text: "test-config", - apiConfiguration: { apiProvider: "anthropic" }, + apiConfiguration: { apiProvider: providerIdentifiers.anthropic }, }) // Should save config as default for current mode @@ -1940,7 +1954,7 @@ describe("ClineProvider", () => { // Test with mcpEnabled: true vi.spyOn(provider, "getState").mockResolvedValueOnce({ apiConfiguration: { - apiProvider: "openrouter" as const, + apiProvider: providerIdentifiers.openrouter, }, mcpEnabled: true, mode: "code" as const, @@ -1964,7 +1978,7 @@ describe("ClineProvider", () => { // Test with mcpEnabled: false vi.spyOn(provider, "getState").mockResolvedValueOnce({ apiConfiguration: { - apiProvider: "openrouter" as const, + apiProvider: providerIdentifiers.openrouter, }, mcpEnabled: false, mode: "code" as const, @@ -2000,7 +2014,7 @@ describe("ClineProvider", () => { // Mock getState to return custom instructions for code mode vi.spyOn(provider, "getState").mockResolvedValue({ apiConfiguration: { - apiProvider: "openrouter" as const, + apiProvider: providerIdentifiers.openrouter, }, customModePrompts: { code: { customInstructions: "Code mode specific instructions" }, @@ -2029,7 +2043,7 @@ describe("ClineProvider", () => { // Mock getState to return architect mode instructions vi.spyOn(provider, "getState").mockResolvedValue({ apiConfiguration: { - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, }, customModePrompts: { architect: { customInstructions: "Architect mode instructions" }, @@ -2064,7 +2078,7 @@ describe("ClineProvider", () => { const profile: ProviderSettingsEntry = { name: "saved-config", id: "saved-config-id", - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, } ;(provider as any).providerSettingsManager = { @@ -2095,7 +2109,9 @@ describe("ClineProvider", () => { getModeConfigId: vi.fn().mockResolvedValue(undefined), listConfig: vi .fn() - .mockResolvedValue([{ name: "current-config", id: "current-id", apiProvider: "anthropic" }]), + .mockResolvedValue([ + { name: "current-config", id: "current-id", apiProvider: providerIdentifiers.anthropic }, + ]), setModeConfig: vi.fn(), } as any @@ -2219,10 +2235,14 @@ describe("ClineProvider", () => { getModeConfigId: vi.fn().mockResolvedValue("config-id"), listConfig: vi .fn() - .mockResolvedValue([{ name: "test-config", id: "config-id", apiProvider: "anthropic" }]), - activateProfile: vi - .fn() - .mockResolvedValue({ name: "test-config", id: "config-id", apiProvider: "anthropic" }), + .mockResolvedValue([ + { name: "test-config", id: "config-id", apiProvider: providerIdentifiers.anthropic }, + ]), + activateProfile: vi.fn().mockResolvedValue({ + name: "test-config", + id: "config-id", + apiProvider: providerIdentifiers.anthropic, + }), } // Spy on log method to verify no warning was logged @@ -2354,7 +2374,9 @@ describe("ClineProvider", () => { getModeConfigId: vi.fn().mockResolvedValue("config-id"), listConfig: vi .fn() - .mockResolvedValue([{ name: "test-config", id: "config-id", apiProvider: "anthropic" }]), + .mockResolvedValue([ + { name: "test-config", id: "config-id", apiProvider: providerIdentifiers.anthropic }, + ]), activateProfile: vi.fn().mockRejectedValue(new Error("Failed to load config")), } @@ -2454,7 +2476,9 @@ describe("ClineProvider", () => { setModeConfig: vi.fn().mockRejectedValue(new Error("Failed to update mode config")), listConfig: vi .fn() - .mockResolvedValue([{ name: "test-config", id: "test-id", apiProvider: "anthropic" }]), + .mockResolvedValue([ + { name: "test-config", id: "test-id", apiProvider: providerIdentifiers.anthropic }, + ]), } as any // Mock getState to provide necessary data @@ -2467,7 +2491,7 @@ describe("ClineProvider", () => { await messageHandler({ type: "upsertApiConfiguration", text: "test-config", - apiConfiguration: { apiProvider: "anthropic", apiKey: "test-key" }, + apiConfiguration: { apiProvider: providerIdentifiers.anthropic, apiKey: "test-key" }, }) // Verify error was logged and user was notified @@ -2486,11 +2510,13 @@ describe("ClineProvider", () => { saveConfig: vi.fn().mockResolvedValue(undefined), listConfig: vi .fn() - .mockResolvedValue([{ name: "test-config", id: "test-id", apiProvider: "anthropic" }]), + .mockResolvedValue([ + { name: "test-config", id: "test-id", apiProvider: providerIdentifiers.anthropic }, + ]), } as any const testApiConfig = { - apiProvider: "anthropic" as const, + apiProvider: providerIdentifiers.anthropic, apiKey: "test-key", } @@ -2506,7 +2532,7 @@ describe("ClineProvider", () => { // Verify state updates expect(mockContext.globalState.update).toHaveBeenCalledWith("listApiConfigMeta", [ - { name: "test-config", id: "test-id", apiProvider: "anthropic" }, + { name: "test-config", id: "test-id", apiProvider: providerIdentifiers.anthropic }, ]) expect(mockContext.globalState.update).toHaveBeenCalledWith("currentApiConfigName", "test-config") @@ -2529,7 +2555,9 @@ describe("ClineProvider", () => { saveConfig: vi.fn().mockResolvedValue(undefined), listConfig: vi .fn() - .mockResolvedValue([{ name: "test-config", id: "test-id", apiProvider: "anthropic" }]), + .mockResolvedValue([ + { name: "test-config", id: "test-id", apiProvider: providerIdentifiers.anthropic }, + ]), } as any // Setup Task instance with auto-mock from the top of the file @@ -2537,7 +2565,7 @@ describe("ClineProvider", () => { await provider.addClineToStack(mockCline) const testApiConfig = { - apiProvider: "anthropic" as const, + apiProvider: providerIdentifiers.anthropic, apiKey: "test-key", } @@ -2556,7 +2584,7 @@ describe("ClineProvider", () => { // Verify state was still updated expect(mockContext.globalState.update).toHaveBeenCalledWith("listApiConfigMeta", [ - { name: "test-config", id: "test-id", apiProvider: "anthropic" }, + { name: "test-config", id: "test-id", apiProvider: providerIdentifiers.anthropic }, ]) expect(mockContext.globalState.update).toHaveBeenCalledWith("currentApiConfigName", "test-config") }) @@ -2570,11 +2598,13 @@ describe("ClineProvider", () => { saveConfig: vi.fn().mockResolvedValue(undefined), listConfig: vi .fn() - .mockResolvedValue([{ name: "test-config", id: "test-id", apiProvider: "anthropic" }]), + .mockResolvedValue([ + { name: "test-config", id: "test-id", apiProvider: providerIdentifiers.anthropic }, + ]), } as any const testApiConfig = { - apiProvider: "anthropic" as const, + apiProvider: providerIdentifiers.anthropic, apiKey: "test-key", } @@ -2590,10 +2620,10 @@ describe("ClineProvider", () => { // Verify state updates expect(mockContext.globalState.update).toHaveBeenCalledWith("listApiConfigMeta", [ - { name: "test-config", id: "test-id", apiProvider: "anthropic" }, + { name: "test-config", id: "test-id", apiProvider: providerIdentifiers.anthropic }, ]) expect(updateGlobalStateSpy).toHaveBeenCalledWith("listApiConfigMeta", [ - { name: "test-config", id: "test-id", apiProvider: "anthropic" }, + { name: "test-config", id: "test-id", apiProvider: providerIdentifiers.anthropic }, ]) }) }) @@ -3185,7 +3215,7 @@ describe("getTelemetryProperties", () => { defaultTaskOptions = { provider, apiConfiguration: { - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, }, } @@ -3426,21 +3456,21 @@ describe("ClineProvider - Router Models", () => { await messageHandler({ type: "requestRouterModels" }) // Verify getModels was called for each provider with correct options - expect(getModels).toHaveBeenCalledWith({ provider: "openrouter" }) - expect(getModels).toHaveBeenCalledWith({ provider: "requesty", apiKey: "requesty-key" }) - expect(getModels).toHaveBeenCalledWith({ provider: "unbound" }) - expect(getModels).toHaveBeenCalledWith({ provider: "vercel-ai-gateway" }) + expect(getModels).toHaveBeenCalledWith({ provider: providerIdentifiers.openrouter }) + expect(getModels).toHaveBeenCalledWith({ provider: providerIdentifiers.requesty, apiKey: "requesty-key" }) + expect(getModels).toHaveBeenCalledWith({ provider: providerIdentifiers.unbound }) + expect(getModels).toHaveBeenCalledWith({ provider: providerIdentifiers.vercelAiGateway }) expect(getModels).toHaveBeenCalledWith({ - provider: "litellm", + provider: providerIdentifiers.litellm, apiKey: "litellm-key", baseUrl: "http://localhost:4000", }) // Opencode Go's /models endpoint is public, so it is fetched like the other no-auth routers. - expect(getModels).toHaveBeenCalledWith(expect.objectContaining({ provider: "opencode-go" })) + expect(getModels).toHaveBeenCalledWith(expect.objectContaining({ provider: providerIdentifiers.opencodeGo })) // Kenari's /models endpoint is public, so it is fetched like the other no-auth routers. - expect(getModels).toHaveBeenCalledWith(expect.objectContaining({ provider: "kenari" })) + expect(getModels).toHaveBeenCalledWith(expect.objectContaining({ provider: providerIdentifiers.kenari })) // NanoGPT's detailed catalog is public and may be scoped by an optional key. - expect(getModels).toHaveBeenCalledWith({ provider: "nanogpt", apiKey: undefined }) + expect(getModels).toHaveBeenCalledWith({ provider: providerIdentifiers.nanogpt, apiKey: undefined }) // Verify response was sent expect(mockPostMessage).toHaveBeenCalledWith({ @@ -3526,14 +3556,14 @@ describe("ClineProvider - Router Models", () => { type: "singleRouterModelFetchResponse", success: false, error: "Requesty API error", - values: { provider: "requesty" }, + values: { provider: providerIdentifiers.requesty }, }) expect(mockPostMessage).toHaveBeenCalledWith({ type: "singleRouterModelFetchResponse", success: false, error: "LiteLLM connection failed", - values: { provider: "litellm" }, + values: { provider: providerIdentifiers.litellm }, }) }) @@ -3566,7 +3596,7 @@ describe("ClineProvider - Router Models", () => { // Verify LiteLLM was called with values from message expect(getModels).toHaveBeenCalledWith({ - provider: "litellm", + provider: providerIdentifiers.litellm, apiKey: "message-litellm-key", baseUrl: "http://message-url:4000", }) @@ -3595,7 +3625,7 @@ describe("ClineProvider - Router Models", () => { // Verify LiteLLM was NOT called expect(getModels).not.toHaveBeenCalledWith( expect.objectContaining({ - provider: "litellm", + provider: providerIdentifiers.litellm, }), ) @@ -3645,7 +3675,7 @@ describe("ClineProvider - Router Models", () => { }) expect(getModels).toHaveBeenCalledWith({ - provider: "lmstudio", + provider: providerIdentifiers.lmstudio, baseUrl: "http://localhost:1234", }) }) @@ -3743,7 +3773,7 @@ describe("ClineProvider - Comprehensive Edit/Delete Edge Cases", () => { defaultTaskOptions = { provider, apiConfiguration: { - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, }, } @@ -4680,7 +4710,7 @@ describe("ClineProvider - Comprehensive Edit/Delete Edge Cases", () => { apiConfiguration: { zooGatewayModelId: "anthropic/claude-sonnet-4" }, } as any) vi.spyOn(provider.contextProxy, "getProviderSettings").mockReturnValue({ - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, } as any) vi.spyOn(provider.contextProxy, "getValues").mockReturnValue({ currentApiConfigName: "Anthropic", @@ -4698,7 +4728,7 @@ describe("ClineProvider - Comprehensive Edit/Delete Edge Cases", () => { expect(upsertSpy).toHaveBeenCalledWith( "Zoo Gateway", expect.objectContaining({ - apiProvider: "zoo-gateway", + apiProvider: providerIdentifiers.zooGateway, zooSessionToken: "zoo_ext_token", zooGatewayBaseUrl: "https://www.zoocode.dev/api/gateway/v1", }), @@ -4711,7 +4741,7 @@ describe("ClineProvider - Comprehensive Edit/Delete Edge Cases", () => { apiConfiguration: { zooGatewayModelId: "anthropic/claude-sonnet-4" }, } as any) vi.spyOn(provider.contextProxy, "getProviderSettings").mockReturnValue({ - apiProvider: "zoo-gateway", + apiProvider: providerIdentifiers.zooGateway, } as any) vi.spyOn(provider.contextProxy, "getValues").mockReturnValue({ currentApiConfigName: "Zoo Gateway", @@ -4721,18 +4751,18 @@ describe("ClineProvider - Comprehensive Edit/Delete Edge Cases", () => { vi.spyOn(provider, "postStateToWebview").mockResolvedValue(undefined) ;(provider as any).providerSettingsManager = { listConfig: vi.fn().mockResolvedValue([ - { name: "Zoo Gateway", apiProvider: "zoo-gateway" }, - { name: "Backup Zoo", apiProvider: "zoo-gateway" }, + { name: "Zoo Gateway", apiProvider: providerIdentifiers.zooGateway }, + { name: "Backup Zoo", apiProvider: providerIdentifiers.zooGateway }, ]), getProfile: vi .fn() .mockResolvedValueOnce({ - apiProvider: "zoo-gateway", + apiProvider: providerIdentifiers.zooGateway, zooSessionToken: "old-token", zooGatewayBaseUrl: "https://old.example/api/gateway/v1", }) .mockResolvedValueOnce({ - apiProvider: "zoo-gateway", + apiProvider: providerIdentifiers.zooGateway, zooSessionToken: "old-token", }), saveConfig, @@ -4794,7 +4824,9 @@ describe("ClineProvider - Comprehensive Edit/Delete Edge Cases", () => { const postMessageSpy = vi.spyOn(provider, "postMessageToWebview").mockResolvedValue(undefined) ;(provider as any).providerSettingsManager = { - listConfig: vi.fn().mockResolvedValue([{ name: "Zoo Gateway", apiProvider: "zoo-gateway" }]), + listConfig: vi + .fn() + .mockResolvedValue([{ name: "Zoo Gateway", apiProvider: providerIdentifiers.zooGateway }]), getProfile: vi.fn().mockResolvedValue({ zooSessionToken: "current-token", zooGatewayBaseUrl: "https://www.zoocode.dev/api/gateway/v1", @@ -4813,7 +4845,9 @@ describe("ClineProvider - Comprehensive Edit/Delete Edge Cases", () => { const handleSpy = vi.spyOn(provider, "handleZooCodeCallback").mockResolvedValue(undefined) ;(provider as any).providerSettingsManager = { - listConfig: vi.fn().mockResolvedValue([{ name: "Zoo Gateway", apiProvider: "zoo-gateway" }]), + listConfig: vi + .fn() + .mockResolvedValue([{ name: "Zoo Gateway", apiProvider: providerIdentifiers.zooGateway }]), getProfile: vi.fn().mockResolvedValue({ zooSessionToken: "stale-token", zooGatewayBaseUrl: "https://www.zoocode.dev/api/gateway/v1", @@ -4831,7 +4865,9 @@ describe("ClineProvider - Comprehensive Edit/Delete Edge Cases", () => { const handleSpy = vi.spyOn(provider, "handleZooCodeCallback").mockResolvedValue(undefined) ;(provider as any).providerSettingsManager = { - listConfig: vi.fn().mockResolvedValue([{ name: "Zoo Gateway", apiProvider: "zoo-gateway" }]), + listConfig: vi + .fn() + .mockResolvedValue([{ name: "Zoo Gateway", apiProvider: providerIdentifiers.zooGateway }]), getProfile: vi.fn().mockResolvedValue({ zooSessionToken: "current-token", zooGatewayBaseUrl: "https://staging.zoocode.dev/api/gateway/v1", diff --git a/src/core/webview/__tests__/ClineProvider.sticky-mode.spec.ts b/src/core/webview/__tests__/ClineProvider.sticky-mode.spec.ts index e6d8c9325f..fedfa13030 100644 --- a/src/core/webview/__tests__/ClineProvider.sticky-mode.spec.ts +++ b/src/core/webview/__tests__/ClineProvider.sticky-mode.spec.ts @@ -6,6 +6,7 @@ import { ClineProvider } from "../ClineProvider" import { ContextProxy } from "../../config/ContextProxy" import { Task } from "../../task/Task" import type { HistoryItem, ProviderName } from "@roo-code/types" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" vi.mock("vscode", () => ({ ExtensionContext: vi.fn(), @@ -318,7 +319,7 @@ describe("ClineProvider - Sticky Mode", () => { // Create a mock task const mockTask = new Task({ provider, - apiConfiguration: { apiProvider: "openrouter" }, + apiConfiguration: { apiProvider: providerIdentifiers.openrouter }, }) // Get the actual taskId from the mock @@ -411,7 +412,7 @@ describe("ClineProvider - Sticky Mode", () => { // Create a mock task with history const mockTask = new Task({ provider, - apiConfiguration: { apiProvider: "openrouter" }, + apiConfiguration: { apiProvider: providerIdentifiers.openrouter }, }) // Get the actual taskId from the mock @@ -534,7 +535,7 @@ describe("ClineProvider - Sticky Mode", () => { // Create a mock task const mockTask = new Task({ provider, - apiConfiguration: { apiProvider: "openrouter" }, + apiConfiguration: { apiProvider: providerIdentifiers.openrouter }, }) // Get the actual taskId from the mock @@ -587,7 +588,7 @@ describe("ClineProvider - Sticky Mode", () => { // Create parent task const parentTask = new Task({ provider, - apiConfiguration: { apiProvider: "openrouter" }, + apiConfiguration: { apiProvider: providerIdentifiers.openrouter }, }) // Get the actual taskId from the mock @@ -636,7 +637,7 @@ describe("ClineProvider - Sticky Mode", () => { // Create a subtask (simulating new_task tool behavior) const subtask = new Task({ provider, - apiConfiguration: { apiProvider: "openrouter" }, + apiConfiguration: { apiProvider: providerIdentifiers.openrouter }, parentTask: parentTask, }) const subtaskId = (subtask as any).taskId || "subtask-id" @@ -672,7 +673,7 @@ describe("ClineProvider - Sticky Mode", () => { // Create a mock task that throws on save const mockTask = new Task({ provider, - apiConfiguration: { apiProvider: "openrouter" }, + apiConfiguration: { apiProvider: providerIdentifiers.openrouter }, }) vi.spyOn(mockTask as any, "saveClineMessages").mockRejectedValue(new Error("Save failed")) @@ -724,8 +725,8 @@ describe("ClineProvider - Sticky Mode", () => { it("should restore API configuration when restoring task from history with mode", async () => { // Setup: Configure different API configs for different modes - const codeApiConfig = { apiProvider: "anthropic" as ProviderName, anthropicApiKey: "code-key" } - const architectApiConfig = { apiProvider: "openai" as ProviderName, openAiApiKey: "architect-key" } + const codeApiConfig = { apiProvider: providerIdentifiers.anthropic, anthropicApiKey: "code-key" } + const architectApiConfig = { apiProvider: providerIdentifiers.openai, openAiApiKey: "architect-key" } // Save API configs await provider.upsertProviderProfile("code-config", codeApiConfig) diff --git a/src/core/webview/__tests__/ClineProvider.sticky-profile.spec.ts b/src/core/webview/__tests__/ClineProvider.sticky-profile.spec.ts index c982cf53c0..7d8493fba3 100644 --- a/src/core/webview/__tests__/ClineProvider.sticky-profile.spec.ts +++ b/src/core/webview/__tests__/ClineProvider.sticky-profile.spec.ts @@ -5,6 +5,7 @@ import { TelemetryService } from "@roo-code/telemetry" import { ClineProvider } from "../ClineProvider" import { ContextProxy } from "../../config/ContextProxy" import type { HistoryItem } from "@roo-code/types" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" vi.mock("vscode", () => ({ ExtensionContext: vi.fn(), @@ -363,12 +364,12 @@ describe("ClineProvider - Sticky Provider Profile", () => { vi.spyOn(provider.providerSettingsManager, "activateProfile").mockResolvedValue({ name: "new-profile", id: "new-profile-id", - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, }) // Mock providerSettingsManager.listConfig vi.spyOn(provider.providerSettingsManager, "listConfig").mockResolvedValue([ - { name: "new-profile", id: "new-profile-id", apiProvider: "anthropic" }, + { name: "new-profile", id: "new-profile-id", apiProvider: providerIdentifiers.anthropic }, ]) // Switch provider profile @@ -428,12 +429,12 @@ describe("ClineProvider - Sticky Provider Profile", () => { vi.spyOn(provider.providerSettingsManager, "activateProfile").mockResolvedValue({ name: "new-profile", id: "new-profile-id", - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, }) // Mock providerSettingsManager.listConfig vi.spyOn(provider.providerSettingsManager, "listConfig").mockResolvedValue([ - { name: "new-profile", id: "new-profile-id", apiProvider: "openrouter" }, + { name: "new-profile", id: "new-profile-id", apiProvider: providerIdentifiers.openrouter }, ]) // Switch provider profile @@ -471,11 +472,11 @@ describe("ClineProvider - Sticky Provider Profile", () => { vi.spyOn(provider.providerSettingsManager, "activateProfile").mockResolvedValue({ name: "new-profile", id: "new-profile-id", - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, }) vi.spyOn(provider.providerSettingsManager, "listConfig").mockResolvedValue([ - { name: "new-profile", id: "new-profile-id", apiProvider: "openrouter" }, + { name: "new-profile", id: "new-profile-id", apiProvider: providerIdentifiers.openrouter }, ]) await provider.activateProviderProfile({ name: "new-profile" }) @@ -513,7 +514,7 @@ describe("ClineProvider - Sticky Provider Profile", () => { // Mock providerSettingsManager.listConfig vi.spyOn(provider.providerSettingsManager, "listConfig").mockResolvedValue([ - { name: "saved-profile", id: "saved-profile-id", apiProvider: "anthropic" }, + { name: "saved-profile", id: "saved-profile-id", apiProvider: providerIdentifiers.anthropic }, ]) // Initialize task with history item @@ -579,7 +580,7 @@ describe("ClineProvider - Sticky Provider Profile", () => { const logSpy = vi.spyOn(provider, "log") vi.spyOn(provider.providerSettingsManager, "listConfig").mockResolvedValue([ - { name: "saved-profile", id: "saved-profile-id", apiProvider: "anthropic" }, + { name: "saved-profile", id: "saved-profile-id", apiProvider: providerIdentifiers.anthropic }, ]) await provider.createTaskWithHistoryItem(historyItem) @@ -613,7 +614,7 @@ describe("ClineProvider - Sticky Provider Profile", () => { vi.spyOn(provider.providerSettingsManager, "getModeConfigId").mockResolvedValue("mode-config-id") vi.spyOn(provider.providerSettingsManager, "listConfig").mockResolvedValue([ - { name: "mode-profile", id: "mode-config-id", apiProvider: "anthropic" }, + { name: "mode-profile", id: "mode-config-id", apiProvider: providerIdentifiers.anthropic }, ]) await provider.createTaskWithHistoryItem(historyItem) @@ -683,8 +684,8 @@ describe("ClineProvider - Sticky Provider Profile", () => { // Mock providerSettingsManager methods vi.spyOn(provider.providerSettingsManager, "getModeConfigId").mockResolvedValue("mode-config-id") vi.spyOn(provider.providerSettingsManager, "listConfig").mockResolvedValue([ - { name: "mode-preferred-profile", id: "mode-config-id", apiProvider: "anthropic" }, - { name: "task-specific-profile", id: "task-profile-id", apiProvider: "openai" }, + { name: "mode-preferred-profile", id: "mode-config-id", apiProvider: providerIdentifiers.anthropic }, + { name: "task-specific-profile", id: "task-profile-id", apiProvider: providerIdentifiers.openai }, ]) // Initialize task with history item @@ -768,12 +769,12 @@ describe("ClineProvider - Sticky Provider Profile", () => { vi.spyOn(provider.providerSettingsManager, "activateProfile").mockResolvedValue({ name: "new-profile", id: "new-profile-id", - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, }) // Mock providerSettingsManager.listConfig vi.spyOn(provider.providerSettingsManager, "listConfig").mockResolvedValue([ - { name: "new-profile", id: "new-profile-id", apiProvider: "anthropic" }, + { name: "new-profile", id: "new-profile-id", apiProvider: providerIdentifiers.anthropic }, ]) // Trigger a profile switch @@ -869,14 +870,14 @@ describe("ClineProvider - Sticky Provider Profile", () => { vi.spyOn(provider.providerSettingsManager, "activateProfile").mockResolvedValue({ name: "profile-c", id: "profile-c-id", - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, }) // Mock providerSettingsManager.listConfig vi.spyOn(provider.providerSettingsManager, "listConfig").mockResolvedValue([ - { name: "profile-a", id: "profile-a-id", apiProvider: "anthropic" }, - { name: "profile-b", id: "profile-b-id", apiProvider: "openai" }, - { name: "profile-c", id: "profile-c-id", apiProvider: "anthropic" }, + { name: "profile-a", id: "profile-a-id", apiProvider: providerIdentifiers.anthropic }, + { name: "profile-b", id: "profile-b-id", apiProvider: providerIdentifiers.openai }, + { name: "profile-c", id: "profile-c-id", apiProvider: providerIdentifiers.anthropic }, ]) // Switch task 1's profile to profile C @@ -928,12 +929,12 @@ describe("ClineProvider - Sticky Provider Profile", () => { vi.spyOn(provider.providerSettingsManager, "activateProfile").mockResolvedValue({ name: "new-profile", id: "new-profile-id", - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, }) // Mock providerSettingsManager.listConfig vi.spyOn(provider.providerSettingsManager, "listConfig").mockResolvedValue([ - { name: "new-profile", id: "new-profile-id", apiProvider: "anthropic" }, + { name: "new-profile", id: "new-profile-id", apiProvider: providerIdentifiers.anthropic }, ]) // Mock log to verify error is logged @@ -996,7 +997,7 @@ describe("ClineProvider - Sticky Provider Profile", () => { // Mock providerSettingsManager.listConfig to return the profile vi.spyOn(provider.providerSettingsManager, "listConfig").mockResolvedValue([ - { name: "failing-profile", id: "failing-profile-id", apiProvider: "anthropic" }, + { name: "failing-profile", id: "failing-profile-id", apiProvider: providerIdentifiers.anthropic }, ]) // Mock activateProviderProfile to throw error diff --git a/src/core/webview/__tests__/messageEnhancer.test.ts b/src/core/webview/__tests__/messageEnhancer.test.ts index 562824bf7c..964c4ebdef 100644 --- a/src/core/webview/__tests__/messageEnhancer.test.ts +++ b/src/core/webview/__tests__/messageEnhancer.test.ts @@ -4,6 +4,7 @@ import { TelemetryService } from "@roo-code/telemetry" import { MessageEnhancer } from "../messageEnhancer" import * as singleCompletionHandlerModule from "../../../utils/single-completion-handler" import { ProviderSettingsManager } from "../../config/ProviderSettingsManager" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" // Mock dependencies vi.mock("../../../utils/single-completion-handler") @@ -14,7 +15,7 @@ describe("MessageEnhancer", () => { let mockSingleCompletionHandler: ReturnType Promise>> const mockApiConfiguration: ProviderSettings = { - apiProvider: "openai", + apiProvider: providerIdentifiers.openai, apiKey: "test-key", apiModelId: "gpt-4", } @@ -32,7 +33,7 @@ describe("MessageEnhancer", () => { mockProviderSettingsManager = { getProfile: vi.fn().mockResolvedValue({ name: "Enhancement Config", - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiKey: "enhancement-key", apiModelId: "claude-3", }), @@ -94,7 +95,7 @@ describe("MessageEnhancer", () => { // Verify the enhancement config was used instead of default const expectedConfig = { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiKey: "enhancement-key", apiModelId: "claude-3", } diff --git a/src/core/webview/__tests__/webviewMessageHandler.routerModels.spec.ts b/src/core/webview/__tests__/webviewMessageHandler.routerModels.spec.ts index 1ba578a894..5a4b3e7be3 100644 --- a/src/core/webview/__tests__/webviewMessageHandler.routerModels.spec.ts +++ b/src/core/webview/__tests__/webviewMessageHandler.routerModels.spec.ts @@ -1,6 +1,11 @@ import { describe, it, expect, vi, beforeEach } from "vitest" -import { kimiCodeAuthMethodSchema, providerIdentifiers, RouterModelsMessageType } from "@roo-code/types" +import { + kimiCodeAuthMethodSchema, + providerIdentifiers, + retiredProviderIdentifiers, + RouterModelsMessageType, +} from "@roo-code/types" import { webviewMessageHandler } from "../webviewMessageHandler" import type { ClineProvider } from "../ClineProvider" @@ -104,7 +109,7 @@ describe("webviewMessageHandler - requestRouterModels provider filter", () => { type: RouterModelsMessageType.singleRouterModelFetchResponse, success: false, error: "Roo Code Router has been removed. Please select and configure a different provider.", - values: { provider: "roo" }, + values: { provider: retiredProviderIdentifiers.roo }, }) }) diff --git a/src/core/webview/__tests__/webviewMessageHandler.spec.ts b/src/core/webview/__tests__/webviewMessageHandler.spec.ts index bc92522790..3070ca532a 100644 --- a/src/core/webview/__tests__/webviewMessageHandler.spec.ts +++ b/src/core/webview/__tests__/webviewMessageHandler.spec.ts @@ -197,6 +197,7 @@ vi.mock("../../mentions/resolveImageMentions", () => ({ import { resolveImageMentions } from "../../mentions/resolveImageMentions" import { Terminal } from "../../../integrations/terminal/Terminal" import { TerminalRegistry } from "../../../integrations/terminal/TerminalRegistry" +import { providerIdentifiers, retiredProviderIdentifiers } from "@roo-code/types/provider-identifiers" describe("webviewMessageHandler - requestLmStudioModels", () => { beforeEach(() => { @@ -232,7 +233,10 @@ describe("webviewMessageHandler - requestLmStudioModels", () => { type: "requestLmStudioModels", }) - expect(mockGetModels).toHaveBeenCalledWith({ provider: "lmstudio", baseUrl: "http://localhost:1234" }) + expect(mockGetModels).toHaveBeenCalledWith({ + provider: providerIdentifiers.lmstudio, + baseUrl: "http://localhost:1234", + }) expect(mockClineProvider.postMessageToWebview).toHaveBeenCalledWith({ type: "lmStudioModels", @@ -332,7 +336,10 @@ describe("webviewMessageHandler - requestOllamaModels", () => { type: "requestOllamaModels", }) - expect(mockGetModels).toHaveBeenCalledWith({ provider: "ollama", baseUrl: "http://localhost:1234" }) + expect(mockGetModels).toHaveBeenCalledWith({ + provider: providerIdentifiers.ollama, + baseUrl: "http://localhost:1234", + }) expect(mockClineProvider.postMessageToWebview).toHaveBeenCalledWith({ type: "ollamaModels", @@ -413,14 +420,14 @@ describe("webviewMessageHandler - requestOllamaModels", () => { // Should use the URL from message values, not the saved state expect(mockFlushModels).toHaveBeenCalledWith( { - provider: "ollama", + provider: providerIdentifiers.ollama, baseUrl: "https://ollama.example.com", apiKey: "secret-key", }, true, ) expect(mockGetModels).toHaveBeenCalledWith({ - provider: "ollama", + provider: providerIdentifiers.ollama, baseUrl: "https://ollama.example.com", apiKey: "secret-key", }) @@ -468,25 +475,27 @@ describe("webviewMessageHandler - requestRouterModels", () => { }) // Verify getModels was called for each provider - expect(mockGetModels).toHaveBeenCalledWith({ provider: "openrouter" }) - expect(mockGetModels).toHaveBeenCalledWith({ provider: "requesty", apiKey: "requesty-key" }) + expect(mockGetModels).toHaveBeenCalledWith({ provider: providerIdentifiers.openrouter }) + expect(mockGetModels).toHaveBeenCalledWith({ provider: providerIdentifiers.requesty, apiKey: "requesty-key" }) expect(mockGetModels).toHaveBeenCalledWith( expect.objectContaining({ - provider: "unbound", + provider: providerIdentifiers.unbound, }), ) - expect(mockGetModels).toHaveBeenCalledWith({ provider: "vercel-ai-gateway" }) + expect(mockGetModels).toHaveBeenCalledWith({ provider: providerIdentifiers.vercelAiGateway }) expect(mockGetModels).toHaveBeenCalledWith({ - provider: "litellm", + provider: providerIdentifiers.litellm, apiKey: "litellm-key", baseUrl: "http://localhost:4000", }) // Opencode Go's /models endpoint is public, so it is fetched like the other no-auth routers. - expect(mockGetModels).toHaveBeenCalledWith(expect.objectContaining({ provider: "opencode-go" })) + expect(mockGetModels).toHaveBeenCalledWith( + expect.objectContaining({ provider: providerIdentifiers.opencodeGo }), + ) // Kenari's /models endpoint is public, so it is fetched like the other no-auth routers. - expect(mockGetModels).toHaveBeenCalledWith(expect.objectContaining({ provider: "kenari" })) + expect(mockGetModels).toHaveBeenCalledWith(expect.objectContaining({ provider: providerIdentifiers.kenari })) // NanoGPT's detailed catalog is public and may optionally be scoped by a key. - expect(mockGetModels).toHaveBeenCalledWith({ provider: "nanogpt", apiKey: undefined }) + expect(mockGetModels).toHaveBeenCalledWith({ provider: providerIdentifiers.nanogpt, apiKey: undefined }) // Verify response was sent expect(mockClineProvider.postMessageToWebview).toHaveBeenCalledWith({ @@ -533,7 +542,7 @@ describe("webviewMessageHandler - requestRouterModels", () => { await webviewMessageHandler(mockClineProvider, { type: "requestRouterModels" }) // Must be fetched despite no configured key, forwarding apiKey: undefined. - expect(mockGetModels).toHaveBeenCalledWith({ provider: "opencode-go", apiKey: undefined }) + expect(mockGetModels).toHaveBeenCalledWith({ provider: providerIdentifiers.opencodeGo, apiKey: undefined }) const routerModelsCall = (mockClineProvider.postMessageToWebview as any).mock.calls.find( ([msg]: [{ type: string }]) => msg.type === "routerModels", @@ -557,13 +566,16 @@ describe("webviewMessageHandler - requestRouterModels", () => { await webviewMessageHandler(mockClineProvider, { type: "requestRouterModels", values: { - provider: "opencode-go", + provider: providerIdentifiers.opencodeGo, opencodeGoApiKey: "fresh-key", }, }) - expect(mockFlushModels).toHaveBeenCalledWith({ provider: "opencode-go", apiKey: "fresh-key" }, true) - expect(mockGetModels).toHaveBeenCalledWith({ provider: "opencode-go", apiKey: "fresh-key" }) + expect(mockFlushModels).toHaveBeenCalledWith( + { provider: providerIdentifiers.opencodeGo, apiKey: "fresh-key" }, + true, + ) + expect(mockGetModels).toHaveBeenCalledWith({ provider: providerIdentifiers.opencodeGo, apiKey: "fresh-key" }) expect(mockClineProvider.postMessageToWebview).toHaveBeenCalledWith({ type: "routerModels", routerModels: { @@ -571,7 +583,7 @@ describe("webviewMessageHandler - requestRouterModels", () => { "opencode/model": expect.objectContaining({ description: "Opencode model" }), }, }, - values: { provider: "opencode-go" }, + values: { provider: providerIdentifiers.opencodeGo }, }) }) @@ -591,13 +603,16 @@ describe("webviewMessageHandler - requestRouterModels", () => { await webviewMessageHandler(mockClineProvider, { type: "requestRouterModels", values: { - provider: "kenari", + provider: providerIdentifiers.kenari, kenariApiKey: "fresh-kenari-key", }, }) - expect(mockFlushModels).toHaveBeenCalledWith({ provider: "kenari", apiKey: "fresh-kenari-key" }, true) - expect(mockGetModels).toHaveBeenCalledWith({ provider: "kenari", apiKey: "fresh-kenari-key" }) + expect(mockFlushModels).toHaveBeenCalledWith( + { provider: providerIdentifiers.kenari, apiKey: "fresh-kenari-key" }, + true, + ) + expect(mockGetModels).toHaveBeenCalledWith({ provider: providerIdentifiers.kenari, apiKey: "fresh-kenari-key" }) expect(mockClineProvider.postMessageToWebview).toHaveBeenCalledWith({ type: "routerModels", routerModels: { @@ -605,7 +620,7 @@ describe("webviewMessageHandler - requestRouterModels", () => { "glm-5-2": expect.objectContaining({ description: "Kenari model" }), }, }, - values: { provider: "kenari" }, + values: { provider: providerIdentifiers.kenari }, }) }) @@ -617,10 +632,10 @@ describe("webviewMessageHandler - requestRouterModels", () => { await webviewMessageHandler(mockClineProvider, { type: "requestRouterModels", - values: { provider: "nanogpt" }, + values: { provider: providerIdentifiers.nanogpt }, }) - expect(mockGetModels).toHaveBeenCalledWith({ provider: "nanogpt", apiKey: undefined }) + expect(mockGetModels).toHaveBeenCalledWith({ provider: providerIdentifiers.nanogpt, apiKey: undefined }) expect(mockFlushModels).not.toHaveBeenCalled() }) @@ -634,11 +649,14 @@ describe("webviewMessageHandler - requestRouterModels", () => { await webviewMessageHandler(mockClineProvider, { type: "requestRouterModels", - values: { provider: "nanogpt", nanoGptApiKey: "unsaved-key" }, + values: { provider: providerIdentifiers.nanogpt, nanoGptApiKey: "unsaved-key" }, }) - expect(mockFlushModels).toHaveBeenCalledWith({ provider: "nanogpt", apiKey: "unsaved-key" }, true) - expect(mockGetModels).toHaveBeenCalledWith({ provider: "nanogpt", apiKey: "unsaved-key" }) + expect(mockFlushModels).toHaveBeenCalledWith( + { provider: providerIdentifiers.nanogpt, apiKey: "unsaved-key" }, + true, + ) + expect(mockGetModels).toHaveBeenCalledWith({ provider: providerIdentifiers.nanogpt, apiKey: "unsaved-key" }) }) it("uses the saved NanoGPT key for manual refresh", async () => { @@ -649,11 +667,14 @@ describe("webviewMessageHandler - requestRouterModels", () => { await webviewMessageHandler(mockClineProvider, { type: "requestRouterModels", - values: { provider: "nanogpt", refresh: true }, + values: { provider: providerIdentifiers.nanogpt, refresh: true }, }) - expect(mockFlushModels).toHaveBeenCalledWith({ provider: "nanogpt", apiKey: "saved-key" }, true) - expect(mockGetModels).toHaveBeenCalledWith({ provider: "nanogpt", apiKey: "saved-key" }) + expect(mockFlushModels).toHaveBeenCalledWith( + { provider: providerIdentifiers.nanogpt, apiKey: "saved-key" }, + true, + ) + expect(mockGetModels).toHaveBeenCalledWith({ provider: providerIdentifiers.nanogpt, apiKey: "saved-key" }) }) it("handles LiteLLM models with values from message when config is missing", async () => { @@ -686,7 +707,7 @@ describe("webviewMessageHandler - requestRouterModels", () => { // Verify LiteLLM was called with values from message expect(mockGetModels).toHaveBeenCalledWith({ - provider: "litellm", + provider: providerIdentifiers.litellm, apiKey: "message-litellm-key", baseUrl: "http://message-url:4000", }) @@ -720,7 +741,7 @@ describe("webviewMessageHandler - requestRouterModels", () => { // Verify LiteLLM was NOT called expect(mockGetModels).not.toHaveBeenCalledWith( expect.objectContaining({ - provider: "litellm", + provider: providerIdentifiers.litellm, }), ) @@ -779,14 +800,14 @@ describe("webviewMessageHandler - requestRouterModels", () => { type: "singleRouterModelFetchResponse", success: false, error: "Requesty API error", - values: { provider: "requesty" }, + values: { provider: providerIdentifiers.requesty }, }) expect(mockClineProvider.postMessageToWebview).toHaveBeenCalledWith({ type: "singleRouterModelFetchResponse", success: false, error: "LiteLLM connection failed", - values: { provider: "litellm" }, + values: { provider: providerIdentifiers.litellm }, }) // Verify final routerModels response includes successful providers and empty objects for failed ones @@ -832,35 +853,35 @@ describe("webviewMessageHandler - requestRouterModels", () => { type: "singleRouterModelFetchResponse", success: false, error: "Structured error message", - values: { provider: "openrouter" }, + values: { provider: providerIdentifiers.openrouter }, }) expect(mockClineProvider.postMessageToWebview).toHaveBeenCalledWith({ type: "singleRouterModelFetchResponse", success: false, error: "Requesty API error", - values: { provider: "requesty" }, + values: { provider: providerIdentifiers.requesty }, }) expect(mockClineProvider.postMessageToWebview).toHaveBeenCalledWith({ type: "singleRouterModelFetchResponse", success: false, error: "Unbound error", - values: { provider: "unbound" }, + values: { provider: providerIdentifiers.unbound }, }) expect(mockClineProvider.postMessageToWebview).toHaveBeenCalledWith({ type: "singleRouterModelFetchResponse", success: false, error: "Vercel AI Gateway error", - values: { provider: "vercel-ai-gateway" }, + values: { provider: providerIdentifiers.vercelAiGateway }, }) expect(mockClineProvider.postMessageToWebview).toHaveBeenCalledWith({ type: "singleRouterModelFetchResponse", success: false, error: "LiteLLM connection failed", - values: { provider: "litellm" }, + values: { provider: providerIdentifiers.litellm }, }) }) @@ -873,7 +894,7 @@ describe("webviewMessageHandler - requestRouterModels", () => { type: "singleRouterModelFetchResponse", success: false, error: "Roo Code Router has been removed. Please select and configure a different provider.", - values: { provider: "roo" }, + values: { provider: retiredProviderIdentifiers.roo }, }) }) @@ -891,7 +912,7 @@ describe("webviewMessageHandler - requestRouterModels", () => { // Verify message values take precedence over saved config (current unsaved field state wins) expect(mockGetModels).toHaveBeenCalledWith({ - provider: "litellm", + provider: providerIdentifiers.litellm, apiKey: "message-key", // From message.values baseUrl: "http://message-url", // From message.values }) @@ -1631,23 +1652,23 @@ describe("zooCodeSignOut", () => { ;(mockClineProvider as any).contextProxy = { ...mockClineProvider.contextProxy, - getProviderSettings: vi.fn().mockReturnValue({ apiProvider: "zoo-gateway" }), + getProviderSettings: vi.fn().mockReturnValue({ apiProvider: providerIdentifiers.zooGateway }), getValues: vi.fn().mockReturnValue({ currentApiConfigName: "Zoo Gateway" }), } ;(mockClineProvider as any).providerSettingsManager = { listConfig: vi.fn().mockResolvedValue([ - { name: "Zoo Gateway", apiProvider: "zoo-gateway" }, - { name: "Backup Zoo", apiProvider: "zoo-gateway" }, + { name: "Zoo Gateway", apiProvider: providerIdentifiers.zooGateway }, + { name: "Backup Zoo", apiProvider: providerIdentifiers.zooGateway }, ]), getProfile: vi .fn() .mockResolvedValueOnce({ - apiProvider: "zoo-gateway", + apiProvider: providerIdentifiers.zooGateway, zooSessionToken: "token-active", zooGatewayModelId: "anthropic/claude-sonnet-4", }) .mockResolvedValueOnce({ - apiProvider: "zoo-gateway", + apiProvider: providerIdentifiers.zooGateway, zooSessionToken: "token-backup", }), saveConfig, @@ -1674,13 +1695,15 @@ describe("zooCodeSignOut", () => { ;(mockClineProvider as any).contextProxy = { ...mockClineProvider.contextProxy, - getProviderSettings: vi.fn().mockReturnValue({ apiProvider: "zoo-gateway" }), + getProviderSettings: vi.fn().mockReturnValue({ apiProvider: providerIdentifiers.zooGateway }), getValues: vi.fn().mockReturnValue({ currentApiConfigName: "Zoo Gateway" }), } ;(mockClineProvider as any).providerSettingsManager = { - listConfig: vi.fn().mockResolvedValue([{ name: "Zoo Gateway", apiProvider: "zoo-gateway" }]), + listConfig: vi + .fn() + .mockResolvedValue([{ name: "Zoo Gateway", apiProvider: providerIdentifiers.zooGateway }]), getProfile: vi.fn().mockResolvedValue({ - apiProvider: "zoo-gateway", + apiProvider: providerIdentifiers.zooGateway, zooGatewayModelId: "anthropic/claude-sonnet-4", }), saveConfig: vi.fn(), diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index e75620e6c1..b481e2ec1d 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -23,6 +23,7 @@ import { checkoutRestorePayloadSchema, getCompletionCheckpoint, providerIdentifiers, + retiredProviderIdentifiers, LmStudioModelsMessageType, OllamaModelsMessageType, OpenAiModelsMessageType, @@ -1412,7 +1413,7 @@ export const webviewMessageHandler = async ( type: RouterModelsMessageType.singleRouterModelFetchResponse, success: false, error: getRouterRemovalMessage(), - values: { provider: "roo" }, + values: { provider: retiredProviderIdentifiers.roo }, }) break } diff --git a/src/eslint-rules/no-raw-provider-identifiers.mjs b/src/eslint-rules/no-raw-provider-identifiers.mjs new file mode 100644 index 0000000000..7520cc6414 --- /dev/null +++ b/src/eslint-rules/no-raw-provider-identifiers.mjs @@ -0,0 +1,122 @@ +import { providerIdentifiers, retiredProviderIdentifiers } from "@roo-code/types/provider-identifiers" + +const providerReplacementsByValue = new Map([ + ...Object.entries(providerIdentifiers).map(([member, value]) => [value, `providerIdentifiers.${member}`]), + ...Object.entries(retiredProviderIdentifiers).map(([member, value]) => [ + value, + `retiredProviderIdentifiers.${member}`, + ]), +]) +const typescriptExpressionWrappers = new Set([ + "TSAsExpression", + "TSNonNullExpression", + "TSSatisfiesExpression", + "TSTypeAssertion", +]) + +function getStaticName(node) { + if (node?.type === "Identifier") { + return node.name + } + + if (node?.type === "MemberExpression") { + if (!node.computed && node.property.type === "Identifier") { + return node.property.name + } + + if (node.computed && node.property.type === "Literal" && typeof node.property.value === "string") { + return node.property.value + } + } + + if (node?.type === "Literal" && typeof node.value === "string") { + return node.value + } + + return undefined +} + +function isProviderLike(node) { + return getStaticName(node)?.toLowerCase().includes("provider") ?? false +} + +function getRawProvider(node) { + while (typescriptExpressionWrappers.has(node?.type)) { + node = node.expression + } + + if (node?.type === "Literal" && typeof node.value === "string") { + const replacement = providerReplacementsByValue.get(node.value) + return replacement ? { replacement, value: node.value } : undefined + } + + if (node?.type === "TemplateLiteral" && node.expressions.length === 0) { + const value = node.quasis[0]?.value.cooked + const replacement = value ? providerReplacementsByValue.get(value) : undefined + return replacement ? { replacement, value } : undefined + } + + return undefined +} + +export const noRawProviderIdentifiers = { + meta: { + type: "problem", + docs: { description: "Require canonical provider identifiers in provider-like contexts" }, + schema: [], + messages: { + useCanonical: + 'Use {{replacement}} instead of the raw provider identifier "{{value}}".', + }, + }, + create(context) { + function reportIfRawProvider(node) { + const provider = getRawProvider(node) + if (provider) { + context.report({ node, messageId: "useCanonical", data: provider }) + } + } + + return { + Property(node) { + if (isProviderLike(node.key)) { + reportIfRawProvider(node.value) + } + }, + PropertyDefinition(node) { + if (isProviderLike(node.key)) { + reportIfRawProvider(node.value) + } + }, + VariableDeclarator(node) { + if (isProviderLike(node.id)) { + reportIfRawProvider(node.init) + } + }, + AssignmentExpression(node) { + if (isProviderLike(node.left)) { + reportIfRawProvider(node.right) + } + }, + BinaryExpression(node) { + if (!["===", "!==", "==", "!="].includes(node.operator)) { + return + } + + if (isProviderLike(node.left)) { + reportIfRawProvider(node.right) + } + if (isProviderLike(node.right)) { + reportIfRawProvider(node.left) + } + }, + SwitchStatement(node) { + if (isProviderLike(node.discriminant)) { + for (const switchCase of node.cases) { + reportIfRawProvider(switchCase.test) + } + } + }, + } + }, +} diff --git a/src/eslint-rules/no-raw-provider-identifiers.test.mjs b/src/eslint-rules/no-raw-provider-identifiers.test.mjs new file mode 100644 index 0000000000..c4efaf90ff --- /dev/null +++ b/src/eslint-rules/no-raw-provider-identifiers.test.mjs @@ -0,0 +1,39 @@ +import { RuleTester } from "eslint" + +import { noRawProviderIdentifiers } from "./no-raw-provider-identifiers.mjs" + +const ruleTester = new RuleTester({ + languageOptions: { + ecmaVersion: 2022, + sourceType: "module", + }, +}) + +ruleTester.run("no-raw-provider-identifiers", noRawProviderIdentifiers, { + valid: [ + "const apiProvider = retiredProviderIdentifiers.roo", + "const provider = retiredProviderIdentifiers.groq", + ], + invalid: [ + { + code: 'const apiProvider = "roo"', + errors: [ + { + message: + 'Use retiredProviderIdentifiers.roo instead of the raw provider identifier "roo".', + type: "Literal", + }, + ], + }, + { + code: "const persistedProvider = `groq`", + errors: [ + { + message: + 'Use retiredProviderIdentifiers.groq instead of the raw provider identifier "groq".', + type: "TemplateLiteral", + }, + ], + }, + ], +}) diff --git a/src/eslint.config.mjs b/src/eslint.config.mjs index 65965eb8d5..27341c6770 100644 --- a/src/eslint.config.mjs +++ b/src/eslint.config.mjs @@ -1,5 +1,7 @@ import { config } from "@roo-code/config-eslint/base" +import { noRawProviderIdentifiers } from "./eslint-rules/no-raw-provider-identifiers.mjs" + /** @type {import("eslint").Linter.Config} */ export default [ ...config, @@ -31,6 +33,22 @@ export default [ "no-undef": "off", }, }, + { + files: ["**/*.ts", "**/*.tsx"], + ignores: [ + "**/fixtures/**", + ], + plugins: { + zoo: { + rules: { + "no-raw-provider-identifiers": noRawProviderIdentifiers, + }, + }, + }, + rules: { + "zoo/no-raw-provider-identifiers": "error", + }, + }, { // Ratchet: enforce no-floating-promises directory by directory. Each // directory is added here once its floating promises are resolved. diff --git a/src/package.json b/src/package.json index 180e3f7e2e..55035dc206 100644 --- a/src/package.json +++ b/src/package.json @@ -529,6 +529,7 @@ }, "devDependencies": { "@ai-sdk/openai-compatible": "2.0.56", + "@typescript-eslint/parser": "8.32.1", "@roo-code/build": "workspace:^", "@roo-code/config-eslint": "workspace:^", "@roo-code/config-typescript": "workspace:^", diff --git a/src/services/code-index/__tests__/config-manager.spec.ts b/src/services/code-index/__tests__/config-manager.spec.ts index 665c83314f..6a496b6809 100644 --- a/src/services/code-index/__tests__/config-manager.spec.ts +++ b/src/services/code-index/__tests__/config-manager.spec.ts @@ -13,6 +13,7 @@ vi.mock("../../../shared/embeddingModels") // Import mocked functions import { getDefaultModelId, getModelDimension, getModelScoreThreshold } from "../../../shared/embeddingModels" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" // Type the mocked functions const mockedGetDefaultModelId = vi.mocked(getDefaultModelId) @@ -102,7 +103,7 @@ describe("CodeIndexConfigManager", () => { expect(result.currentConfig).toEqual({ isConfigured: false, - embedderProvider: "openai", + embedderProvider: providerIdentifiers.openai, modelId: undefined, openAiOptions: { openAiNativeApiKey: "" }, ollamaOptions: { ollamaBaseUrl: "" }, @@ -118,7 +119,7 @@ describe("CodeIndexConfigManager", () => { const mockGlobalState = { codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderBaseUrl: "", codebaseIndexEmbedderModelId: "text-embedding-3-large", } @@ -134,7 +135,7 @@ describe("CodeIndexConfigManager", () => { expect(result.currentConfig).toMatchObject({ isConfigured: true, - embedderProvider: "openai", + embedderProvider: providerIdentifiers.openai, modelId: "text-embedding-3-large", openAiOptions: { openAiNativeApiKey: "test-openai-key" }, ollamaOptions: { ollamaBaseUrl: "" }, @@ -301,7 +302,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-large", }) setupSecretMocks({ @@ -314,7 +315,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "ollama", + codebaseIndexEmbedderProvider: providerIdentifiers.ollama, codebaseIndexEmbedderBaseUrl: "http://ollama.local", codebaseIndexEmbedderModelId: "nomic-embed-text", }) @@ -328,7 +329,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-small", }) setupSecretMocks({ @@ -342,7 +343,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-large", }) @@ -363,7 +364,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-small", }) setupSecretMocks({ @@ -376,7 +377,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-ada-002", }) @@ -396,7 +397,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-small", }) setupSecretMocks({ @@ -414,7 +415,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-small", }) setupSecretMocks({ @@ -439,7 +440,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://old-qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-small", }) setupSecretMocks({ @@ -453,7 +454,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://new-qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-small", }) @@ -466,7 +467,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-small", }) setupSecretMocks({ @@ -480,7 +481,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "unknown-model", }) @@ -493,7 +494,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "ollama", + codebaseIndexEmbedderProvider: providerIdentifiers.ollama, codebaseIndexEmbedderBaseUrl: "http://old-ollama.local", codebaseIndexEmbedderModelId: "nomic-embed-text", }) @@ -504,7 +505,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "ollama", + codebaseIndexEmbedderProvider: providerIdentifiers.ollama, codebaseIndexEmbedderBaseUrl: "http://new-ollama.local", codebaseIndexEmbedderModelId: "nomic-embed-text", }) @@ -753,7 +754,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, }) setupSecretMocks({}) @@ -763,7 +764,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "ollama", + codebaseIndexEmbedderProvider: providerIdentifiers.ollama, codebaseIndexEmbedderBaseUrl: "http://ollama.local", }) @@ -777,7 +778,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, }) setupSecretMocks({}) @@ -787,7 +788,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-large", }) @@ -800,7 +801,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-small", codebaseIndexSearchMinScore: 0.8, // User setting }) @@ -816,7 +817,7 @@ describe("CodeIndexConfigManager", () => { it("should fall back to model-specific threshold when user setting is undefined", async () => { // Mock the model score threshold mockedGetModelScoreThreshold.mockImplementation((provider, modelId) => { - if (provider === "ollama" && modelId === "nomic-embed-code") { + if (provider === providerIdentifiers.ollama && modelId === "nomic-embed-code") { return 0.15 } return undefined @@ -825,7 +826,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "ollama", + codebaseIndexEmbedderProvider: providerIdentifiers.ollama, codebaseIndexEmbedderModelId: "nomic-embed-code", // No codebaseIndexSearchMinScore - user hasn't configured it }) @@ -839,7 +840,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "unknown-model", // Model not in profiles // No codebaseIndexSearchMinScore }) @@ -857,7 +858,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "ollama", + codebaseIndexEmbedderProvider: providerIdentifiers.ollama, codebaseIndexEmbedderModelId: "nomic-embed-code", codebaseIndexSearchMinScore: 0, // User explicitly sets 0 }) @@ -903,7 +904,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, // No modelId specified // No codebaseIndexSearchMinScore }) @@ -920,7 +921,7 @@ describe("CodeIndexConfigManager", () => { it("should handle priority correctly: user > model > default", async () => { // Mock the model score threshold mockedGetModelScoreThreshold.mockImplementation((provider, modelId) => { - if (provider === "ollama" && modelId === "nomic-embed-code") { + if (provider === providerIdentifiers.ollama && modelId === "nomic-embed-code") { return 0.15 } return undefined @@ -930,7 +931,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "ollama", + codebaseIndexEmbedderProvider: providerIdentifiers.ollama, codebaseIndexEmbedderModelId: "nomic-embed-code", // Has 0.15 threshold codebaseIndexSearchMinScore: 0.9, // User overrides }) @@ -942,7 +943,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "ollama", + codebaseIndexEmbedderProvider: providerIdentifiers.ollama, codebaseIndexEmbedderModelId: "nomic-embed-code", // No user setting }) @@ -955,7 +956,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "custom-unknown-model", // No user setting, unknown model }) @@ -972,7 +973,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-small", codebaseIndexSearchMaxResults: 150, // User setting }) @@ -984,7 +985,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-small", // No user setting }) @@ -997,7 +998,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-small", codebaseIndexSearchMaxResults: 10, // Minimum allowed }) @@ -1010,7 +1011,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-small", codebaseIndexSearchMaxResults: 200, // Maximum allowed }) @@ -1028,7 +1029,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-small", }) setupSecretMocks({}) @@ -1039,7 +1040,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-small", codebaseIndexSearchMinScore: 0.5, // Changed unrelated setting }) @@ -1054,7 +1055,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, // Always enabled now codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, }) setupSecretMocks({}) @@ -1076,7 +1077,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, }) setupSecretMocks({ codeIndexOpenAiKey: "", @@ -1103,7 +1104,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-small", }) setupSecretMocks({ @@ -1117,7 +1118,7 @@ describe("CodeIndexConfigManager", () => { const mockPrevConfig = { enabled: true, configured: true, - embedderProvider: "openai" as const, + embedderProvider: providerIdentifiers.openai, modelId: "text-embedding-3-large", // Different model with different dimensions openAiKey: "test-key", ollamaBaseUrl: undefined, @@ -1149,7 +1150,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-small", }) setupSecretMocks({ @@ -1183,7 +1184,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-small", }) setupSecretMocks({ @@ -1216,7 +1217,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, }) setupSecretMocks({ codeIndexOpenAiKey: "test-key", @@ -1231,7 +1232,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "ollama", + codebaseIndexEmbedderProvider: providerIdentifiers.ollama, codebaseIndexEmbedderBaseUrl: "http://ollama.local", }) @@ -1306,7 +1307,7 @@ describe("CodeIndexConfigManager", () => { return { codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "gemini", + codebaseIndexEmbedderProvider: providerIdentifiers.gemini, } } return undefined @@ -1326,7 +1327,7 @@ describe("CodeIndexConfigManager", () => { return { codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "gemini", + codebaseIndexEmbedderProvider: providerIdentifiers.gemini, } } return undefined @@ -1343,7 +1344,7 @@ describe("CodeIndexConfigManager", () => { it("should return false when required values are missing", async () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, }) await configManager.loadConfiguration() @@ -1356,7 +1357,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-large", }) setupSecretMocks({ @@ -1371,7 +1372,7 @@ describe("CodeIndexConfigManager", () => { const config = configManager.getConfig() expect(config).toMatchObject({ isConfigured: true, - embedderProvider: "openai", + embedderProvider: providerIdentifiers.openai, modelId: "text-embedding-3-large", openAiOptions: { openAiNativeApiKey: "test-openai-key" }, ollamaOptions: { ollamaBaseUrl: undefined }, @@ -1410,7 +1411,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-small", }) setupSecretMocks({ @@ -1430,7 +1431,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, // Always enabled now codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-small", }) setupSecretMocks({ @@ -1453,7 +1454,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://qdrant.local", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-small", }) setupSecretMocks({ @@ -1475,7 +1476,7 @@ describe("CodeIndexConfigManager", () => { // Initial state: disabled mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: false, - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexQdrantUrl: "http://localhost:6333", }) mockContextProxy.getSecret.mockReturnValue(undefined) @@ -1487,7 +1488,7 @@ describe("CodeIndexConfigManager", () => { // Update the internal state to enabled with proper configuration mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexQdrantUrl: "http://localhost:6333", }) mockContextProxy.getSecret.mockImplementation((key: string) => { @@ -1505,7 +1506,7 @@ describe("CodeIndexConfigManager", () => { // Initial state: enabled and configured mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexQdrantUrl: "http://localhost:6333", }) mockContextProxy.getSecret.mockImplementation((key: string) => { @@ -1517,7 +1518,7 @@ describe("CodeIndexConfigManager", () => { const previousSnapshot: PreviousConfigSnapshot = { enabled: true, configured: true, - embedderProvider: "openai", + embedderProvider: providerIdentifiers.openai, openAiKey: "test-key", qdrantUrl: "http://localhost:6333", } @@ -1525,7 +1526,7 @@ describe("CodeIndexConfigManager", () => { // Update to disabled mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: false, - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexQdrantUrl: "http://localhost:6333", }) mockContextProxy.getSecret.mockImplementation((key: string) => { @@ -1543,7 +1544,7 @@ describe("CodeIndexConfigManager", () => { // Initial state: enabled and configured mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexQdrantUrl: "http://localhost:6333", }) mockContextProxy.getSecret.mockImplementation((key: string) => { @@ -1572,7 +1573,7 @@ describe("CodeIndexConfigManager", () => { const previousSnapshot: PreviousConfigSnapshot = { enabled: false, configured: false, - embedderProvider: "openai", + embedderProvider: providerIdentifiers.openai, } // Same config, still disabled @@ -1584,7 +1585,7 @@ describe("CodeIndexConfigManager", () => { // Initial state: enabled with openai mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, - codebaseIndexEmbedderProvider: "ollama", + codebaseIndexEmbedderProvider: providerIdentifiers.ollama, codebaseIndexOllamaBaseUrl: "http://localhost:11434", codebaseIndexQdrantUrl: "http://localhost:6333", }) @@ -1594,7 +1595,7 @@ describe("CodeIndexConfigManager", () => { const previousSnapshot: PreviousConfigSnapshot = { enabled: true, configured: true, - embedderProvider: "openai", + embedderProvider: providerIdentifiers.openai, openAiKey: "test-key", qdrantUrl: "http://localhost:6333", } @@ -1607,7 +1608,7 @@ describe("CodeIndexConfigManager", () => { // Initial state: disabled with openai mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: false, - codebaseIndexEmbedderProvider: "ollama", + codebaseIndexEmbedderProvider: providerIdentifiers.ollama, }) mockContextProxy.getSecret.mockReturnValue(undefined) configManager = new CodeIndexConfigManager(mockContextProxy) @@ -1615,7 +1616,7 @@ describe("CodeIndexConfigManager", () => { const previousSnapshot: PreviousConfigSnapshot = { enabled: false, configured: false, - embedderProvider: "openai", + embedderProvider: providerIdentifiers.openai, } // Provider changed but feature is disabled @@ -1635,7 +1636,7 @@ describe("CodeIndexConfigManager", () => { it("should load configuration and return proper structure", async () => { const mockConfigValues = { codebaseIndexEnabled: true, - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-ada-002", codebaseIndexQdrantUrl: "http://localhost:6333", codebaseIndexSearchMinScore: 0.5, @@ -1665,7 +1666,7 @@ describe("CodeIndexConfigManager", () => { // Initial state: disabled mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: false, - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexQdrantUrl: "http://localhost:6333", }) mockContextProxy.getSecret.mockReturnValue(undefined) @@ -1677,7 +1678,7 @@ describe("CodeIndexConfigManager", () => { // Change to enabled with proper configuration mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexQdrantUrl: "http://localhost:6333", }) mockContextProxy.getSecret.mockImplementation((key: string) => { @@ -1694,7 +1695,7 @@ describe("CodeIndexConfigManager", () => { it("should return the current configuration", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexQdrantUrl: "http://localhost:6333", }) mockContextProxy.getSecret.mockImplementation((key: string) => { @@ -1715,7 +1716,7 @@ describe("CodeIndexConfigManager", () => { it("should return true when OpenAI provider is properly configured", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexQdrantUrl: "http://localhost:6333", }) mockContextProxy.getSecret.mockImplementation((key: string) => { @@ -1730,7 +1731,7 @@ describe("CodeIndexConfigManager", () => { it("should return false when OpenAI provider is missing API key", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexQdrantUrl: "http://localhost:6333", }) mockContextProxy.getSecret.mockReturnValue(undefined) @@ -1742,7 +1743,7 @@ describe("CodeIndexConfigManager", () => { it("should return true when Ollama provider is properly configured", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, - codebaseIndexEmbedderProvider: "ollama", + codebaseIndexEmbedderProvider: providerIdentifiers.ollama, codebaseIndexEmbedderBaseUrl: "http://localhost:11434", codebaseIndexQdrantUrl: "http://localhost:6333", }) @@ -1755,7 +1756,7 @@ describe("CodeIndexConfigManager", () => { it("should return false when Qdrant URL is missing", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, }) mockContextProxy.getSecret.mockImplementation((key: string) => { if (key === "codeIndexOpenAiKey") return "test-key" @@ -1801,7 +1802,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-small", codebaseIndexEmbedderModelDimension: 2048, // Custom dimension should be ignored codebaseIndexQdrantUrl: "http://localhost:6333", @@ -1874,7 +1875,7 @@ describe("CodeIndexConfigManager", () => { mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, // No modelId specified codebaseIndexQdrantUrl: "http://localhost:6333", }) @@ -1919,7 +1920,7 @@ describe("CodeIndexConfigManager", () => { it("should correctly handle OpenRouter mistral model dimensions across restarts", async () => { // Mock getModelDimension to return correct dimensions for OpenRouter models mockedGetModelDimension.mockImplementation((provider, modelId) => { - if (provider === "openrouter") { + if (provider === providerIdentifiers.openrouter) { if (modelId === "mistralai/codestral-embed-2505") return 1536 if (modelId === "mistralai/mistral-embed-2312") return 1024 if (modelId === "openai/text-embedding-3-large") return 3072 @@ -1930,7 +1931,7 @@ describe("CodeIndexConfigManager", () => { // Initial configuration with OpenRouter and Mistral model mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, - codebaseIndexEmbedderProvider: "openrouter", + codebaseIndexEmbedderProvider: providerIdentifiers.openrouter, codebaseIndexEmbedderModelId: "mistralai/codestral-embed-2505", codebaseIndexQdrantUrl: "http://localhost:6333", }) @@ -1959,7 +1960,7 @@ describe("CodeIndexConfigManager", () => { it("should not require restart for OpenRouter when same model dimensions are used", async () => { // Mock both models to have same dimension mockedGetModelDimension.mockImplementation((provider, modelId) => { - if (provider === "openrouter") { + if (provider === providerIdentifiers.openrouter) { if (modelId === "mistralai/codestral-embed-2505") return 1536 if (modelId === "openai/text-embedding-3-small") return 1536 } @@ -1969,7 +1970,7 @@ describe("CodeIndexConfigManager", () => { // Initial state with OpenRouter and Mistral model mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, - codebaseIndexEmbedderProvider: "openrouter", + codebaseIndexEmbedderProvider: providerIdentifiers.openrouter, codebaseIndexEmbedderModelId: "mistralai/codestral-embed-2505", codebaseIndexQdrantUrl: "http://localhost:6333", }) @@ -1984,7 +1985,7 @@ describe("CodeIndexConfigManager", () => { // Change to another model with same dimension mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, - codebaseIndexEmbedderProvider: "openrouter", + codebaseIndexEmbedderProvider: providerIdentifiers.openrouter, codebaseIndexEmbedderModelId: "openai/text-embedding-3-small", // Same 1536 dimension codebaseIndexQdrantUrl: "http://localhost:6333", }) @@ -1997,7 +1998,7 @@ describe("CodeIndexConfigManager", () => { it("should require restart for OpenRouter when model dimensions change", async () => { // Mock models with different dimensions mockedGetModelDimension.mockImplementation((provider, modelId) => { - if (provider === "openrouter") { + if (provider === providerIdentifiers.openrouter) { if (modelId === "mistralai/codestral-embed-2505") return 1536 if (modelId === "mistralai/mistral-embed-2312") return 1024 } @@ -2007,7 +2008,7 @@ describe("CodeIndexConfigManager", () => { // Initial state with 1536-dimension model mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, - codebaseIndexEmbedderProvider: "openrouter", + codebaseIndexEmbedderProvider: providerIdentifiers.openrouter, codebaseIndexEmbedderModelId: "mistralai/codestral-embed-2505", codebaseIndexQdrantUrl: "http://localhost:6333", }) @@ -2022,7 +2023,7 @@ describe("CodeIndexConfigManager", () => { // Change to model with different dimension mockContextProxy.getGlobalState.mockReturnValue({ codebaseIndexEnabled: true, - codebaseIndexEmbedderProvider: "openrouter", + codebaseIndexEmbedderProvider: providerIdentifiers.openrouter, codebaseIndexEmbedderModelId: "mistralai/mistral-embed-2312", // Different 1024 dimension codebaseIndexQdrantUrl: "http://localhost:6333", }) diff --git a/src/services/code-index/__tests__/manager.spec.ts b/src/services/code-index/__tests__/manager.spec.ts index edcd8c22f4..627163f900 100644 --- a/src/services/code-index/__tests__/manager.spec.ts +++ b/src/services/code-index/__tests__/manager.spec.ts @@ -2,6 +2,7 @@ import { CodeIndexManager } from "../manager" import { CodeIndexServiceFactory } from "../service-factory" import type { MockedClass } from "vitest" import * as path from "path" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" // Helper: create a mock vscode.Uri from an fsPath function mockUri(fsPath: string, scheme = "file") { @@ -181,7 +182,7 @@ describe("CodeIndexManager - handleSettingsChange regression", () => { isFeatureEnabled: true, getConfig: vi.fn().mockReturnValue({ isConfigured: true, - embedderProvider: "openai", + embedderProvider: providerIdentifiers.openai, modelId: "text-embedding-3-small", openAiOptions: { openAiNativeApiKey: "test-key" }, qdrantUrl: "http://localhost:6333", @@ -250,7 +251,7 @@ describe("CodeIndexManager - handleSettingsChange regression", () => { isFeatureEnabled: true, getConfig: vi.fn().mockReturnValue({ isConfigured: true, - embedderProvider: "openai", + embedderProvider: providerIdentifiers.openai, modelId: "text-embedding-3-small", openAiOptions: { openAiNativeApiKey: "test-key" }, qdrantUrl: "http://localhost:6333", @@ -380,7 +381,7 @@ describe("CodeIndexManager - handleSettingsChange regression", () => { isFeatureEnabled: true, getConfig: vitest.fn().mockReturnValue({ isConfigured: true, - embedderProvider: "openai", + embedderProvider: providerIdentifiers.openai, modelId: "text-embedding-3-small", openAiOptions: { openAiNativeApiKey: "test-key" }, qdrantUrl: "http://localhost:6333", @@ -477,7 +478,7 @@ describe("CodeIndexManager - handleSettingsChange regression", () => { isFeatureEnabled: true, getConfig: vi.fn().mockReturnValue({ isConfigured: true, - embedderProvider: "openai", + embedderProvider: providerIdentifiers.openai, modelId: "text-embedding-3-small", openAiOptions: { openAiNativeApiKey: "test-key" }, qdrantUrl: "http://localhost:6333", @@ -584,7 +585,7 @@ describe("CodeIndexManager - handleSettingsChange regression", () => { getGlobalState: vi.fn().mockReturnValue({ codebaseIndexEnabled: true, codebaseIndexQdrantUrl: "http://localhost:6333", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderModelId: "text-embedding-3-small", codebaseIndexEmbedderModelDimension: 1536, codebaseIndexSearchMaxResults: 10, diff --git a/src/services/code-index/__tests__/service-factory.spec.ts b/src/services/code-index/__tests__/service-factory.spec.ts index aafc198d85..aaf248d47a 100644 --- a/src/services/code-index/__tests__/service-factory.spec.ts +++ b/src/services/code-index/__tests__/service-factory.spec.ts @@ -38,6 +38,7 @@ const MockedQdrantVectorStore = QdrantVectorStore as MockedClass const mockGetModelDimension = getModelDimension as MockedFunction @@ -63,7 +64,7 @@ describe("CodeIndexServiceFactory", () => { // Arrange const testModelId = "text-embedding-3-large" const testConfig = { - embedderProvider: "openai", + embedderProvider: providerIdentifiers.openai, modelId: testModelId, openAiOptions: { openAiNativeApiKey: "test-api-key", @@ -85,7 +86,7 @@ describe("CodeIndexServiceFactory", () => { // Arrange const testModelId = "nomic-embed-text:latest" const testConfig = { - embedderProvider: "ollama", + embedderProvider: providerIdentifiers.ollama, modelId: testModelId, ollamaOptions: { ollamaBaseUrl: "http://localhost:11434", @@ -106,7 +107,7 @@ describe("CodeIndexServiceFactory", () => { it("should handle undefined model ID for OpenAI embedder", () => { // Arrange const testConfig = { - embedderProvider: "openai", + embedderProvider: providerIdentifiers.openai, modelId: undefined, openAiOptions: { openAiNativeApiKey: "test-api-key", @@ -127,7 +128,7 @@ describe("CodeIndexServiceFactory", () => { it("should handle undefined model ID for Ollama embedder", () => { // Arrange const testConfig = { - embedderProvider: "ollama", + embedderProvider: providerIdentifiers.ollama, modelId: undefined, ollamaOptions: { ollamaBaseUrl: "http://localhost:11434", @@ -148,7 +149,7 @@ describe("CodeIndexServiceFactory", () => { it("should throw error when OpenAI API key is missing", () => { // Arrange const testConfig = { - embedderProvider: "openai", + embedderProvider: providerIdentifiers.openai, modelId: "text-embedding-3-large", openAiOptions: { openAiNativeApiKey: undefined, @@ -163,7 +164,7 @@ describe("CodeIndexServiceFactory", () => { it("should throw error when Ollama base URL is missing", () => { // Arrange const testConfig = { - embedderProvider: "ollama", + embedderProvider: providerIdentifiers.ollama, modelId: "nomic-embed-text:latest", ollamaOptions: { ollamaBaseUrl: undefined, @@ -270,7 +271,7 @@ describe("CodeIndexServiceFactory", () => { it("should create GeminiEmbedder with default model when no modelId specified", () => { // Arrange const testConfig = { - embedderProvider: "gemini", + embedderProvider: providerIdentifiers.gemini, geminiOptions: { apiKey: "test-gemini-api-key", }, @@ -287,7 +288,7 @@ describe("CodeIndexServiceFactory", () => { it("should create GeminiEmbedder with specified modelId", () => { // Arrange const testConfig = { - embedderProvider: "gemini", + embedderProvider: providerIdentifiers.gemini, modelId: "gemini-embedding-001", geminiOptions: { apiKey: "test-gemini-api-key", @@ -306,7 +307,7 @@ describe("CodeIndexServiceFactory", () => { // Arrange - service-factory passes the config modelId directly; // GeminiEmbedder handles the migration internally const testConfig = { - embedderProvider: "gemini", + embedderProvider: providerIdentifiers.gemini, modelId: "text-embedding-004", geminiOptions: { apiKey: "test-gemini-api-key", @@ -324,7 +325,7 @@ describe("CodeIndexServiceFactory", () => { it("should throw error when Gemini API key is missing", () => { // Arrange const testConfig = { - embedderProvider: "gemini", + embedderProvider: providerIdentifiers.gemini, geminiOptions: { apiKey: undefined, }, @@ -338,7 +339,7 @@ describe("CodeIndexServiceFactory", () => { it("should throw error when Gemini options are missing", () => { // Arrange const testConfig = { - embedderProvider: "gemini", + embedderProvider: providerIdentifiers.gemini, geminiOptions: undefined, } mockConfigManager.getConfig.mockReturnValue(testConfig as any) @@ -381,7 +382,7 @@ describe("CodeIndexServiceFactory", () => { // Arrange const testModelId = "text-embedding-3-large" const testConfig = { - embedderProvider: "openai", + embedderProvider: providerIdentifiers.openai, modelId: testModelId, qdrantUrl: "http://localhost:6333", qdrantApiKey: "test-key", @@ -406,7 +407,7 @@ describe("CodeIndexServiceFactory", () => { // Arrange const testModelId = "nomic-embed-text:latest" const testConfig = { - embedderProvider: "ollama", + embedderProvider: providerIdentifiers.ollama, modelId: testModelId, qdrantUrl: "http://localhost:6333", qdrantApiKey: "test-key", @@ -592,7 +593,7 @@ describe("CodeIndexServiceFactory", () => { it("should use model-specific dimension for Gemini provider", () => { // Arrange const testConfig = { - embedderProvider: "gemini", + embedderProvider: providerIdentifiers.gemini, modelId: "gemini-embedding-001", qdrantUrl: "http://localhost:6333", qdrantApiKey: "test-key", @@ -616,7 +617,7 @@ describe("CodeIndexServiceFactory", () => { it("should use default model dimension for Gemini when modelId not specified", () => { // Arrange const testConfig = { - embedderProvider: "gemini", + embedderProvider: providerIdentifiers.gemini, qdrantUrl: "http://localhost:6333", qdrantApiKey: "test-key", } @@ -641,7 +642,7 @@ describe("CodeIndexServiceFactory", () => { it("should use default model when config.modelId is undefined", () => { // Arrange const testConfig = { - embedderProvider: "openai", + embedderProvider: providerIdentifiers.openai, modelId: undefined, qdrantUrl: "http://localhost:6333", qdrantApiKey: "test-key", @@ -665,7 +666,7 @@ describe("CodeIndexServiceFactory", () => { it("should throw error when vector dimension cannot be determined", () => { // Arrange const testConfig = { - embedderProvider: "openai", + embedderProvider: providerIdentifiers.openai, modelId: "unknown-model", qdrantUrl: "http://localhost:6333", qdrantApiKey: "test-key", @@ -680,7 +681,7 @@ describe("CodeIndexServiceFactory", () => { it("should throw error when Qdrant URL is missing", () => { // Arrange const testConfig = { - embedderProvider: "openai", + embedderProvider: providerIdentifiers.openai, modelId: "text-embedding-3-small", qdrantUrl: undefined, qdrantApiKey: "test-key", @@ -716,7 +717,7 @@ describe("CodeIndexServiceFactory", () => { it("should validate OpenAI embedder successfully", async () => { // Arrange const testConfig = { - embedderProvider: "openai", + embedderProvider: providerIdentifiers.openai, modelId: "text-embedding-3-small", openAiOptions: { openAiNativeApiKey: "test-api-key", @@ -740,7 +741,7 @@ describe("CodeIndexServiceFactory", () => { it("should return validation error from OpenAI embedder", async () => { // Arrange const testConfig = { - embedderProvider: "openai", + embedderProvider: providerIdentifiers.openai, modelId: "text-embedding-3-small", openAiOptions: { openAiNativeApiKey: "invalid-key", @@ -769,7 +770,7 @@ describe("CodeIndexServiceFactory", () => { it("should validate Ollama embedder successfully", async () => { // Arrange const testConfig = { - embedderProvider: "ollama", + embedderProvider: providerIdentifiers.ollama, modelId: "nomic-embed-text", ollamaOptions: { ollamaBaseUrl: "http://localhost:11434", @@ -818,7 +819,7 @@ describe("CodeIndexServiceFactory", () => { it("should validate Gemini embedder successfully", async () => { // Arrange const testConfig = { - embedderProvider: "gemini", + embedderProvider: providerIdentifiers.gemini, geminiOptions: { apiKey: "test-gemini-api-key", }, @@ -841,7 +842,7 @@ describe("CodeIndexServiceFactory", () => { it("should handle validation exceptions", async () => { // Arrange const testConfig = { - embedderProvider: "openai", + embedderProvider: providerIdentifiers.openai, modelId: "text-embedding-3-small", openAiOptions: { openAiNativeApiKey: "test-api-key", @@ -869,7 +870,7 @@ describe("CodeIndexServiceFactory", () => { it("should return error for invalid embedder configuration", async () => { // Arrange const testConfig = { - embedderProvider: "openai", + embedderProvider: providerIdentifiers.openai, modelId: "text-embedding-3-small", openAiOptions: { openAiNativeApiKey: undefined, // Missing API key diff --git a/src/services/code-index/config-manager.ts b/src/services/code-index/config-manager.ts index abac552561..dc6f72d34a 100644 --- a/src/services/code-index/config-manager.ts +++ b/src/services/code-index/config-manager.ts @@ -4,6 +4,7 @@ import { EmbedderProvider } from "./interfaces/manager" import { CodeIndexConfig, PreviousConfigSnapshot } from "./interfaces/config" import { DEFAULT_SEARCH_MIN_SCORE, DEFAULT_MAX_SEARCH_RESULTS } from "./constants" import { getDefaultModelId, getModelDimension, getModelScoreThreshold } from "../../shared/embeddingModels" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" /** * Manages configuration state and validation for the code indexing feature. @@ -11,7 +12,7 @@ import { getDefaultModelId, getModelDimension, getModelScoreThreshold } from ".. */ export class CodeIndexConfigManager { private codebaseIndexEnabled: boolean = false - private embedderProvider: EmbedderProvider = "openai" + private embedderProvider: EmbedderProvider = providerIdentifiers.openai private modelId?: string private modelDimension?: number private openAiOptions?: ApiHandlerOptions @@ -48,7 +49,7 @@ export class CodeIndexConfigManager { const codebaseIndexConfig = this.contextProxy?.getGlobalState("codebaseIndexConfig") ?? { codebaseIndexEnabled: false, codebaseIndexQdrantUrl: "http://localhost:6333", - codebaseIndexEmbedderProvider: "openai", + codebaseIndexEmbedderProvider: providerIdentifiers.openai, codebaseIndexEmbedderBaseUrl: "", codebaseIndexEmbedderModelId: "", codebaseIndexSearchMinScore: undefined, @@ -106,24 +107,24 @@ export class CodeIndexConfigManager { this.openAiOptions = { openAiNativeApiKey: openAiKey } // Set embedder provider with support for openai-compatible - if (codebaseIndexEmbedderProvider === "ollama") { - this.embedderProvider = "ollama" + if (codebaseIndexEmbedderProvider === providerIdentifiers.ollama) { + this.embedderProvider = providerIdentifiers.ollama } else if (codebaseIndexEmbedderProvider === "openai-compatible") { this.embedderProvider = "openai-compatible" - } else if (codebaseIndexEmbedderProvider === "gemini") { - this.embedderProvider = "gemini" - } else if (codebaseIndexEmbedderProvider === "mistral") { - this.embedderProvider = "mistral" - } else if (codebaseIndexEmbedderProvider === "vercel-ai-gateway") { - this.embedderProvider = "vercel-ai-gateway" + } else if (codebaseIndexEmbedderProvider === providerIdentifiers.gemini) { + this.embedderProvider = providerIdentifiers.gemini + } else if (codebaseIndexEmbedderProvider === providerIdentifiers.mistral) { + this.embedderProvider = providerIdentifiers.mistral + } else if (codebaseIndexEmbedderProvider === providerIdentifiers.vercelAiGateway) { + this.embedderProvider = providerIdentifiers.vercelAiGateway } else if ((codebaseIndexEmbedderProvider as string) === "bedrock") { - this.embedderProvider = "bedrock" - } else if (codebaseIndexEmbedderProvider === "openrouter") { - this.embedderProvider = "openrouter" + this.embedderProvider = providerIdentifiers.bedrock + } else if (codebaseIndexEmbedderProvider === providerIdentifiers.openrouter) { + this.embedderProvider = providerIdentifiers.openrouter } else if (codebaseIndexEmbedderProvider === "semble") { this.embedderProvider = "semble" } else { - this.embedderProvider = "openai" + this.embedderProvider = providerIdentifiers.openai } this.modelId = codebaseIndexEmbedderModelId || undefined @@ -238,11 +239,11 @@ export class CodeIndexConfigManager { return true } - if (this.embedderProvider === "openai") { + if (this.embedderProvider === providerIdentifiers.openai) { const openAiKey = this.openAiOptions?.openAiNativeApiKey const qdrantUrl = this.qdrantUrl return !!(openAiKey && qdrantUrl) - } else if (this.embedderProvider === "ollama") { + } else if (this.embedderProvider === providerIdentifiers.ollama) { // Ollama model ID has a default, so only base URL is strictly required for config const ollamaBaseUrl = this.ollamaOptions?.ollamaBaseUrl const qdrantUrl = this.qdrantUrl @@ -253,28 +254,28 @@ export class CodeIndexConfigManager { const qdrantUrl = this.qdrantUrl const isConfigured = !!(baseUrl && apiKey && qdrantUrl) return isConfigured - } else if (this.embedderProvider === "gemini") { + } else if (this.embedderProvider === providerIdentifiers.gemini) { const apiKey = this.geminiOptions?.apiKey const qdrantUrl = this.qdrantUrl const isConfigured = !!(apiKey && qdrantUrl) return isConfigured - } else if (this.embedderProvider === "mistral") { + } else if (this.embedderProvider === providerIdentifiers.mistral) { const apiKey = this.mistralOptions?.apiKey const qdrantUrl = this.qdrantUrl const isConfigured = !!(apiKey && qdrantUrl) return isConfigured - } else if (this.embedderProvider === "vercel-ai-gateway") { + } else if (this.embedderProvider === providerIdentifiers.vercelAiGateway) { const apiKey = this.vercelAiGatewayOptions?.apiKey const qdrantUrl = this.qdrantUrl const isConfigured = !!(apiKey && qdrantUrl) return isConfigured - } else if (this.embedderProvider === "bedrock") { + } else if (this.embedderProvider === providerIdentifiers.bedrock) { // Only region is required for Bedrock (profile is optional) const region = this.bedrockOptions?.region const qdrantUrl = this.qdrantUrl const isConfigured = !!(region && qdrantUrl) return isConfigured - } else if (this.embedderProvider === "openrouter") { + } else if (this.embedderProvider === providerIdentifiers.openrouter) { const apiKey = this.openRouterOptions?.apiKey const qdrantUrl = this.qdrantUrl const isConfigured = !!(apiKey && qdrantUrl) diff --git a/src/services/code-index/embedders/__tests__/openrouter.spec.ts b/src/services/code-index/embedders/__tests__/openrouter.spec.ts index 088e9c7185..3f8d526e19 100644 --- a/src/services/code-index/embedders/__tests__/openrouter.spec.ts +++ b/src/services/code-index/embedders/__tests__/openrouter.spec.ts @@ -4,6 +4,7 @@ import { OpenAI } from "openai" import { OpenRouterEmbedder, OPENROUTER_DEFAULT_PROVIDER_NAME } from "../openrouter" import { getModelDimension, getDefaultModelId } from "../../../../shared/embeddingModels" import { clearAllMocks, restoreGlobals } from "../../../../test-utils/reset" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" // Mock the OpenAI SDK vi.mock("openai") @@ -340,7 +341,7 @@ describe("OpenRouterEmbedder", () => { }) it("should validate configuration with specificProvider", async () => { - const specificProvider = "openai" + const specificProvider = providerIdentifiers.openai const embedderWithProvider = new OpenRouterEmbedder(mockApiKey, undefined, undefined, specificProvider) const testEmbedding = new Float32Array([0.25, 0.5]) diff --git a/src/services/code-index/service-factory.ts b/src/services/code-index/service-factory.ts index 96b6d80c90..beab32ad02 100644 --- a/src/services/code-index/service-factory.ts +++ b/src/services/code-index/service-factory.ts @@ -26,6 +26,7 @@ import { ICodeParser, IEmbedder, IFileWatcher, IVectorStore } from "./interfaces import { CodeIndexConfigManager } from "./config-manager" import { CacheManager } from "./cache-manager" import { BATCH_SEGMENT_THRESHOLD } from "./constants" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" /** * Factory class responsible for creating and configuring code indexing service dependencies. @@ -55,7 +56,7 @@ export class CodeIndexServiceFactory { ) } - if (provider === "openai") { + if (provider === providerIdentifiers.openai) { const apiKey = config.openAiOptions?.openAiNativeApiKey if (!apiKey) { @@ -65,7 +66,7 @@ export class CodeIndexServiceFactory { ...config.openAiOptions, openAiEmbeddingModelId: config.modelId, }) - } else if (provider === "ollama") { + } else if (provider === providerIdentifiers.ollama) { if (!config.ollamaOptions?.ollamaBaseUrl) { throw new Error(t("embeddings:serviceFactory.ollamaConfigMissing")) } @@ -82,28 +83,28 @@ export class CodeIndexServiceFactory { config.openAiCompatibleOptions.apiKey, config.modelId, ) - } else if (provider === "gemini") { + } else if (provider === providerIdentifiers.gemini) { if (!config.geminiOptions?.apiKey) { throw new Error(t("embeddings:serviceFactory.geminiConfigMissing")) } return new GeminiEmbedder(config.geminiOptions.apiKey, config.modelId) - } else if (provider === "mistral") { + } else if (provider === providerIdentifiers.mistral) { if (!config.mistralOptions?.apiKey) { throw new Error(t("embeddings:serviceFactory.mistralConfigMissing")) } return new MistralEmbedder(config.mistralOptions.apiKey, config.modelId) - } else if (provider === "vercel-ai-gateway") { + } else if (provider === providerIdentifiers.vercelAiGateway) { if (!config.vercelAiGatewayOptions?.apiKey) { throw new Error(t("embeddings:serviceFactory.vercelAiGatewayConfigMissing")) } return new VercelAiGatewayEmbedder(config.vercelAiGatewayOptions.apiKey, config.modelId) - } else if (provider === "bedrock") { + } else if (provider === providerIdentifiers.bedrock) { // Only region is required for Bedrock (profile is optional) if (!config.bedrockOptions?.region) { throw new Error(t("embeddings:serviceFactory.bedrockConfigMissing")) } return new BedrockEmbedder(config.bedrockOptions.region, config.bedrockOptions.profile, config.modelId) - } else if (provider === "openrouter") { + } else if (provider === providerIdentifiers.openrouter) { if (!config.openRouterOptions?.apiKey) { throw new Error(t("embeddings:serviceFactory.openRouterConfigMissing")) } diff --git a/src/shared/__tests__/ProfileValidator.spec.ts b/src/shared/__tests__/ProfileValidator.spec.ts index ace96c9fd0..865fa5cf51 100644 --- a/src/shared/__tests__/ProfileValidator.spec.ts +++ b/src/shared/__tests__/ProfileValidator.spec.ts @@ -79,7 +79,7 @@ describe("ProfileValidator", () => { providers: {}, } const profile: ProviderSettings = { - apiProvider: "openai", + apiProvider: providerIdentifiers.openai, openAiModelId: "gpt-4", } @@ -107,7 +107,7 @@ describe("ProfileValidator", () => { }, } const profile: ProviderSettings = { - apiProvider: "openai", + apiProvider: providerIdentifiers.openai, openAiModelId: "gpt-4", } @@ -122,7 +122,7 @@ describe("ProfileValidator", () => { }, } const profile: ProviderSettings = { - apiProvider: "openai", + apiProvider: providerIdentifiers.openai, openAiModelId: "any-model-id", } @@ -137,7 +137,7 @@ describe("ProfileValidator", () => { }, } const profile: ProviderSettings = { - apiProvider: "openai", + apiProvider: providerIdentifiers.openai, } expect(ProfileValidator.isProfileAllowed(profile, allowList)).toBe(false) @@ -151,7 +151,7 @@ describe("ProfileValidator", () => { }, } const profile: ProviderSettings = { - apiProvider: "openai", + apiProvider: providerIdentifiers.openai, openAiModelId: "gpt-4", } @@ -166,7 +166,7 @@ describe("ProfileValidator", () => { }, } const profile: ProviderSettings = { - apiProvider: "openai", + apiProvider: providerIdentifiers.openai, openAiModelId: "gpt-4", } @@ -181,7 +181,7 @@ describe("ProfileValidator", () => { }, } const profile: ProviderSettings = { - apiProvider: "openai", + apiProvider: providerIdentifiers.openai, openAiModelId: "gpt-4", } @@ -196,7 +196,7 @@ describe("ProfileValidator", () => { }, } const profile: ProviderSettings = { - apiProvider: "openai", + apiProvider: providerIdentifiers.openai, openAiModelId: "gpt-4", } @@ -211,7 +211,7 @@ describe("ProfileValidator", () => { }, } const profile: ProviderSettings = { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, apiModelId: "claude-3-opus", } @@ -226,7 +226,7 @@ describe("ProfileValidator", () => { }, } const profile: ProviderSettings = { - apiProvider: "ollama", + apiProvider: providerIdentifiers.ollama, ollamaModelId: "llama3", } @@ -304,7 +304,7 @@ describe("ProfileValidator", () => { }, } const profile: ProviderSettings = { - apiProvider: "lmstudio", + apiProvider: providerIdentifiers.lmstudio, lmStudioModelId: "lmstudio-model", } @@ -319,7 +319,7 @@ describe("ProfileValidator", () => { }, } const profile: ProviderSettings = { - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterModelId: "openrouter-model", } @@ -334,7 +334,7 @@ describe("ProfileValidator", () => { }, } const profile: ProviderSettings = { - apiProvider: "requesty", + apiProvider: providerIdentifiers.requesty, requestyModelId: "requesty-model", } @@ -361,7 +361,7 @@ describe("ProfileValidator", () => { providers: {}, } const profile: ProviderSettings = { - apiProvider: "openai", + apiProvider: providerIdentifiers.openai, openAiModelId: "gpt-4", } diff --git a/src/shared/__tests__/api.spec.ts b/src/shared/__tests__/api.spec.ts index 0363c27cdf..0f8b16f6cf 100644 --- a/src/shared/__tests__/api.spec.ts +++ b/src/shared/__tests__/api.spec.ts @@ -1,6 +1,7 @@ import { type ModelInfo, type ProviderSettings, ANTHROPIC_DEFAULT_MAX_TOKENS } from "@roo-code/types" import { getModelMaxOutputTokens, shouldUseReasoningBudget, shouldUseReasoningEffort } from "../api" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" describe("getModelMaxOutputTokens", () => { const mockModel: ModelInfo = { @@ -11,7 +12,7 @@ describe("getModelMaxOutputTokens", () => { test("should return model maxTokens when maxTokens is within 20% of context window", () => { const settings: ProviderSettings = { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, } // mockModel has maxTokens: 8192 and contextWindow: 200000 @@ -33,7 +34,7 @@ describe("getModelMaxOutputTokens", () => { } const settings: ProviderSettings = { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, enableReasoningEffort: true, modelMaxTokens: 32000, } @@ -72,7 +73,7 @@ describe("getModelMaxOutputTokens", () => { } const settings: ProviderSettings = { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, enableReasoningEffort: false, // Not using reasoning } @@ -93,7 +94,7 @@ describe("getModelMaxOutputTokens", () => { getModelMaxOutputTokens({ modelId: "claude-opus-4-7", model, - settings: { apiProvider: "anthropic", enableReasoningEffort: false }, + settings: { apiProvider: providerIdentifiers.anthropic, enableReasoningEffort: false }, }), ).toBe(ANTHROPIC_DEFAULT_MAX_TOKENS) @@ -101,7 +102,11 @@ describe("getModelMaxOutputTokens", () => { getModelMaxOutputTokens({ modelId: "claude-opus-4-7", model, - settings: { apiProvider: "anthropic", enableReasoningEffort: true, modelMaxTokens: 32_768 }, + settings: { + apiProvider: providerIdentifiers.anthropic, + enableReasoningEffort: true, + modelMaxTokens: 32_768, + }, }), ).toBe(32_768) }) @@ -122,7 +127,7 @@ describe("getModelMaxOutputTokens", () => { getModelMaxOutputTokens({ modelId: "claude-opus-4-8", model, - settings: { apiProvider: "anthropic", enableReasoningEffort: false }, + settings: { apiProvider: providerIdentifiers.anthropic, enableReasoningEffort: false }, }), ).toBe(ANTHROPIC_DEFAULT_MAX_TOKENS) @@ -130,7 +135,11 @@ describe("getModelMaxOutputTokens", () => { getModelMaxOutputTokens({ modelId: "claude-opus-4-8", model, - settings: { apiProvider: "anthropic", enableReasoningEffort: true, modelMaxTokens: 32_768 }, + settings: { + apiProvider: providerIdentifiers.anthropic, + enableReasoningEffort: true, + modelMaxTokens: 32_768, + }, }), ).toBe(32_768) }) @@ -149,7 +158,7 @@ describe("getModelMaxOutputTokens", () => { getModelMaxOutputTokens({ modelId: "claude-fable-5", model, - settings: { apiProvider: "anthropic", enableReasoningEffort: false }, + settings: { apiProvider: providerIdentifiers.anthropic, enableReasoningEffort: false }, }), ).toBe(ANTHROPIC_DEFAULT_MAX_TOKENS) @@ -157,7 +166,11 @@ describe("getModelMaxOutputTokens", () => { getModelMaxOutputTokens({ modelId: "claude-fable-5", model, - settings: { apiProvider: "anthropic", enableReasoningEffort: true, modelMaxTokens: 32_768 }, + settings: { + apiProvider: providerIdentifiers.anthropic, + enableReasoningEffort: true, + modelMaxTokens: 32_768, + }, }), ).toBe(32_768) }) @@ -176,7 +189,7 @@ describe("getModelMaxOutputTokens", () => { getModelMaxOutputTokens({ modelId: "claude-sonnet-5", model, - settings: { apiProvider: "anthropic", enableReasoningEffort: false }, + settings: { apiProvider: providerIdentifiers.anthropic, enableReasoningEffort: false }, }), ).toBe(ANTHROPIC_DEFAULT_MAX_TOKENS) @@ -184,7 +197,11 @@ describe("getModelMaxOutputTokens", () => { getModelMaxOutputTokens({ modelId: "claude-sonnet-5", model, - settings: { apiProvider: "anthropic", enableReasoningEffort: true, modelMaxTokens: 32_768 }, + settings: { + apiProvider: providerIdentifiers.anthropic, + enableReasoningEffort: true, + modelMaxTokens: 32_768, + }, }), ).toBe(32_768) }) @@ -203,7 +220,7 @@ describe("getModelMaxOutputTokens", () => { getModelMaxOutputTokens({ modelId: "claude-opus-5", model, - settings: { apiProvider: "anthropic", enableReasoningEffort: false }, + settings: { apiProvider: providerIdentifiers.anthropic, enableReasoningEffort: false }, }), ).toBe(ANTHROPIC_DEFAULT_MAX_TOKENS) @@ -211,7 +228,11 @@ describe("getModelMaxOutputTokens", () => { getModelMaxOutputTokens({ modelId: "claude-opus-5", model, - settings: { apiProvider: "anthropic", enableReasoningEffort: true, modelMaxTokens: 32_768 }, + settings: { + apiProvider: providerIdentifiers.anthropic, + enableReasoningEffort: true, + modelMaxTokens: 32_768, + }, }), ).toBe(32_768) }) @@ -226,7 +247,7 @@ describe("getModelMaxOutputTokens", () => { } const settings: ProviderSettings = { - apiProvider: "gemini", + apiProvider: providerIdentifiers.gemini, enableReasoningEffort: false, // Not using reasoning } @@ -242,7 +263,7 @@ describe("getModelMaxOutputTokens", () => { } const settings: ProviderSettings = { - apiProvider: "openai", + apiProvider: providerIdentifiers.openai, } const result = getModelMaxOutputTokens({ @@ -263,7 +284,7 @@ describe("getModelMaxOutputTokens", () => { } const settings: ProviderSettings = { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, } const result = getModelMaxOutputTokens({ @@ -283,7 +304,7 @@ describe("getModelMaxOutputTokens", () => { } const settings: ProviderSettings = { - apiProvider: "openai", + apiProvider: providerIdentifiers.openai, } const result = getModelMaxOutputTokens({ @@ -303,7 +324,7 @@ describe("getModelMaxOutputTokens", () => { } const settings: ProviderSettings = { - apiProvider: "openai", + apiProvider: providerIdentifiers.openai, } // Test various GPT-5 model IDs @@ -330,7 +351,7 @@ describe("getModelMaxOutputTokens", () => { } const settings: ProviderSettings = { - apiProvider: "zai", + apiProvider: providerIdentifiers.zai, modelMaxTokens: 64_000, // user override, above 20% of the context window (40k) } @@ -348,7 +369,7 @@ describe("getModelMaxOutputTokens", () => { } const settings: ProviderSettings = { - apiProvider: "zai", + apiProvider: providerIdentifiers.zai, modelMaxTokens: 999_999, // beyond the model ceiling } @@ -364,7 +385,7 @@ describe("getModelMaxOutputTokens", () => { } const settings: ProviderSettings = { - apiProvider: "openai", + apiProvider: providerIdentifiers.openai, } // Test non-GPT-5 model IDs @@ -411,7 +432,7 @@ describe("getModelMaxOutputTokens", () => { const result = getModelMaxOutputTokens({ modelId: "gpt-5-turbo", model, - settings: { apiProvider: "openai" }, + settings: { apiProvider: providerIdentifiers.openai }, format: "openai", }) @@ -430,7 +451,7 @@ describe("getModelMaxOutputTokens", () => { const result = getModelMaxOutputTokens({ modelId: "glm-5.1", model, - settings: { apiProvider: "zai" }, + settings: { apiProvider: providerIdentifiers.zai }, format: "openai", }) @@ -447,7 +468,7 @@ describe("getModelMaxOutputTokens", () => { const result = getModelMaxOutputTokens({ modelId: "glm-5.1", model, - settings: { apiProvider: "openai" }, + settings: { apiProvider: providerIdentifiers.openai }, format: "openai", }) diff --git a/src/shared/__tests__/checkExistApiConfig.spec.ts b/src/shared/__tests__/checkExistApiConfig.spec.ts index ab92beea36..570e5c8223 100644 --- a/src/shared/__tests__/checkExistApiConfig.spec.ts +++ b/src/shared/__tests__/checkExistApiConfig.spec.ts @@ -1,6 +1,6 @@ // npx vitest run src/shared/__tests__/checkExistApiConfig.spec.ts -import { providerIdentifiers, type ProviderSettings } from "@roo-code/types" +import { providerIdentifiers, retiredProviderIdentifiers, type ProviderSettings } from "@roo-code/types" import { checkExistKey } from "../checkExistApiConfig" @@ -61,7 +61,7 @@ describe("checkExistKey", () => { it("should return true for fake-ai provider without API key", () => { const config: ProviderSettings = { - apiProvider: "fake-ai", + apiProvider: providerIdentifiers.fakeAi, } expect(checkExistKey(config)).toBe(true) }) @@ -86,14 +86,14 @@ describe("checkExistKey", () => { it("should return false for roo provider without API key", () => { const config: ProviderSettings = { - apiProvider: "roo", + apiProvider: retiredProviderIdentifiers.roo, } expect(checkExistKey(config)).toBe(false) }) it("should return true for kimi-code provider with OAuth auth method", () => { const config: ProviderSettings = { - apiProvider: "kimi-code", + apiProvider: providerIdentifiers.kimiCode, kimiCodeAuthMethod: "oauth", } expect(checkExistKey(config)).toBe(true) @@ -105,14 +105,14 @@ describe("checkExistKey", () => { it("should return true for kimi-code provider without auth method (defaults to OAuth)", () => { const config: ProviderSettings = { - apiProvider: "kimi-code", + apiProvider: providerIdentifiers.kimiCode, } expect(checkExistKey(config)).toBe(true) }) it("should return true for kimi-code provider with api-key auth and key present", () => { const config: ProviderSettings = { - apiProvider: "kimi-code", + apiProvider: providerIdentifiers.kimiCode, kimiCodeAuthMethod: "api-key", kimiCodeApiKey: "test-key", } @@ -121,7 +121,7 @@ describe("checkExistKey", () => { it("should return false for kimi-code provider with api-key auth but no key", () => { const config: ProviderSettings = { - apiProvider: "kimi-code", + apiProvider: providerIdentifiers.kimiCode, kimiCodeAuthMethod: "api-key", } expect(checkExistKey(config)).toBe(false) @@ -129,7 +129,7 @@ describe("checkExistKey", () => { it("should return false for zoo-gateway without session token or auth", () => { const config: ProviderSettings = { - apiProvider: "zoo-gateway", + apiProvider: providerIdentifiers.zooGateway, zooGatewayModelId: "alibaba/qwen-3.6-max-preview", } expect(checkExistKey(config)).toBe(false) @@ -142,7 +142,7 @@ describe("checkExistKey", () => { it("should return true for zoo-gateway when profile has zooSessionToken", () => { const config: ProviderSettings = { - apiProvider: "zoo-gateway", + apiProvider: providerIdentifiers.zooGateway, zooSessionToken: "zoo_ext_test_token", } expect(checkExistKey(config)).toBe(true) @@ -150,7 +150,7 @@ describe("checkExistKey", () => { it("should return true for zoo-gateway when Zoo Code session auth is active", () => { const config: ProviderSettings = { - apiProvider: "zoo-gateway", + apiProvider: providerIdentifiers.zooGateway, zooGatewayModelId: "alibaba/qwen-3.6-max-preview", } expect(checkExistKey(config, true)).toBe(true) @@ -158,7 +158,7 @@ describe("checkExistKey", () => { it("should ignore zooCodeIsAuthenticated for non-zoo-gateway providers", () => { const config: ProviderSettings = { - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, } expect(checkExistKey(config, true)).toBe(false) }) diff --git a/src/shared/embeddingModels.ts b/src/shared/embeddingModels.ts index a89e2c9488..3c59b681d2 100644 --- a/src/shared/embeddingModels.ts +++ b/src/shared/embeddingModels.ts @@ -3,6 +3,7 @@ */ import type { EmbedderProvider, EmbeddingModelProfiles } from "@roo-code/types" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" // Example profiles - expand this list as needed export const EMBEDDING_MODEL_PROFILES: EmbeddingModelProfiles = { @@ -157,11 +158,11 @@ export function getModelQueryPrefix(provider: EmbedderProvider, modelId: string) */ export function getDefaultModelId(provider: EmbedderProvider): string { switch (provider) { - case "openai": + case providerIdentifiers.openai: case "openai-compatible": return "text-embedding-3-small" - case "ollama": { + case providerIdentifiers.ollama: { // Choose a sensible default for Ollama, e.g., the first one listed or a specific one const ollamaModels = EMBEDDING_MODEL_PROFILES.ollama const defaultOllamaModel = ollamaModels && Object.keys(ollamaModels)[0] @@ -174,18 +175,18 @@ export function getDefaultModelId(provider: EmbedderProvider): string { return "unknown-default" // Placeholder specific model ID } - case "gemini": + case providerIdentifiers.gemini: return "gemini-embedding-001" - case "mistral": + case providerIdentifiers.mistral: return "codestral-embed-2505" - case "vercel-ai-gateway": + case providerIdentifiers.vercelAiGateway: return "openai/text-embedding-3-large" - case "bedrock": + case providerIdentifiers.bedrock: return "amazon.titan-embed-text-v2:0" - case "openrouter": + case providerIdentifiers.openrouter: return "openai/text-embedding-3-large" case "semble": diff --git a/src/utils/__tests__/autoImportSettings.spec.ts b/src/utils/__tests__/autoImportSettings.spec.ts index 80347cae2b..010cb273b6 100644 --- a/src/utils/__tests__/autoImportSettings.spec.ts +++ b/src/utils/__tests__/autoImportSettings.spec.ts @@ -77,6 +77,7 @@ import { autoImportSettings } from "../autoImportSettings" import * as vscode from "vscode" import fsPromises from "fs/promises" import { fileExistsAtPath } from "../fs" +import { providerIdentifiers, retiredProviderIdentifiers } from "@roo-code/types/provider-identifiers" describe("autoImportSettings", () => { let mockProviderSettingsManager: any @@ -193,7 +194,7 @@ describe("autoImportSettings", () => { currentApiConfigName: "test-config", apiConfigs: { "test-config": { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, anthropicApiKey: "test-key", }, }, @@ -235,13 +236,13 @@ describe("autoImportSettings", () => { currentApiConfigName: "test-config", apiConfigs: { "test-config": { - apiProvider: "anthropic", + apiProvider: providerIdentifiers.anthropic, anthropicApiKey: "test-key", }, }, }, globalSettings: { - imageGenerationProvider: "roo", + imageGenerationProvider: retiredProviderIdentifiers.roo, customInstructions: "Test instructions", }, } diff --git a/src/utils/__tests__/enhance-prompt.spec.ts b/src/utils/__tests__/enhance-prompt.spec.ts index 7e8c702984..755e9df7d7 100644 --- a/src/utils/__tests__/enhance-prompt.spec.ts +++ b/src/utils/__tests__/enhance-prompt.spec.ts @@ -5,6 +5,7 @@ import type { ProviderSettings } from "@roo-code/types" import { singleCompletionHandler } from "../single-completion-handler" import { buildApiHandler, SingleCompletionHandler } from "../../api" import { supportPrompt } from "../../shared/support-prompt" +import { providerIdentifiers } from "@roo-code/types/provider-identifiers" // Mock the API handler vi.mock("../../api", () => ({ @@ -13,7 +14,7 @@ vi.mock("../../api", () => ({ describe("enhancePrompt", () => { const mockApiConfig: ProviderSettings = { - apiProvider: "openai", + apiProvider: providerIdentifiers.openai, openAiApiKey: "test-key", openAiBaseUrl: "https://api.openai.com/v1", enableReasoningEffort: false, @@ -98,7 +99,7 @@ describe("enhancePrompt", () => { it("uses appropriate model based on provider", async () => { const openRouterConfig: ProviderSettings = { - apiProvider: "openrouter", + apiProvider: providerIdentifiers.openrouter, openRouterApiKey: "test-key", openRouterModelId: "test-model", enableReasoningEffort: false, diff --git a/src/vitest.config.ts b/src/vitest.config.ts index c0c8310e24..42986c454c 100644 --- a/src/vitest.config.ts +++ b/src/vitest.config.ts @@ -19,7 +19,7 @@ export default defineConfig({ coverage: { provider: "v8", reporter: ["text", "lcov"], - include: ["src/**/*.ts", "src/**/*.tsx"], + include: ["src/**/*.ts", "src/**/*.tsx", "eslint-rules/**/*.mjs"], exclude: [ "**/*.test.ts", "**/*.test.tsx", From 63aca680e5fc4674af6411474f1cf0dc1af2fe91 Mon Sep 17 00:00:00 2001 From: Naved Merchant Date: Thu, 20 Aug 2026 20:55:48 +0000 Subject: [PATCH 36/66] fix(semble): increase archive download limit (#1306) --- .../code-index/semble/__tests__/semble-downloader.spec.ts | 7 +++++++ src/services/code-index/semble/semble-downloader.ts | 5 +++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/services/code-index/semble/__tests__/semble-downloader.spec.ts b/src/services/code-index/semble/__tests__/semble-downloader.spec.ts index 29fa8c1859..8a68da175f 100644 --- a/src/services/code-index/semble/__tests__/semble-downloader.spec.ts +++ b/src/services/code-index/semble/__tests__/semble-downloader.spec.ts @@ -97,6 +97,7 @@ import { downloadSemble, getSembleBinaryPath, SEMBLE_SHA256, + SEMBLE_MAX_ARCHIVE_BYTES, } from "../semble-downloader" import * as https from "https" import { spawn } from "child_process" @@ -111,6 +112,12 @@ describe("SEMBLE_SHA256 checksum fixture", () => { }) }) +describe("Semble archive download limit", () => { + it("allows 100 MiB for future release growth", () => { + expect(SEMBLE_MAX_ARCHIVE_BYTES).toBe(100 * 1024 * 1024) + }) +}) + describe("semble-downloader", () => { beforeEach(() => { clearAllMocks() diff --git a/src/services/code-index/semble/semble-downloader.ts b/src/services/code-index/semble/semble-downloader.ts index 5f68ffe58c..6a326b2150 100644 --- a/src/services/code-index/semble/semble-downloader.ts +++ b/src/services/code-index/semble/semble-downloader.ts @@ -26,7 +26,8 @@ const SEMBLE_ARCHIVES: Record = { export const SEMBLE_VERSION = "v0.4.1" const DOWNLOAD_BASE_URL = `https://github.com/Zoo-Code-Org/sembleexec/releases/download/${SEMBLE_VERSION}` const VERSION_FILE = ".semble-version" -const MAX_ARCHIVE_BYTES = 50 * 1024 * 1024 +// Leave room for future release growth while still rejecting anomalous downloads. +export const SEMBLE_MAX_ARCHIVE_BYTES = 100 * 1024 * 1024 /** * SHA-256 checksums for each platform archive at SEMBLE_VERSION. @@ -122,7 +123,7 @@ export async function downloadSemble(storageDir: string): Promise verifyChecksum(archivePath, expectedChecksum), extractArchive: async (archivePath, stagingDir) => { From 21d35c4a96d42b4014e33c9a1085f4dbb533378c Mon Sep 17 00:00:00 2001 From: edelauna <54631123+edelauna@users.noreply.github.com> Date: Thu, 20 Aug 2026 20:56:32 +0000 Subject: [PATCH 37/66] fix(task-history): atomic per-task merge and drop shared index file (#1231) (#1261) * fix(task-history): prevent concurrent index clobbering * test(task-history): add regression coverage for self-healing index recovery * fix(task-history): atomic read-modify-write prevents cross-process lost updates * fix(task-history): atomic read-modify-write prevents cross-process lost updates * fix(task-history): drop _index.json, scan task dirs on read * refactor(task-history): extract computeDelta and mergeWithDisk helpers * fix(safeWriteJson): propagate non-ENOENT read errors during merge * fix(task-history): harden cross-process merge and reconciliation * fix(task-history): throw DeltaRejectedError on invalid merge and harden edge cases --------- Co-authored-by: Naved Merchant --- src/core/task-persistence/TaskHistoryStore.ts | 311 ++++++++---------- .../TaskHistoryStore.crossInstance.spec.ts | 154 ++++++++- .../TaskHistoryStore.reconciliation.spec.ts | 13 +- .../__tests__/TaskHistoryStore.spec.ts | 75 +---- ...iewMessageHandler.importRooHistory.spec.ts | 10 +- src/core/webview/webviewMessageHandler.ts | 1 - src/eslint-suppressions.json | 5 - src/shared/globalFileNames.ts | 1 - src/utils/__tests__/safeWriteJson.test.ts | 74 +++++ src/utils/safeWriteJson.ts | 31 +- 10 files changed, 418 insertions(+), 257 deletions(-) diff --git a/src/core/task-persistence/TaskHistoryStore.ts b/src/core/task-persistence/TaskHistoryStore.ts index e4707ee0a9..075d21474f 100644 --- a/src/core/task-persistence/TaskHistoryStore.ts +++ b/src/core/task-persistence/TaskHistoryStore.ts @@ -7,12 +7,23 @@ import deepEqual from "fast-deep-equal" import type { HistoryItem } from "@roo-code/types" import { GlobalFileNames } from "../../shared/globalFileNames" -import { safeWriteJson } from "../../utils/safeWriteJson" +import { LOCK_STALE_MS, safeWriteJson } from "../../utils/safeWriteJson" import { getStorageBasePath } from "../../utils/storage" /** Valid status values for a task's HistoryItem. */ export type HistoryItemStatus = NonNullable +export class DeltaRejectedError extends Error { + constructor( + public readonly taskId: string, + public readonly diskStatus: HistoryItemStatus, + public readonly attemptedStatus: HistoryItemStatus, + ) { + super(`Delta rejected for task ${taskId}: disk status ${diskStatus} rejects transition to ${attemptedStatus}`) + this.name = "DeltaRejectedError" + } +} + const VALID_TRANSITIONS: Record = { active: ["delegated", "completed", "interrupted"], delegated: ["active"], @@ -34,12 +45,30 @@ export function assertValidTransition(from: HistoryItemStatus | undefined, to: H } /** - * Index file format for fast startup reads. + * Build a `safeWriteJson` merge callback that applies only `delta` to the + * current disk state, preserving fields written by another process. */ -interface HistoryIndex { - version: number - updatedAt: number - entries: HistoryItem[] +function mergeWithDisk(delta: Partial): (existing: unknown, incoming: unknown) => unknown { + return (existing, incoming) => { + if (!existing || typeof existing !== "object" || !("id" in existing)) { + return incoming + } + const disk = existing as HistoryItem + if (delta.status !== undefined) { + const diskStatus: HistoryItemStatus = disk.status ?? "active" + if (delta.status !== diskStatus) { + const validTargets = VALID_TRANSITIONS[diskStatus] + if (!validTargets?.includes(delta.status as HistoryItemStatus)) { + throw new DeltaRejectedError(disk.id, diskStatus, delta.status as HistoryItemStatus) + } + } + } + const merged = { ...disk, ...delta } + if (delta.childIds && disk.childIds) { + merged.childIds = [...new Set([...disk.childIds, ...delta.childIds])] + } + return merged + } } /** @@ -75,12 +104,14 @@ interface DelegationRepairIntent { * * Each task's HistoryItem is stored as an individual JSON file in its * existing task directory (`globalStorage/tasks//history_item.json`). - * A single index file (`globalStorage/tasks/_index.json`) is maintained - * as a cache for fast list reads at startup. + * There is no shared index file. Reads scan the task directories. * - * Cross-process safety comes from `safeWriteJson`'s `proper-lockfile` - * on per-task file writes. Within a single extension host process, - * an in-process write lock serializes mutations. + * Cross-process safety for per-task files comes from `safeWriteJson`'s + * `proper-lockfile` with a `merge` callback: each write reads the + * current file under the advisory lock and merges incoming fields, so + * a concurrent writer's changes are preserved rather than silently + * dropped. Within a single extension host process, an in-process write + * lock serializes mutations. */ /** * Options for TaskHistoryStore constructor. @@ -100,7 +131,6 @@ export class TaskHistoryStore { private cache: Map = new Map() private taskFileMtimes: Map = new Map() private writeLock: Promise = Promise.resolve() - private indexWriteTimer: ReturnType | null = null private fsWatcher: fsSync.FSWatcher | null = null private reconcileTimer: ReturnType | null = null private disposed = false @@ -112,9 +142,6 @@ export class TaskHistoryStore { public readonly initialized: Promise private resolveInitialized!: () => void - /** Debounce window for index writes in milliseconds. */ - private static readonly INDEX_WRITE_DEBOUNCE_MS = 2000 - /** Periodic reconciliation interval in milliseconds. */ private static readonly RECONCILE_INTERVAL_MS = 5 * 60 * 1000 @@ -129,37 +156,34 @@ export class TaskHistoryStore { // ────────────────────────────── Lifecycle ────────────────────────────── /** - * Load index, reconcile if needed, start watchers. + * Scan task files, reconcile delegation state, start watchers. */ async initialize(): Promise { try { const tasksDir = await this.getTasksDir() await fs.mkdir(tasksDir, { recursive: true }) - // 1. Load existing index into the cache - await this.loadIndex() - - // 2. Reconcile cache against actual task directories on disk + // 1. Scan task directories to populate the cache await this.reconcile({ forceRefresh: true }) // Capture which active tasks were present in persisted state before replay can // change any statuses. Reconciliation must not treat a replay-repaired parent // as an orphaned active child in the same startup pass. const persistedActiveIds = this.getPersistedActiveIds() - // 3. Complete any two-record repair interrupted after its intent was durable. + // 2. Complete any two-record repair interrupted after its intent was durable. try { await this.replayDelegationRepairIntent() } catch (error) { console.error("[TaskHistoryStore] Failed to replay delegation repair intent:", error) } - // 4. Repair delegation inconsistencies left by a previous crash + // 3. Repair delegation inconsistencies left by a previous crash await this.reconcileDelegationState(persistedActiveIds) - // 5. Start fs.watch for cross-instance reactivity + // 4. Start fs.watch for cross-instance reactivity this.startWatcher() - // 6. Start periodic reconciliation as a defensive fallback + // 5. Start periodic reconciliation as a defensive fallback this.startPeriodicReconciliation() } finally { // Mark initialization as complete so callers awaiting `initialized` can proceed @@ -173,11 +197,6 @@ export class TaskHistoryStore { dispose(): void { this.disposed = true - if (this.indexWriteTimer) { - clearTimeout(this.indexWriteTimer) - this.indexWriteTimer = null - } - if (this.reconcileTimer) { clearTimeout(this.reconcileTimer) this.reconcileTimer = null @@ -187,11 +206,6 @@ export class TaskHistoryStore { this.fsWatcher.close() this.fsWatcher = null } - - // Synchronously flush the index (best-effort) - this.flushIndex().catch((err) => { - console.error("[TaskHistoryStore] Error flushing index on dispose:", err) - }) } // ────────────────────────────── Reads ────────────────────────────── @@ -222,8 +236,8 @@ export class TaskHistoryStore { /** * Insert or update a history item. * - * Writes the per-task file immediately (source of truth), - * updates the in-memory Map, and schedules a debounced index write. + * Writes the per-task file immediately (source of truth) + * and updates the in-memory cache. */ async upsert(item: HistoryItem): Promise { return this.withLock(() => this.upsertCore(item)) @@ -250,20 +264,40 @@ export class TaskHistoryStore { if (!options.skipTransitionCheck && existing && item.status !== undefined) { const normalizedExisting: HistoryItemStatus = existing.status ?? "active" if (item.status !== normalizedExisting) { - assertValidTransition(existing.status, item.status) + try { + assertValidTransition(existing.status, item.status) + } catch (cacheError) { + // Cache may be stale from a peer write. Re-read disk + // under the store lock before rejecting the transition. + const diskItem = await this.readTaskFile(item.id) + if (!diskItem) { + throw cacheError + } + assertValidTransition(diskItem.status, item.status) + } } } // Merge: preserve existing metadata unless explicitly overwritten const merged = existing ? { ...existing, ...item } : item - // Write per-task file (source of truth) - await this.writeTaskFile(merged) + const delta = existing ? this.buildDelta(item.id, existing, item) : { ...item } + let written: HistoryItem + try { + written = await this.writeTaskFile(merged, delta) + } catch (error) { + if (error instanceof DeltaRejectedError) { + const diskItem = await this.readTaskFile(item.id) + if (diskItem) { + this.cache.set(item.id, diskItem) + } + throw error + } + throw error + } - // Update in-memory cache - this.cache.set(merged.id, merged) - // Schedule debounced index write - this.scheduleIndexWrite() + // Update in-memory cache with what was actually persisted + this.cache.set(written.id, written) const all = this.getAll() @@ -291,8 +325,6 @@ export class TaskHistoryStore { // File may already be deleted } - this.scheduleIndexWrite() - // Call onWrite callback inside the lock for serialized write-through if (this.onWrite) { await this.onWrite(this.getAll()) @@ -317,8 +349,6 @@ export class TaskHistoryStore { } } - this.scheduleIndexWrite() - // Call onWrite callback inside the lock for serialized write-through if (this.onWrite) { await this.onWrite(this.getAll()) @@ -329,7 +359,7 @@ export class TaskHistoryStore { // ────────────────────────────── Reconciliation ────────────────────────────── /** - * Scan task directories vs index and fix any drift. + * Scan task directories and fix any drift between disk and cache. * * - Tasks on disk but missing from cache: read and add * - Tasks in cache but missing from disk: remove @@ -346,20 +376,18 @@ export class TaskHistoryStore { return // tasks dir doesn't exist yet } - // Filter out the index file and hidden files + // Filter out hidden and reserved names const taskDirNames = dirEntries.filter((name) => !name.startsWith("_") && !name.startsWith(".")) const onDiskIds = new Set(taskDirNames) const cacheIds = new Set(this.cache.keys()) - let changed = false + const liveIds = new Set() - // Task files are authoritative during startup. Later watcher and periodic - // reconciliations use mtime change detection to avoid rewriting the index when - // nothing changed on disk. for (const taskId of onDiskIds) { try { const taskFilePath = await this.getTaskFilePath(taskId) const { mtimeMs } = await fs.stat(taskFilePath) + liveIds.add(taskId) if ( !options.forceRefresh && this.cache.has(taskId) && @@ -369,31 +397,37 @@ export class TaskHistoryStore { } const item = await this.readTaskFile(taskId) - if (item) { + if (item?.id === taskId) { const previous = this.cache.get(taskId) this.taskFileMtimes.set(taskId, mtimeMs) if (!deepEqual(previous, item)) { this.cache.set(taskId, item) - changed = true } } } catch { - // Corrupted or missing file, skip + // File may be temporarily absent during a peer's atomic + // rename window in safeWriteJson. The advisory lock is + // held for the entire write, so its presence means a + // write is in progress — keep the task live. + try { + const lockPath = (await this.getTaskFilePath(taskId)) + ".lock" + const lockStat = await fs.stat(lockPath) + if (Date.now() - lockStat.mtimeMs < LOCK_STALE_MS) { + liveIds.add(taskId) + } + } catch { + // No lock file — file is genuinely absent + } } } - // Tasks in cache but not on disk: remove from cache + // Evict tasks whose history_item.json no longer exists for (const taskId of cacheIds) { - if (!onDiskIds.has(taskId)) { + if (!liveIds.has(taskId)) { this.cache.delete(taskId) this.taskFileMtimes.delete(taskId) - changed = true } } - - if (changed) { - this.scheduleIndexWrite() - } }) } @@ -428,7 +462,7 @@ export class TaskHistoryStore { * Reconcile delegation state while the store lock is already held. * * Callers that do not hold the lock must use `reconcileDelegationState()`. - * Migration uses this core method so its cache/file/index updates and the + * Migration uses this core method so its cache/file updates and the * follow-up repair remain one serialized operation without re-entering the * non-reentrant lock. */ @@ -584,12 +618,6 @@ export class TaskHistoryStore { await this.onWrite(this.getAll()) } await this.removeDelegationRepairIntent() - // Task files are authoritative and the intent is the recovery journal. - // Clean up the journal before scheduling the derived index: a crash after - // cleanup but before the index write is safe because startup rebuilds the - // index from task files, while the reverse ordering could make the index - // appear durable before recovery metadata is settled. - this.scheduleIndexWrite() }) } @@ -645,9 +673,6 @@ export class TaskHistoryStore { await this.onWrite(this.getAll()) } await this.removeDelegationRepairIntent() - // The index is derived state; keep the intent until authoritative task-file - // writes and write-through have completed, then schedule the index update. - this.scheduleIndexWrite() } private matchesDelegationRepairParentPreconditions(intent: DelegationRepairIntent, parent: HistoryItem): boolean { @@ -845,96 +870,52 @@ export class TaskHistoryStore { } } - // Write the index - await this.writeIndex() - // Repair any delegation inconsistencies introduced by the migrated entries. // Run the lock-free core because migration already holds the store lock. await this.reconcileDelegationStateCore(this.getPersistedActiveIds()) }) } - // ────────────────────────────── Private: Index management ────────────────────────────── - - /** - * Load the `_index.json` file into the in-memory cache. - */ - private async loadIndex(): Promise { - const indexPath = await this.getIndexPath() - - try { - const raw = await fs.readFile(indexPath, "utf8") - const index: HistoryIndex = JSON.parse(raw) - - if (index.version === 1 && Array.isArray(index.entries)) { - for (const entry of index.entries) { - if (entry.id) { - this.cache.set(entry.id, entry) - } - } - } - } catch { - // Index doesn't exist or is corrupted; cache stays empty. - // Reconciliation will rebuild it from per-task files. - } - } - - /** - * Write the full index to disk. - */ - private async writeIndex(): Promise { - const indexPath = await this.getIndexPath() - const index: HistoryIndex = { - version: 1, - updatedAt: Date.now(), - entries: this.getAll(), - } - - await safeWriteJson(indexPath, index) - } + // ────────────────────────────── Private: Per-task file I/O ────────────────────────────── /** - * Schedule a debounced index write. + * Return only the fields in `incoming` that differ from `cached`. */ - private scheduleIndexWrite(): void { - if (this.disposed) { - return - } - - if (this.indexWriteTimer) { - clearTimeout(this.indexWriteTimer) - } - - this.indexWriteTimer = setTimeout(async () => { - this.indexWriteTimer = null - try { - await this.writeIndex() - } catch (err) { - console.error("[TaskHistoryStore] Failed to write index:", err) - } - }, TaskHistoryStore.INDEX_WRITE_DEBOUNCE_MS) + private computeDelta(cached: HistoryItem, incoming: Partial): Partial { + return Object.fromEntries( + Object.entries(incoming).filter(([k, v]) => !deepEqual(v, (cached as Record)[k])), + ) as Partial } - /** - * Force an immediate index write (called on dispose/shutdown). - */ - async flushIndex(): Promise { - if (this.indexWriteTimer) { - clearTimeout(this.indexWriteTimer) - this.indexWriteTimer = null - } - - await this.writeIndex() + private buildDelta(id: string, cached: HistoryItem, incoming: Partial): Partial { + return { id, ...this.computeDelta(cached, incoming) } } - // ────────────────────────────── Private: Per-task file I/O ────────────────────────────── - /** * Write a HistoryItem to its per-task `history_item.json` file. + * + * When `delta` is provided, the merge callback applies only the + * delta to the current disk state, so fields written by another + * process are preserved. Without a delta the full item is written + * as-is (used by administrative repair paths that are authoritative). */ - private async writeTaskFile(item: HistoryItem): Promise { + private async writeTaskFile(item: HistoryItem, delta?: Partial): Promise { const filePath = await this.getTaskFilePath(item.id) - await safeWriteJson(filePath, item) + if (delta) { + let written: HistoryItem = item + const mergeFn = mergeWithDisk(delta) + await safeWriteJson(filePath, item, { + merge: (existing, incoming) => { + const result = mergeFn(existing, incoming) + written = result as HistoryItem + return result + }, + }) + return written + } else { + await safeWriteJson(filePath, item) + return item + } } /** @@ -1055,10 +1036,11 @@ export class TaskHistoryStore { } /** - * Atomically update two related HistoryItems within a single lock acquisition. - * Both updaters run synchronously (no I/O, no lock re-entry). Both writes are - * committed before the lock releases — no concurrent writer can observe an - * intermediate state. + * Update two related HistoryItems within a single in-process lock acquisition. + * Both updaters run synchronously (no I/O, no lock re-entry). Both writes + * complete before the lock releases, so no in-process reader can observe an + * intermediate state. Cross-process atomicity is NOT guaranteed — each + * writeTaskFile call acquires and releases its own advisory file lock. * * @throws If either task ID is not present in the cache. */ @@ -1105,16 +1087,21 @@ export class TaskHistoryStore { const mergedFirst = { ...first, ...updatedFirst } const mergedSecond = { ...second, ...updatedSecond } - // Write both files before touching the cache so readers never observe a - // half-updated in-memory state between the two await points. - await this.writeTaskFile(mergedFirst) - await this.writeTaskFile(mergedSecond) + const writtenFirst = await this.writeTaskFile(mergedFirst, this.buildDelta(firstId, first, updatedFirst)) + let writtenSecond: HistoryItem + try { + writtenSecond = await this.writeTaskFile(mergedSecond, this.buildDelta(secondId, second, updatedSecond)) + } catch (error) { + // First record is committed on disk. Update cache so it + // reflects disk state before propagating the error. + this.cache.set(firstId, writtenFirst) + throw error + } - // Both disk writes succeeded — now update the cache atomically. - this.cache.set(firstId, mergedFirst) - this.cache.set(secondId, mergedSecond) + // Both disk writes succeeded — now update the cache. + this.cache.set(firstId, writtenFirst) + this.cache.set(secondId, writtenSecond) - this.scheduleIndexWrite() const all = this.getAll() if (this.onWrite) { await this.onWrite(all) @@ -1155,12 +1142,4 @@ export class TaskHistoryStore { const tasksDir = await this.getTasksDir() return path.join(tasksDir, taskId, GlobalFileNames.historyItem) } - - /** - * Get the path to the `_index.json` file. - */ - private async getIndexPath(): Promise { - const tasksDir = await this.getTasksDir() - return path.join(tasksDir, GlobalFileNames.historyIndex) - } } diff --git a/src/core/task-persistence/__tests__/TaskHistoryStore.crossInstance.spec.ts b/src/core/task-persistence/__tests__/TaskHistoryStore.crossInstance.spec.ts index e5166c478c..cef9874e5f 100644 --- a/src/core/task-persistence/__tests__/TaskHistoryStore.crossInstance.spec.ts +++ b/src/core/task-persistence/__tests__/TaskHistoryStore.crossInstance.spec.ts @@ -6,7 +6,7 @@ import * as os from "os" import type { HistoryItem } from "@roo-code/types" -import { TaskHistoryStore } from "../TaskHistoryStore" +import { TaskHistoryStore, DeltaRejectedError } from "../TaskHistoryStore" import { GlobalFileNames } from "../../../shared/globalFileNames" vi.mock("../../../utils/storage", () => ({ @@ -15,12 +15,30 @@ vi.mock("../../../utils/storage", () => ({ }), })) -// Mock safeWriteJson to use plain fs writes in tests (avoids proper-lockfile issues) +// Mock safeWriteJson to use plain fs writes but honor the merge callback. vi.mock("../../../utils/safeWriteJson", () => ({ - safeWriteJson: vi.fn().mockImplementation(async (filePath: string, data: any) => { - await fs.mkdir(path.dirname(filePath), { recursive: true }) - await fs.writeFile(filePath, JSON.stringify(data, null, "\t"), "utf8") - }), + safeWriteJson: vi + .fn() + .mockImplementation( + async ( + filePath: string, + data: unknown, + options?: { merge?: (existing: unknown, incoming: unknown) => unknown }, + ) => { + await fs.mkdir(path.dirname(filePath), { recursive: true }) + if (options?.merge) { + let existing: unknown = null + try { + const raw = await fs.readFile(filePath, "utf8") + existing = JSON.parse(raw) + } catch { + // File does not exist or is corrupt + } + data = options.merge(existing, data) + } + await fs.writeFile(filePath, JSON.stringify(data, null, "\t"), "utf8") + }, + ), })) function makeHistoryItem(overrides: Partial = {}): HistoryItem { @@ -124,6 +142,27 @@ describe("TaskHistoryStore cross-instance safety", () => { expect(storeB.get("shared-task")).toBeUndefined() }) + it("delete by instance A is detected even when the task directory remains", async () => { + await storeA.initialize() + await storeB.initialize() + + const item = makeHistoryItem({ id: "file-only-delete" }) + await storeA.upsert(item) + await storeB.reconcile() + + expect(storeB.get("file-only-delete")).toBeDefined() + + // delete() unlinks history_item.json but leaves the task directory. + await storeA.delete("file-only-delete") + + // Directory still exists (other files like ui_messages.json may remain). + const taskDir = path.join(tmpDir, "tasks", "file-only-delete") + await expect(fs.access(taskDir)).resolves.toBeUndefined() + + await storeB.reconcile() + expect(storeB.get("file-only-delete")).toBeUndefined() + }) + it("per-task file updates by one instance are visible to another after invalidation", async () => { await storeA.initialize() await storeB.initialize() @@ -164,4 +203,107 @@ describe("TaskHistoryStore cross-instance safety", () => { expect(storeA.getAll().length).toBe(10) expect(storeB.getAll().length).toBe(10) }) + + /** + * Host B completes a task on disk while host A's cache still has it + * active. Host A's next save updates only totalCost (a full-object + * upsert — the realistic production shape). The diff-delta merge + * preserves B's status because status did not change in A's cache. + */ + it("per-task diff-delta preserves a peer's status change on full-object upsert", async () => { + await storeA.initialize() + + // Base item with an explicit status — mirrors real production items. + const base = makeHistoryItem({ id: "shared-task", status: "active", totalCost: 0.01, ts: 1000 }) + await storeA.upsert(base) + + // Host B completes the task on disk; A's cache still has "active". + const filePath = path.join(tmpDir, "tasks", "shared-task", GlobalFileNames.historyItem) + const onDisk = JSON.parse(await fs.readFile(filePath, "utf8")) + onDisk.status = "completed" + onDisk.completionResultSummary = "done by host B" + await fs.writeFile(filePath, JSON.stringify(onDisk), "utf8") + + // Host A does a full-object upsert (the realistic path — spread the + // cached item and change one field). The cached item has status: "active". + await storeA.upsert({ ...storeA.get("shared-task")!, totalCost: 9.99 }) + + const final = JSON.parse(await fs.readFile(filePath, "utf8")) as HistoryItem + expect(final.totalCost).toBe(9.99) + // Status is preserved from disk because A's delta does not include + // status — it was unchanged relative to A's cache. + expect(final.status).toBe("completed") + expect(final.completionResultSummary).toBe("done by host B") + + // Cache reflects the caller's totalCost change and the peer's status. + expect(storeA.get("shared-task")!.totalCost).toBe(9.99) + expect(storeA.get("shared-task")!.status).toBe("completed") + expect(storeA.get("shared-task")!.completionResultSummary).toBe("done by host B") + }) + + /** + * Regression: a stale host whose cache says "active" tries to write + * status: "delegated" after a peer already wrote "completed" to disk. + * The merge must reject the entire delta (including companion fields) + * to prevent an internally-inconsistent record. + */ + it("merge rejects an invalid status transition against disk and throws DeltaRejectedError", async () => { + await storeA.initialize() + + const base = makeHistoryItem({ id: "guarded-task", status: "active", totalCost: 0.01, ts: 1000 }) + await storeA.upsert(base) + + // Peer writes terminal "completed" directly to disk. + const filePath = path.join(tmpDir, "tasks", "guarded-task", GlobalFileNames.historyItem) + const onDisk = JSON.parse(await fs.readFile(filePath, "utf8")) + onDisk.status = "completed" + onDisk.completionResultSummary = "done by peer" + await fs.writeFile(filePath, JSON.stringify(onDisk), "utf8") + + // Host A's cache still has "active". It tries to delegate (active → delegated + // passes the cache check, but completed → delegated is invalid on disk). + const staleItem = storeA.get("guarded-task")! + await expect( + storeA.upsert({ + ...staleItem, + status: "delegated", + awaitingChildId: "child-99", + delegatedToId: "child-99", + }), + ).rejects.toThrow(DeltaRejectedError) + + const final = JSON.parse(await fs.readFile(filePath, "utf8")) as HistoryItem + // Terminal status must survive — disk is untouched. + expect(final.status).toBe("completed") + expect(final.completionResultSummary).toBe("done by peer") + // Companion fields from the rejected delta must NOT be applied. + expect(final.awaitingChildId).toBeUndefined() + expect(final.delegatedToId).toBeUndefined() + + // Cache must reflect the disk state, not the stale delta. + expect(storeA.get("guarded-task")!.status).toBe("completed") + }) + + /** + * When both hosts change the same field, the last writer wins. + * This is expected — true conflict resolution requires application + * semantics that a generic merge cannot provide. + */ + it("same-field changes from both hosts are last-writer-wins", async () => { + await storeA.initialize() + await storeB.initialize() + + const base = makeHistoryItem({ id: "shared-task", status: "active", totalCost: 0.01, ts: 1000 }) + await storeA.upsert(base) + await storeB.reconcile() + + // Both hosts change totalCost. + await storeA.upsert({ ...storeA.get("shared-task")!, totalCost: 1.0 }) + await storeB.upsert({ ...storeB.get("shared-task")!, totalCost: 2.0 }) + + const filePath = path.join(tmpDir, "tasks", "shared-task", GlobalFileNames.historyItem) + const final = JSON.parse(await fs.readFile(filePath, "utf8")) as HistoryItem + // B wrote last, so B's value wins. + expect(final.totalCost).toBe(2.0) + }) }) diff --git a/src/core/task-persistence/__tests__/TaskHistoryStore.reconciliation.spec.ts b/src/core/task-persistence/__tests__/TaskHistoryStore.reconciliation.spec.ts index e788b5d96a..e37fd1a25e 100644 --- a/src/core/task-persistence/__tests__/TaskHistoryStore.reconciliation.spec.ts +++ b/src/core/task-persistence/__tests__/TaskHistoryStore.reconciliation.spec.ts @@ -465,7 +465,7 @@ describe("TaskHistoryStore reconcileDelegationState", () => { await expect(fs.access(intentPath)).rejects.toThrow() }) - it("does not schedule the derived index before repair-intent cleanup succeeds", async () => { + it("removes the repair-intent file after successful replay", async () => { const child = makeItem({ id: "child-deferred-index", status: "active", parentTaskId: "parent-deferred-index" }) const parent = makeItem({ id: "parent-deferred-index", @@ -478,23 +478,12 @@ describe("TaskHistoryStore reconcileDelegationState", () => { await fs.writeFile(intentPath, JSON.stringify(makeRepairIntent(parent, child))) await store.reconcile({ forceRefresh: true }) - const events: string[] = [] const storeInternals = store as unknown as { - scheduleIndexWrite: () => void - removeDelegationRepairIntent: () => Promise replayDelegationRepairIntent: () => Promise } - vi.spyOn(storeInternals, "removeDelegationRepairIntent").mockImplementation(async () => { - events.push("cleanup") - await fs.unlink(intentPath) - }) - vi.spyOn(storeInternals, "scheduleIndexWrite").mockImplementation(() => { - events.push("schedule") - }) await storeInternals.replayDelegationRepairIntent() - expect(events).toEqual(["cleanup", "schedule"]) await expect(fs.access(intentPath)).rejects.toThrow() }) diff --git a/src/core/task-persistence/__tests__/TaskHistoryStore.spec.ts b/src/core/task-persistence/__tests__/TaskHistoryStore.spec.ts index 3188e9c505..8ce80e096d 100644 --- a/src/core/task-persistence/__tests__/TaskHistoryStore.spec.ts +++ b/src/core/task-persistence/__tests__/TaskHistoryStore.spec.ts @@ -57,29 +57,19 @@ describe("TaskHistoryStore", () => { expect(store.getAll()).toEqual([]) }) - it("initializes from existing index file", async () => { + it("initializes from existing per-task files", async () => { const tasksDir = path.join(tmpDir, "tasks") await fs.mkdir(tasksDir, { recursive: true }) const item1 = makeHistoryItem({ id: "task-1", ts: 1000 }) const item2 = makeHistoryItem({ id: "task-2", ts: 2000 }) - // Create task directories so reconciliation doesn't remove them await fs.mkdir(path.join(tasksDir, "task-1"), { recursive: true }) await fs.mkdir(path.join(tasksDir, "task-2"), { recursive: true }) - // Write per-task files await fs.writeFile(path.join(tasksDir, "task-1", GlobalFileNames.historyItem), JSON.stringify(item1)) await fs.writeFile(path.join(tasksDir, "task-2", GlobalFileNames.historyItem), JSON.stringify(item2)) - // Write index - const index = { - version: 1, - updatedAt: Date.now(), - entries: [item1, item2], - } - await fs.writeFile(path.join(tasksDir, GlobalFileNames.historyIndex), JSON.stringify(index)) - await store.initialize() expect(store.getAll()).toHaveLength(2) @@ -374,7 +364,7 @@ describe("TaskHistoryStore", () => { expect(store.get("idem-task")).toBeDefined() }) - it("serializes migration cache and index updates behind the store lock", async () => { + it("serializes migration cache updates behind the store lock", async () => { const tasksDir = path.join(tmpDir, "tasks") const migrated = makeHistoryItem({ id: "migration-locked" }) const concurrent = makeHistoryItem({ id: "migration-concurrent" }) @@ -389,12 +379,17 @@ describe("TaskHistoryStore", () => { const migrationWriteStarted = new Promise((resolve) => { signalMigrationWriteStarted = resolve }) - const storeInternals = store as unknown as { writeIndex: () => Promise } - const originalWriteIndex = storeInternals.writeIndex.bind(store) - vi.spyOn(storeInternals, "writeIndex").mockImplementation(async () => { - signalMigrationWriteStarted() - await migrationWriteCanFinish - return originalWriteIndex() + + const { safeWriteJson: mockSafeWriteJson } = await import("../../../utils/safeWriteJson") + const originalImpl = vi.mocked(mockSafeWriteJson).getMockImplementation()! + let firstCall = true + vi.mocked(mockSafeWriteJson).mockImplementation(async (...args) => { + if (firstCall) { + firstCall = false + signalMigrationWriteStarted() + await migrationWriteCanFinish + } + return originalImpl(...args) }) const migration = store.migrateFromGlobalState([migrated]) @@ -407,45 +402,6 @@ describe("TaskHistoryStore", () => { expect(store.get(migrated.id)).toEqual(migrated) expect(store.get(concurrent.id)).toEqual(concurrent) - await store.flushIndex() - const index = JSON.parse(await fs.readFile(path.join(tasksDir, GlobalFileNames.historyIndex), "utf8")) as { - entries: HistoryItem[] - } - expect(index.entries.map((entry) => entry.id)).toEqual(expect.arrayContaining([migrated.id, concurrent.id])) - }) - }) - - describe("flushIndex()", () => { - it("writes index to disk on flush", async () => { - await store.initialize() - - await store.upsert(makeHistoryItem({ id: "flush-task" })) - await store.flushIndex() - - const indexPath = path.join(tmpDir, "tasks", GlobalFileNames.historyIndex) - const raw = await fs.readFile(indexPath, "utf8") - const index = JSON.parse(raw) - - expect(index.version).toBe(1) - expect(index.entries).toHaveLength(1) - expect(index.entries[0].id).toBe("flush-task") - }) - }) - - describe("dispose()", () => { - it("flushes index on dispose", async () => { - await store.initialize() - - await store.upsert(makeHistoryItem({ id: "dispose-task" })) - store.dispose() - - // Give the flush a moment to complete - await new Promise((resolve) => setTimeout(resolve, 100)) - - const indexPath = path.join(tmpDir, "tasks", GlobalFileNames.historyIndex) - const raw = await fs.readFile(indexPath, "utf8") - const index = JSON.parse(raw) - expect(index.entries).toHaveLength(1) }) }) @@ -748,8 +704,9 @@ describe("TaskHistoryStore", () => { const parentDisk = JSON.parse(await fs.readFile(parentFile, "utf8")) expect(parentDisk.status).toBe("delegated") - // Cache was NOT updated (cache set is deferred until after both writes succeed) - expect(store.get("child-partial")?.status).toBe("active") + // First record's cache IS updated (it was committed to disk). + // Second record's cache is unchanged (write never completed). + expect(store.get("child-partial")?.status).toBe("completed") expect(store.get("parent-partial")?.status).toBe("delegated") }) diff --git a/src/core/webview/__tests__/webviewMessageHandler.importRooHistory.spec.ts b/src/core/webview/__tests__/webviewMessageHandler.importRooHistory.spec.ts index df85ff1df4..1f23e353c6 100644 --- a/src/core/webview/__tests__/webviewMessageHandler.importRooHistory.spec.ts +++ b/src/core/webview/__tests__/webviewMessageHandler.importRooHistory.spec.ts @@ -52,7 +52,6 @@ describe("webviewMessageHandler - importRooHistory", () => { taskHistoryStore: { invalidateAll: ReturnType reconcile: ReturnType - flushIndex: ReturnType } postMessageToWebview: ReturnType postStateToWebview: ReturnType @@ -71,7 +70,6 @@ describe("webviewMessageHandler - importRooHistory", () => { taskHistoryStore: { invalidateAll: vi.fn(), reconcile: vi.fn().mockResolvedValue(undefined), - flushIndex: vi.fn().mockResolvedValue(undefined), }, postMessageToWebview: vi.fn().mockResolvedValue(undefined), postStateToWebview: vi.fn().mockResolvedValue(undefined), @@ -106,7 +104,7 @@ describe("webviewMessageHandler - importRooHistory", () => { expect(importRooTaskHistoryMock).toHaveBeenCalledWith("/mock/storage", expect.any(Function)) expect(mockProvider.taskHistoryStore.invalidateAll).toHaveBeenCalledTimes(1) expect(mockProvider.taskHistoryStore.reconcile).toHaveBeenCalledTimes(1) - expect(mockProvider.taskHistoryStore.flushIndex).toHaveBeenCalledTimes(1) + expect(mockProvider.postStateToWebview).toHaveBeenCalledTimes(1) expect(mockProvider.postMessageToWebview).toHaveBeenNthCalledWith(1, { type: "rooHistoryImportProgress", @@ -189,7 +187,7 @@ describe("webviewMessageHandler - importRooHistory", () => { expect(importRooTaskHistoryMock).toHaveBeenCalledWith("/mock/storage", expect.any(Function)) expect(mockProvider.taskHistoryStore.invalidateAll).not.toHaveBeenCalled() expect(mockProvider.taskHistoryStore.reconcile).not.toHaveBeenCalled() - expect(mockProvider.taskHistoryStore.flushIndex).not.toHaveBeenCalled() + expect(mockProvider.postStateToWebview).not.toHaveBeenCalled() expect(mockProvider.postMessageToWebview).toHaveBeenNthCalledWith(2, { type: "rooHistoryImportProgress", @@ -222,7 +220,7 @@ describe("webviewMessageHandler - importRooHistory", () => { // after a partial-copy failure still reconciles the store. expect(mockProvider.taskHistoryStore.invalidateAll).toHaveBeenCalledTimes(1) expect(mockProvider.taskHistoryStore.reconcile).toHaveBeenCalledTimes(1) - expect(mockProvider.taskHistoryStore.flushIndex).toHaveBeenCalledTimes(1) + expect(mockProvider.postStateToWebview).toHaveBeenCalledTimes(1) expect(vscode.window.showWarningMessage).toHaveBeenCalledWith( "common:warnings.rooHistoryImport.alreadyImported", @@ -237,7 +235,7 @@ describe("webviewMessageHandler - importRooHistory", () => { expect(mockProvider.taskHistoryStore.invalidateAll).not.toHaveBeenCalled() expect(mockProvider.taskHistoryStore.reconcile).not.toHaveBeenCalled() - expect(mockProvider.taskHistoryStore.flushIndex).not.toHaveBeenCalled() + expect(mockProvider.postStateToWebview).not.toHaveBeenCalled() expect(mockProvider.log).toHaveBeenCalledWith("[importRooHistory] failed: permission denied") expect(mockProvider.postMessageToWebview).toHaveBeenNthCalledWith(2, { diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index b481e2ec1d..648269c1b5 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -1003,7 +1003,6 @@ export const webviewMessageHandler = async ( // so a retry after a partial-copy failure still reconciles the store. await provider.taskHistoryStore.invalidateAll() await provider.taskHistoryStore.reconcile() - await provider.taskHistoryStore.flushIndex() await provider.postStateToWebview() await provider.postMessageToWebview({ type: "rooHistoryImportProgress", diff --git a/src/eslint-suppressions.json b/src/eslint-suppressions.json index f790fba436..f405adc8df 100644 --- a/src/eslint-suppressions.json +++ b/src/eslint-suppressions.json @@ -779,11 +779,6 @@ "count": 4 } }, - "core/task-persistence/__tests__/TaskHistoryStore.crossInstance.spec.ts": { - "@typescript-eslint/no-explicit-any": { - "count": 1 - } - }, "core/task-persistence/__tests__/TaskHistoryStore.spec.ts": { "@typescript-eslint/no-explicit-any": { "count": 4 diff --git a/src/shared/globalFileNames.ts b/src/shared/globalFileNames.ts index 7bfe18f4bc..9f15a06319 100644 --- a/src/shared/globalFileNames.ts +++ b/src/shared/globalFileNames.ts @@ -5,6 +5,5 @@ export const GlobalFileNames = { customModes: "custom_modes.yaml", taskMetadata: "task_metadata.json", historyItem: "history_item.json", - historyIndex: "_index.json", delegationRepairIntent: "_delegation_repair_intent.json", } diff --git a/src/utils/__tests__/safeWriteJson.test.ts b/src/utils/__tests__/safeWriteJson.test.ts index e060de4a31..79d08678a0 100644 --- a/src/utils/__tests__/safeWriteJson.test.ts +++ b/src/utils/__tests__/safeWriteJson.test.ts @@ -468,4 +468,78 @@ describe("safeWriteJson", () => { consoleErrorSpy.mockRestore() }) + + // Merge option tests + test("should merge incoming data with existing file content when merge callback is provided", async () => { + const initial = { a: 1, b: 2 } + await safeWriteJson(currentTestFilePath, initial) + + const incoming = { b: 3, c: 4 } + await safeWriteJson(currentTestFilePath, incoming, { + merge: (existing, data) => ({ + ...(existing as Record), + ...(data as Record), + }), + }) + + const content = await readFileContent(currentTestFilePath) + expect(content).toEqual({ a: 1, b: 3, c: 4 }) + }) + + test("should pass null to merge callback when file does not exist", async () => { + const newFilePath = path.join(tempDir, "nonexistent.json") + const mergeFn = vi.fn((existing, incoming) => incoming) + + await safeWriteJson(newFilePath, { value: 42 }, { merge: mergeFn }) + + expect(mergeFn).toHaveBeenCalledWith(null, { value: 42 }) + const content = await readFileContent(newFilePath) + expect(content).toEqual({ value: 42 }) + }) + + test("should propagate non-ENOENT read errors during merge instead of silently losing data", async () => { + const initial = { a: 1, b: 2 } + await safeWriteJson(currentTestFilePath, initial) + + const eio = Object.assign(new Error("I/O error"), { code: "EIO" }) + vi.mocked(fs.readFile).mockRejectedValueOnce(eio) + + await expect( + safeWriteJson( + currentTestFilePath, + { b: 99 }, + { + merge: (existing, incoming) => ({ + ...(existing as Record), + ...(incoming as Record), + }), + }, + ), + ).rejects.toThrow("I/O error") + + const content = await readFileContent(currentTestFilePath) + expect(content).toEqual({ a: 1, b: 2 }) + }) + + test("should treat corrupt JSON as null during merge", async () => { + await fs.writeFile(currentTestFilePath, "not valid json", "utf8") + + const mergeFn = vi.fn((_existing, incoming) => incoming) + await safeWriteJson(currentTestFilePath, { value: 1 }, { merge: mergeFn }) + + expect(mergeFn).toHaveBeenCalledWith(null, { value: 1 }) + const content = await readFileContent(currentTestFilePath) + expect(content).toEqual({ value: 1 }) + }) + + test("should write incoming data directly when no merge callback is provided", async () => { + const initial = { a: 1, b: 2 } + await safeWriteJson(currentTestFilePath, initial) + + const replacement = { c: 3 } + await safeWriteJson(currentTestFilePath, replacement) + + const content = await readFileContent(currentTestFilePath) + expect(content).toEqual({ c: 3 }) + }) }) diff --git a/src/utils/safeWriteJson.ts b/src/utils/safeWriteJson.ts index c32dd92ce5..957a0bb20f 100644 --- a/src/utils/safeWriteJson.ts +++ b/src/utils/safeWriteJson.ts @@ -15,6 +15,16 @@ export interface SafeWriteJsonOptions { * @default false */ prettyPrint?: boolean + + /** + * When provided, the current file is read under the advisory lock + * and passed to this function along with the incoming data. The + * return value replaces `data` for the write. This turns a blind + * overwrite into an atomic read-modify-write, preventing cross-process + * lost updates. `existing` is null when the file does not exist or + * cannot be parsed. + */ + merge?: (existing: unknown, incoming: unknown) => unknown } /** @@ -54,7 +64,7 @@ async function safeWriteJson(filePath: string, data: any, options?: SafeWriteJso // Acquire the lock before any file operations try { releaseLock = await lockfile.lock(absoluteFilePath, { - stale: 31000, // Stale after 31 seconds + stale: LOCK_STALE_MS, update: 10000, // Update mtime every 10 seconds to prevent staleness if operation is long realpath: false, // the file may not exist yet, which is acceptable retries: { @@ -83,6 +93,23 @@ async function safeWriteJson(filePath: string, data: any, options?: SafeWriteJso let actualTempBackupFilePath: string | null = null try { + // If a merge callback was provided, read the current file under the lock + // and let the caller merge before we write. Must be inside try/finally + // so a throwing merge still releases the lock. + if (options?.merge) { + let existing: unknown = null + try { + existing = JSON.parse(await fs.readFile(absoluteFilePath, "utf8")) + } catch (error: unknown) { + const code = + error && typeof error === "object" && "code" in error ? (error as { code: string }).code : undefined + if (!(error instanceof SyntaxError) && code !== "ENOENT") { + throw error + } + } + data = options.merge(existing, data) + } + // Step 1: Write data to a new temporary file. actualTempNewFilePath = path.join( path.dirname(absoluteFilePath), @@ -220,4 +247,6 @@ async function _streamDataToFile(targetPath: string, data: any, prettyPrint = fa }) } +export const LOCK_STALE_MS = 31_000 + export { safeWriteJson } From 871bb982db4428b156dd983d6a8ee35538c42446 Mon Sep 17 00:00:00 2001 From: "zoomote[bot]" <305051434+zoomote[bot]@users.noreply.github.com> Date: Thu, 20 Aug 2026 21:17:16 +0000 Subject: [PATCH 38/66] [Fix] Chat controls fade into light IDE themes (#1298) * fix(webview): adapt chat controls to IDE themes * test(webview): cover theme-aware control states * test(webview): add visual regression screenshots for theme-aware chat controls --------- Co-authored-by: Roomote Co-authored-by: Elliott de Launay --- webview-ui/playwright/vscode-theme-light.css | 1 + .../src/components/chat/ApiConfigSelector.tsx | 8 +- .../components/chat/AutoApproveDropdown.tsx | 8 +- .../src/components/chat/ModeSelector.tsx | 8 +- .../chat/UpdateTodoListToolBlock.tsx | 87 ++++++----------- .../__tests__/AutoApproveDropdown.spec.tsx | 58 +++++++++++ .../chat/__tests__/ModeSelector.spec.tsx | 14 +++ .../__tests__/ThemeAwareControls.visual.tsx | 90 ++++++++++++++++++ .../UpdateTodoListToolBlock.spec.tsx | 44 +++++++++ .../chat-controls-delete-dialog-dark.png | Bin 0 -> 4945 bytes .../chat-controls-delete-dialog-light.png | Bin 0 -> 5113 bytes .../chat-controls-focus-dark.png | Bin 0 -> 5327 bytes .../chat-controls-focus-light.png | Bin 0 -> 5233 bytes .../chat-controls-resting-dark.png | Bin 0 -> 5187 bytes .../chat-controls-resting-light.png | Bin 0 -> 5112 bytes .../src/components/ui/select-dropdown.tsx | 9 +- .../components/ui/selectorTriggerStyles.ts | 5 + 17 files changed, 252 insertions(+), 80 deletions(-) create mode 100644 webview-ui/src/components/chat/__tests__/AutoApproveDropdown.spec.tsx create mode 100644 webview-ui/src/components/chat/__tests__/ThemeAwareControls.visual.tsx create mode 100644 webview-ui/src/components/chat/__tests__/UpdateTodoListToolBlock.spec.tsx create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/chat-controls-delete-dialog-dark.png create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/chat-controls-delete-dialog-light.png create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/chat-controls-focus-dark.png create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/chat-controls-focus-light.png create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/chat-controls-resting-dark.png create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/chat-controls-resting-light.png create mode 100644 webview-ui/src/components/ui/selectorTriggerStyles.ts diff --git a/webview-ui/playwright/vscode-theme-light.css b/webview-ui/playwright/vscode-theme-light.css index c877cea470..3edfff4899 100644 --- a/webview-ui/playwright/vscode-theme-light.css +++ b/webview-ui/playwright/vscode-theme-light.css @@ -22,6 +22,7 @@ --vscode-list-activeSelectionBackground: #0060c0; --vscode-list-activeSelectionForeground: #ffffff; --vscode-toolbar-hoverBackground: #e8e8e8; + --vscode-panel-border: #cecece; --vscode-widget-border: #d4d4d4; --vscode-widget-shadow: #00000029; --vscode-menu-foreground: #3b3b3b; diff --git a/webview-ui/src/components/chat/ApiConfigSelector.tsx b/webview-ui/src/components/chat/ApiConfigSelector.tsx index e370296ec3..ef5151a00d 100644 --- a/webview-ui/src/components/chat/ApiConfigSelector.tsx +++ b/webview-ui/src/components/chat/ApiConfigSelector.tsx @@ -2,6 +2,7 @@ import { useState, useMemo, useCallback } from "react" import { Fzf } from "fzf" import { cn } from "@/lib/utils" +import { enabledSelectorTriggerClassName, selectorTriggerClassName } from "@/components/ui/selectorTriggerStyles" import { useRooPortal } from "@/components/ui/hooks/useRooPortal" import { Popover, PopoverContent, PopoverTrigger, StandardTooltip } from "@/components/ui" import { useAppTranslation } from "@/i18n/TranslationContext" @@ -153,11 +154,8 @@ export const ApiConfigSelector = ({ data-testid="dropdown-trigger" className={cn( "min-w-0 inline-flex items-center relative whitespace-nowrap px-1.5 py-1 text-xs", - "bg-transparent border border-[rgba(255,255,255,0.08)] rounded-md text-vscode-foreground", - "transition-all duration-150 focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder focus-visible:ring-inset", - disabled - ? "opacity-50 cursor-not-allowed" - : "opacity-90 hover:opacity-100 hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)] cursor-pointer", + selectorTriggerClassName, + disabled ? "opacity-50 cursor-not-allowed" : enabledSelectorTriggerClassName, triggerClassName, )}> {displayName} diff --git a/webview-ui/src/components/chat/AutoApproveDropdown.tsx b/webview-ui/src/components/chat/AutoApproveDropdown.tsx index 8a5b8adfd6..f0c64e52c1 100644 --- a/webview-ui/src/components/chat/AutoApproveDropdown.tsx +++ b/webview-ui/src/components/chat/AutoApproveDropdown.tsx @@ -4,6 +4,7 @@ import { ListChecks, LayoutList, Settings, CheckCheck, X } from "lucide-react" import { vscode } from "@/utils/vscode" import { cn } from "@/lib/utils" +import { enabledSelectorTriggerClassName, selectorTriggerClassName } from "@/components/ui/selectorTriggerStyles" import { useExtensionState } from "@/context/ExtensionStateContext" @@ -152,12 +153,9 @@ export const AutoApproveDropdown = ({ disabled = false, triggerClassName = "" }: data-testid="auto-approve-dropdown-trigger" className={cn( "inline-flex items-center gap-1.5 relative whitespace-nowrap px-1.5 py-1 text-xs", - "bg-transparent border border-[rgba(255,255,255,0.08)] rounded-md text-vscode-foreground", - "transition-all duration-150 focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder focus-visible:ring-inset", + selectorTriggerClassName, "max-[300px]:shrink-0", - disabled - ? "opacity-50 cursor-not-allowed" - : "opacity-90 hover:opacity-100 hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)] cursor-pointer", + disabled ? "opacity-50 cursor-not-allowed" : enabledSelectorTriggerClassName, triggerClassName, )}> {!effectiveAutoApprovalEnabled ? ( diff --git a/webview-ui/src/components/chat/ModeSelector.tsx b/webview-ui/src/components/chat/ModeSelector.tsx index b436d92225..9e6a5a3a76 100644 --- a/webview-ui/src/components/chat/ModeSelector.tsx +++ b/webview-ui/src/components/chat/ModeSelector.tsx @@ -9,6 +9,7 @@ import { type Mode, getAllModes, defaultModeSlug } from "@roo/modes" import { vscode } from "@/utils/vscode" import { telemetryClient } from "@/utils/TelemetryClient" import { cn } from "@/lib/utils" +import { enabledSelectorTriggerClassName, selectorTriggerClassName } from "@/components/ui/selectorTriggerStyles" import { useExtensionState } from "@/context/ExtensionStateContext" import { useAppTranslation } from "@/i18n/TranslationContext" import { useRooPortal } from "@/components/ui/hooks/useRooPortal" @@ -223,11 +224,8 @@ export const ModeSelector = ({ data-testid="mode-selector-trigger" className={cn( "inline-flex items-center relative whitespace-nowrap px-1.5 py-1 text-xs", - "bg-transparent border border-[rgba(255,255,255,0.08)] rounded-md text-vscode-foreground", - "transition-all duration-150 focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder focus-visible:ring-inset", - disabled - ? "opacity-50 cursor-not-allowed" - : "opacity-90 hover:opacity-100 hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)] cursor-pointer", + selectorTriggerClassName, + disabled ? "opacity-50 cursor-not-allowed" : enabledSelectorTriggerClassName, triggerClassName, !disabled && !hasOpenedModeSelector ? "bg-primary opacity-90 hover:bg-primary-hover text-vscode-button-foreground" diff --git a/webview-ui/src/components/chat/UpdateTodoListToolBlock.tsx b/webview-ui/src/components/chat/UpdateTodoListToolBlock.tsx index e851284505..33e557a61f 100644 --- a/webview-ui/src/components/chat/UpdateTodoListToolBlock.tsx +++ b/webview-ui/src/components/chat/UpdateTodoListToolBlock.tsx @@ -1,6 +1,15 @@ import React, { useState, useEffect, useRef } from "react" import { ToolUseBlock, ToolUseBlockHeader } from "../common/ToolUseBlock" import MarkdownBlock from "../common/MarkdownBlock" +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogTitle, +} from "@/components/ui" interface TodoItem { id?: string @@ -430,67 +439,25 @@ const UpdateTodoListToolBlock: React.FC = ({ )}

)HSOjVM`(&bK3kBJt;p#l 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%0D3USsty(QiGM-t|(Q{zGi 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 literal 0 HcmV?d00001 diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-3-.png b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-3-.png new file mode 100644 index 0000000000000000000000000000000000000000..455dc7d068b5f8685368b45cdb778c23ae02e434 GIT binary patch literal 40472 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 literal 0 HcmV?d00001 From eac2f0c5cb00137f78aab3251f803d4708bf9a44 Mon Sep 17 00:00:00 2001 From: Para <62068271+murd0cc@users.noreply.github.com> Date: Wed, 19 Aug 2026 14:20:13 +0300 Subject: [PATCH 31/66] regenerated snapshots with correct playwright image --- .../__screenshots__/screenshot-1-.png | Bin 93655 -> 136546 bytes .../__screenshots__/screenshot-2-.png | Bin 49081 -> 70384 bytes .../__screenshots__/screenshot-3-.png | Bin 40472 -> 56888 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-1-.png b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-1-.png index 346f214dbe7e895ce058412183794c33e78cdb2a..53c7200cc7c055b825b2ab2e22ea32e9c995c070 100644 GIT binary patch literal 136546 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 P<$}73wsQGni=h7n$7DL& literal 93655 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

`?) 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ξ?Ym#9#&V%IblndOuL zjAKs3+kPg$c?(^0RJMVd25FJisVEhtu+m!G6t>xHu8h?QoOwMw9vm4xxUy?fmm8`V znz}YNwa!)-$8i4|=2>IRe<@GVF243c7TTHi7Wi3vpE=jhFOMj_SLa(=T6k@;qRP?~ zIjen=vEN7`u6H<(yKsLB1~ALH0YqYnQqI!y@;6mZ*jRm!Rg1Mh1NH?+t*2z9ybIDS z1&=Dc(879J4-XI4VRk-qrE$6hlQ|NG#Q1%3@M5FZp4f>6TAgl6?owGur`m{H7I7UT zheW&`QL2W^C=z>qndYba{85ybwCpp*W_LJ5;3 zI-I-+#IFDwu*(71PId}xA}7YLiHcn6N6+g!xozeI>Pb~7{{}3#UvPP)MY$D2&8@~$ zt3mp($S1A(#OL|aYo)m_yxC(MD(f(A!hvU*EtSlmVxQN;G&S<`<=SuK9nmF?HsZ+? z8OOYFQop7s?<}oRPuz)po6V+yx!!c=4iU+Pg9>z0{yI@1u+OJm`S(Y;xQOUiI;Q7) z{b>mC>(`I~>o~e6#2OyI7E{dB78|Z}lA=}}CoDV&!jfQugmQ~;@CJ7)>(niryCaIQ zu?c|s_q})Ks5<$${Mz?=7PwsgV;#;0)PX=?Vf=WuIGWFMaP;D;Cr7Rp&aqa}1vU-l$bta*^T5}MPW<^SHcT4`a#k)TzlREbMa z&!SV&b|N@S`s!lY(3`GzBV+QPABstMyvipU|!!z-V&*6NQ-D&m4UL zq>=8DYU5E{$g``mC1x#kHn)3&0H=7p$yJNk+&9h8)qw&7W-Vii}J%BM8v%=@INU^r4Yf7Aem~%=CFDFBfKG(cW#pNi8 zF80NFK4-Lm`E(l~W17;3O5)AowRd!cM??_B^5Q=F#KQFdCt81s_}XK?>-oyJEo0bh zzXeby8M2^_G$m<)W&RQ}{dXh@9Gb4to@uv100^|mfKfhJ@RUlI#R)Zms z1(fvW7NDE85}^$y1W(J6T{a%sfnhR2(K%G+JH;PUa%T=3Q&i3z&lo@=r2(fUk~)+c!w)5}gp~E; z?D%4Lk2UF?F=QiVWE+hB_LDp=f0%8t9oSu-H^DS40J|_YvV1;(zPnwh$@BwQWp`W) z(wMO3h4l3}lyhBa?f5Jv6h{#I0L)YBr}$^)AFty;fC!d^QW3A|1=uMa0V!Qk9Nh7clR9DHk*)_$E-^P`=$J7>jF|*oizbT3EnM36P>rf;T zC4omQ^t-PkBVwomZb15_B9cUj1%-_@jcCMf^UuiKgV^<_969ULR9A ze6tYl?jD`@#A&nlCRIW&y{P%uHyhu&P78TlkI+76oWFqp!ugmutt+QYn!*e$OjzqP z-Y(92&I17_G@!fvT^{Wxa zacn=unR9)pCr@QIQuN&~24z3fDay)3{C5YCHWc;!Rtf;k=QHi4ni5|QZ!yv50yUbs z^D~pMq>lrHZpf$P0%?ZtRDIJqocBK|qiOHEyEhGTa+DQiT>#F-iHu{%CD#Z8Em^`C zI>iGJZGt9dQ2`Iub-U~L86xtRIM2+!4EEr>5o-xY!dp5qqy>U5fG%VvPu{^(+CYj5`D z0Q=OHcKgX0>HB{w)rvX1`xC&nxei&KAK`n66AH)s?BqAmjN|FN>74VLc7puuHXyci zxqhxGI)iN&3s`G38IN5yxW<_TuM;Z^;*)*MUjJ#6fR4HMFUOMm8N>5Dd@+KFuYkkB zROl?Uj7vS}vgn@5w^?rCkDAyels3#tv@`76IPAWX%0zZ3H5mJ9?wV} zPP+G4o2gttNh(%i>P6ZI>Sq(T#GJ5m($UYTcoa$M2>b4R;%n*bm%NYHJV+rR={W{h zb;F3g0Vp50>LD!OY_7^&fGcC3JwS=Iik|zfQaG!XVa2G|924Hx5yyK*!%Lk5ZmgGP?fBmRDn zplGc~(6aVxv%?c3UG!y4t6TIEEd=HJVX>BxKPNdQe9;)5XdKTU>9OqD#Jb$Ps3LJ0K?87iT-z@?&l-UcfNzzTKSL` z6Gis;Eh7+49I`!XN)nXS;DmUTr4*0~q-c^2yZ->wuVY|hrl^T%oss9Jdt>%9Fo+aJ zx|Or?*$INh*!>g`5a(CILs2S`vD~nvvKV5J{fCGOhQC~^Cs$#uxbp^y$}e0(BXinn zV+jfhHl>++2v$#+{CN5Gk-y1iTciET;3eD0F__cwW=-LG%s7Lerg~9km*qi8clNg3 zxfj*I#1H$}mxEgSrCGP3SGdFPHb|VU)sEZ=m)?rMq-S~ae&jt2aoYDji(}uJ!5w=x zH8qb<9Y5o2y>rusBcyP#OZ)P-+dz4td=l5BXR$}=SsICtbU}u_&q3syW7na(KUUQ& zxrlmL20Vn-Zn&K4*Ix&=_F6@R+T+5~?GgzJe$KI>#UsQpn^- zhrAYe-s&zF($97uRSKUIs?->le&n+FurWO9HeQk;fQf)Y6;m{>)i~px(67Xj}&lWmzJ7#ChQG;{_@5#;TNGxlR#~X~AC8_$ z8qxbN$e`GS(K-*^+!WTpmtyaD6xl^tu|#qN+?J1nW*QVg*F`|wS=P~Dw-l4{h0ly^ zMPhe4N9b2jRc)RLjCIkTU&|>JvXyF0Lz~%2Th`Sjaa^ufz~F8K>Ck%8X8$}waRD;q z-^v!|+_saaV-H0><6Set+!&wiNBX>tI-kP}+463a&5*3z3w;i6V6C)%CpLfoZwh!K zO3vq5F{-)$_IDMzSM9u%Lfa_HnS)Kg_R)iTe*e9p8mFZ3KlGvMmCGum<#VycAoxw# zFq!e%h}Z75dryIfhn#1qrtgL4N--|vGML7(mqu-2wu|N3^!qcdrv%SMP^yTwhP6p2 z1?s@fvgeKdGRf#Gx_Cw>#CkG=7mM`(yD zC$DBXH6{G5bfjbkTHt6otBH5b7qNFaT^>U+4H!=%zTEj|^GA$KI9Q8^v`MLMvuOh3Rl0uReAoCB*M>&qjg;Cl; z>W(F0PZc?_)?BLFZmx1nn*#g4m3CcYpPEdV>SIm8k78#3NRjgpV51wNsh$h<(udpK z^Ked1`U(dL!zt(0f9G*6+og%eB@ObE^NQ|$Xg>e>a7}0HRfF}H&BcDLe)XX5Pih$> zk3$O@zKVHM5{hml8SW8!<>9g5-#;(=N=xfD>_~a$)x2zTn1>pjrvbyZ7zEZuPw-Ah zr7Q9%8~PwBvcI(xrDr-ru?%SuI%?wsGC0ZV%!;~_@T)F{s3&dTZU;(L@d`UFr_vqBy|$Aa(2ih(=T8SPGi)M&ZNIk zRf7+a2~aH?bG$&Sqhq9wHJnf`TC385ycSf{jEHmzT^+FCT;?EB%sqpdqc87LtiAO~ zbXBd(`s1Nn{A-L5Zf#q8zM{@y&P|bzW9P+4s(+2NB4DyZVi(*^`x2srMb6<2Mo>|f zEcSQ7#0w!4<_2A;9T6P)8$2!P7abuy9*{ly{yqVMk^~FbJ=|lTwyFE=f{h3lYj<#n zF+J`ae+dFn*59dE!f!>EWTJ-PeYPj6@O%!~ovP!U`%v@W4W+uxMZs}s(E=)+F-1Q~S9vLLS50%h+Z?AuU1Z3t( z{wcw}gAQOVFU6zP+meV@MNms?Qg;%@vlOalE|xMbV9xrmiDJ{uYrX!hs}yob%s_!%BAm4KAa0xB2Bw+ zNa5UEf3rt2LNp40KAYXKTGqzoBfgB&e>Z`Q0K0lm492G&vFUvw!G#?EHeYP_zkRMV zLjkCde)MHK+QQgrBCwGrfwDdnBKx8@c;gToZhjqQ2kT*A3QyMW5y*^N|KumW(^ zyXAsvtOR25NQYgFIVeAB5mzhu)X$>N8ew^ncfLaW_EJHNTR$!Ve?V&l{2JT46a*<@ z|GNcH`w+BKXMPa}!^An`e^r^aJ^UC@vX0&%0O(mv4ZiWv$tLYlmhtf%ny*pR4l;Gx zc%?N{Kl>O6IS#ZYsKntu1}};B;ezp>`xFQfl`)RXts9ubw-j@kXei`+O~yahj5AkSB6DUDp7Q zh~O}a6AkO&_8`5*l;wnQEEs>UM-YjPsId0k;6BYyZ_PDGRS5zbgyhl_0TZMn2?u*@ z-g^X+0-V;-ee1%(YA;O$qV1{d1zc$!4+#um^hmXi%X{)NZu})>ogT@se_&;n#v4{x zBINS7s@&wOBw<~Dwg8h}07HfBx>&Jr3af0;6hY@j$s!VYW*Lm}-?hbc@~O(XBsu$Wy5)m2n^e0JLIUiIFL;z9f}h_3TKE%c#(H4|3G6P3%0 zBgA_)LQd0~x8Y3vn{AVv!h|Tg4Mt%|26BgDsl3m>Ep;h2b~(f13ac2(XudDp7jKzfJg6%XFr?ze<@8`fppW`4I)Ms5HI`h0~Krk5;aU+Bx?nMv_>c@kS*zrQ<%R z5(lg*4{8ISos|MzYzpkyOd@2}$r!K3M2UOAp1Kkn;oEHM?;u+opckNpRJOYB`FEyF)gT+$37YvW+nlZ~my&iI|B{I14vm?liG z`_kg^Dj1hLche1@Eo1v2(^*P+BqNyE(cMR3JF+UzkIZGl z*fOC2y%R+fyff1X@9=Aj_*rB*DZArI`n?c<- z6L#|%ySvn)avqmw0f@I@q@?DwERzJGA?9yyVQv8S^$Z==u4U%J!limG;`-K`s=;V< zYTPggHBP1_!2p6m+8w&wQqqV16nrG@#-K;aD}fwaVhl>dF4!rShJf!-F^i6jW`|Dlh9eOUpKhQYNA8E=$K3$J;v7R}OaaVQ&r;=ReWvvb-vxgb|F7+fB z6W$)OJe{!_d<|HhKDEIw%lq{PsFDCv3hQbtElL*=7Ssm=p?Zk)3$sB|;VXJz$-i{J z3MTcb3g-%$t<|{-HGdz?u&R0m_bVvPd08{X^I*whY|}Vmf9M1{oLhgJMU6-bu}f-q zEOeYw1K~Egtk|^}9CQ}M1b>ZZe7;4B0mG0doj%(k8D9hVVsYPmQX6@U$z)S4L7q(b zQ}^V8^wy|8ZZ=IiGh#(|qjm-o^~Ew$8+4xC6qrr7s?zFvpHvlOVc*_9xp!3!KYh|4 z8+B65d}j$#B%jVtmsg{o1h3dJDVg!Eg$~`_8x;zr?#2SZusNtZV9hSw_@?>+83mg@ zTqAR7T8-lq}Z5K^8H3E{>xEmx1oGK39-%ZxGLT>%i!*oS+1Z| zi-!-G)bV+}XX7>2voP$xIgc;sldxJ?YsN>!{n8w5d|7op&UIhX;UM0J{LcmY$c!MB zyB3UQ@FY1GB$;mTH@x{E%CZ2rA5kai8C!U(?3=woAG!P}+E5IULP)r6>)n+iF5=JL z*$CFX`z-*D85A$3F`wbz=;-#s&5%qlYRe>Cqe}Y)_lQ}s`EsKeDobSG@ug^DQaEwE zWsky$uHOukT@l~W`o$Onv+eqDZ-f?SOe}=l!`)_XagjV-ZbH?@%Wc#hDIfJ4(g#9L zdRdIex~eamDM8@nG~e5wSDDrcLP*=T201ask9d_esPqB@r5h-`rP-%NB(1}87>16m zFKQ(TEtx4biU~U5IQ`&B+R_dfeROhS%cTfmE$7$pdkHPx#iB+9}QkM)Z<6cX!Oo> zY%_fU4`*9ODhtbIwdE{aDu^KQIg_EDM=ZnLzw`U>w;To|?Ylr-jQI0*Ry+mqQ~PJE zlR^$b`D2=kh*F!`@kqXs-4zXK>%$H7Fln3PW%w{@>pD2&q>miZql#Ad+;W*z4JJi^ z)gVJl5jK}@c#wyu8_>&G`kHyktQ)JT?8ythSD&HJ>)en0ANu^oO!82{{Dl)zhI@P0 z&>QFW^7sBf!ZnAue!R_ugEE`x`1dJ2oLMY*@B-i5y273QY7{MlYY{Jky%aSEB$--1 zZxsBp!GM($*t;nfJ`;G}FvDTiO$8O=h zAS+W#rY`B>jwhEZNvz2cV@JhAY;6mT!C0R}Yox1^fH>)3AwQF?+j_Ac)>$qlv0(^x zp|szYms9eea9+Zl6lkerriPbohQL0U+6I-&lAkRX0~s@f2FYgm>n z0e&D|3*Rv~oOpCSg;xv14mo*v7?jR*u9_;tene&ORzEU+tkoTFN?(5ybq(5J=VYWa z313|E&YK9SNrQ`gfDo18G@;~ShLw!6T2jar9Y^0^eS1HEhTU>auPq@*O{on~5w zCI1sAA$Dn(T`Zwh)ASf(a_1z0n+)F#!r2p8Mq4pus!cItv&|^93sXHxZ$@8YWF8$( zz_rD;AVPjbc5~BJ`%Wf=K`Caz>^L;vsW{|dEfyTNB!hs2lu&>h;;bfy$eKo+L}#xo zS*pU}t_ysTEmGzT)1=SB(Tk)?Uv%VYh-o>*zmAI=_-}#5O4eA{+GqZ$##r4GeGt=( z-RSjW#=FYm-{z3W>vI>I;Mj#srUAp|uQ%Lbg89!WWA_^>TKl+x0TzxQ%^( z_GR@twz^KB9{WP&3uVGrO4Y)FZ1!}SK(GWg$P@in(A)K2Er)Cr=(--qLh#(jpusb> zih>LlP`+SR)nct398A9)17Wq1Drg0vvA zLjaju!MB(GCl^q0N46gavQVAHXRzLN^x{Fq1gi)&{49o!l$o+LvYDi*a&Gz_c8)EL zpN*+rEp{pc8xU-wp@ve4KBTE?yX2)_Drky08$)hsf9>nKXBE3nfdpPuya3}zfX-Sw#AdPWhQbXlt? z;rWs(_HL{wiv>DzlK>h8C$fn{#j@`IlpuH(*wRr@RjSV3L`{Vpqyv$Jb|?J4mQj z-gqGc%Lj|od7*TQTRtXroKLV~S9ZL(kvgJ6N>=OONIMWCce-2DhUJ!PV zTZQ@uSs+F z_!nINnVH36RrXjBV9=E)BvLoY4Yp2FEWS@yNX-b+<>bg#Zq&p7@#R{&^AdNwKODMK z_c5ukWhSpN253#0z}G^|LdMKB5SjFvqblNoxroZ4Q3xO=Li~&1F*$&gy86mwn}7ws z?&)x165E5aiGx%}%W`JXkGv6e2yJ5o*0WBhi>+M|svZ9QKW@U7?!Pks)Mj!vsXs!t zYP6A*H+-+$yO5J==Cx3sqB*SOM1VY&#Gp}@U1C9!HdmUZg2!T5wN@N6!bk|ovAhSG z-(S2Fb76n&mXDSBFYDx=S2sE|ZDa^xM``u0S-5^ed+aq?J|~mpI+-1Wc4?ZYNrkW| zAz8@wAKXMU_qJMoOQA~`1}2@+9#;Nkc_VQrhLz3mz28w)7$v}~G0l}!Yx{KT@=m`< z;Em9tSM0w+H8eV_C6v-nTRld4T`B$Ha_k|J^~Z?B%eHk!U`6{9Iw!P8dvVg}Z<9xt zN%?p+wSR+^{s5z-L3n(eE#HTOF1E0psZed84E65=I^b$7}w#jv;-#J?tYYNvnm<%DRZzOwp zk=3YLQ8I1fjA|&qZ^FnYC_*ssW%u#Dlo6;E@VzUyQ+)*1ohY@FU{!(z8!H);O%2jj zb0vcq_buCV&6$EY{6q%QqQZLmY_VM156W{B#gPSSE>dMhWPdCwpY5;97wjJFj@^ULL1byp}%Pdbf=o^e~O4W66U|84=U zMTN7>CF!O<%<mYOX3^F+JJ{8u;FapnEs3ELy)Pm`%z6ilMa1 z4VVgJD_IEf3~2fB{Eusv63LE+qYhPjFqmvY941}cJleW-HEV)fl2-$JX6!kv-?A++ z#8I#@zb2$Yu#vK80=|5h$fe3wd(vy@M%jXezCR39Az8wSncmwiO129c*O(4^qJLmG z^peRypD+ynrZv}qo_UwDM=^soh@~b!nYg%=SWG3MS6u$5K-ZrEVEXmpblS{Qkxb8k zGf;(!QlhWtA{;x02H<%GF>^kya=0y*oXb56=n)Tx%AkkK>s7d5bXy^^yHO5>>UI&l zurL}1JaX1Lt@I)+Z%*x$#DSL=Dy}&kh%C$(SYG z6vI?p$VuTS4NiMhs4A(~7b8;?qYS^{+aOPerb0~1%9Ng6_ZZ^8l!q1(-zIZTS2=6+ z!X3*}vp5^zs>!n|K-becXFX<1KNS7|p6dy6T1V8&2p`i0*5n^hWY%8PttD2# z5NWL+#O7O)ENzvF%}aE73!tIN$BT=XJwi_f6PBG;bsE#LP zN{{^8jStcVuy{`HD1=xkK# zy-1Ta+S8ay&?xM7MD!5|oBA1?yPeT(1p-!x_sn~UYSg6&>X*vv1sXv;;`|uSwVL2|vTz&G0 zjq8ADckV5~&Cb{Nt%ANLO?Iwt<`)p$SJrfuR9DVVyI*W}JojGzod?E~U4Hv*b8g+& zJpej%WmUj+(B@o~k+JMmpk*7}ccFOMAf~wyrz`K@L+N1Z0d|^Em+$!%Fw$+9#t#5& zv&~y?P#4wb-*VgRH*H339AHt1ypB3Nr*Z|}vgw&v8)%o|0E_qsr*EqlV4Y+TJVq)r zLcQ92Jn?_ViTFdjopPI7V1}G8{U3yLawP%hyvBrvS=4FrSNb#=m2a|4w3j<$<4Tn} zQVF$H91rqTd`q)|RG}L)Ee`b1I(k1v*W4i4O(dbRZu3cKQ>!XpNMpREL!M! zURQ??RdAjs350n58-LDOJh!aXeO_^B;eVTf?9Z6Uj6MGQVC1CJWv%d$q~!2tb=u0% zOXs-|+w<=Y?6knG`SIN2sm^`N)0Lk8)|!A4|I_`tqm9A0AA=c$j$Qk>)4$uzTIenF zx}AZ+)wou5;N8>P_TOfMx+y`2{;S;F=F`pbX~FY@0X^oA%LmvpJYAGNzg@nf1+yWX!1Ed^CYv z>Z$W~NFUpbWp)WB`h!~V7C!Q99wopOWx2Ap`%f-kfMzvPWm1V@ldcS3s(0e?ZX|6< z`j+5okcnuS7Bz=>ohl-yDQ~3Y4trI{ce`m5Via3ZIHD0XDVTFB8sZb~Lo%22`AhLS zwruIrlV3TL=A9Mmd3OlaB^jhHzNjB}=iB1&QuXBla!@iw@wYI#?_2VV&F|Gt-R;j$ zzM{K2@TdNq*PXEj-qgqLk+R*@3#u!t_cPT(6GzcWneF~n%yO04<8&k~?CS2iJ7(DS z38#n6`ZUL_>{WN1X%=&KwU|1n@{T8q)qpVEg9|dEXL^#^$YM)sqBfgXB+GUs>CnSOUDzhjYcxW6CLjEr=J+1Cv zoc_bGEL*GWTX=Mn&Ba~Zq|GpT{4s;2p^_q88u-6#1qAW}o%$bZ?Q4Gzy|2Rh`TLW8 zU0(@cD(AXCa9vba$y?RCpUh0Zh`27slLj|1T~Xx+eC+iPMy~7WF$^!<)+3FW^0f*s z8^jV*-hJQFqyBGZP>;5l0K5Vode3I`s)qjukD_x|2l7oeM! zs60IUuA-Q&f*|9e`xGf>#3ka$Uu!KsOUkIgqo$&o8phdW=~xMOZ9ALk#g11i^HZ~U zDM=0)<)yi-Nrgp&LA0Y=)2CH6ef#UEfGp0fmJCvq7=2uVJ?l!np^TA@(SXGk0?zvW z9`0kie~=;rgI*sA_2kz|{dsVp-w_ZF=vZmNCjwH{@lyxR2b@NllLmoC57fETK_HEe zkxl0l-fmuVW@H||1%p$o9&?AdQO8`8LxY2BMKA5fyeVOX;Y>NkcY+UlV*QWr0kIV5eBD3`IKMbnWR zb;`xW$;0A+TG76C|BfWRcROcQ>5+;oOx>i`;Qh?jR!yY_wF2qH;CjXs7Hk!DZ?|PT z?`Ga)``~Apz9cd}FLPo8#TCDZ=KMjpTpQ0*Dl6MC)}laRWqXNl6a&!El8#s^G2|_; zaI9Q8f2Kld%4PK7?_46gFy>$ns|%9y4^iv&l@%#TCP)ZYx3mh<5EC8B+?ud?$V{=& zr}(#Rp8!Ou2?>AN zFa=~4tHP}Z|DqP>6#L*I+QAMc)l1J}g|uZn_x1ys)A*9WXgoC4kk!ll5fG9aP*&N^ za?aNA7ul-n)$!8`fcpn9x@4g`}?`qsUaSZh_KP#jFOs`&5{wHpjxbC7Za?e@ZX0lq4r-32E9a+Y*tGEn!ScOld#;EL4}3BEV?AK zY6LV=vMEvx8*qV!=NMZG`ePvIGIa$^SvKu>&}C-XGBF)?|DSK=wTxM*F@XlY7^9P} zNsnu}=`SB)fx~}B-$RH~OB)u4bVX%3lN@t0v7s@8VJ@Lzl{_(n6;n3GV*y~I#M0tD z?*z;f zyP_@fyYF|CF$G#cgUsn)Q9v3T5TG9|$0lYXFTtIhaNOfuCU%cGHp3Avg0Xm)KlMfA zt2vyURhijKHRRs9r-Py1%qk_0YP8uEAzP<5B`OZ z!P6F*v}LRq@c=)1cOKp46n`ctp1VwJ?vzmdT9yLz_4=VEs+DK~DoY@#gY=nOT3R}m zC%*m2Kg^MXN5ZGEDl0O{Z)t zpO&z!@@@G}H~V7<+E=*+80MgV7wEgCEeCf0+29FOa+6d4(=bnn!rMivR}p*TpI4of zCRee8?ObCEXNG*XQE25|+^%iT-)|wFls$PAP=~O+zP+6w|C&5*0j3K7Zh@nws;;~L zM}q=hBetAM7@OP~jW$6AA6Y}yx=6#(j!=G&N_=&$!qhA4VL5TRDXiLvs}*DDzary+ z{w`6OWiik?m6wlN)~62I83CHNfFgG zfinB4NC8@ISj7PNDYAoSq+vt2z23LnT3c<&gkKstKsy0&t{QW|kutj$wy0!?do)_=An-(zRuK7PpjB{CjzWegU&rbq&jV`LkZ}3iOlo_`U=hL5>2AYNT5S zQaH91%ji7OS&hPS;#|*^yc5IB|8@c94#3|t@MyV^#Ux9T@!3f8qmmq)z*`&Smfw<; zw{$tIqv*z~7VD@|*cgGs6*0MFl-K^Thqpo6W~cRH7zy#?F~PcRPQ+G#YPHuMkgC>2 zlhvR)A7ob=jQnX5m6;K+4sLspMmhrxTp*$YHIJ-(%zIC8fP4*IC3z(AD`k zu$%v0E)}2^*T&0b%M4S>Vf91a`ox2lywm#9_o!5@hwd%=z8DT-M`?nIiQZv8;Byqi zC|jwV4QIG00P%(I$dpFeP9+l4GaWBOp#E#rrudrS9vx|7RgY`m7*p(BQtt+88$dy1 zammcC^bC&^O{F&i4~cL<7*Qo8af?r*rqyN|tq=Z@*-Q#o{=8tPnRocVT!SJyjD#SY zhvG3p;4$2Upo^*GkX88j>#{M_H;$7Ut*x6D(`!#Nd*`xO3}tkV8tr*9XXDE{obgp} zsv6`amHSoFO!c2D@-_B6pKkD+%-)$y(X<%r%%Ez)dO)^G3I41Lr~L1`@!F_Y+p4_H zA~~!nWn;b-(L$;+sLqjP`uBI~IL7=WJ_M>#vK&KFReEt@s;a33k}gXIm=Ll2+8FU! zU#{xSz^eME-gLr*?EKzzR6BU7AITnkm@STR=WNQpOK{7Beq*=9 zf4Df71C7#9Sc}_`4I5O=^?FH~mSt%P!C*V*<>rU;cIM}U)BX!y5?l1U3qKLJjLz?Q zn|5|nX)p*5NTk`&W9CHc9EhPeWp8aVs2;fTyulxiD--J3^I=Hv$LGZ<8*ff4~=4F_0`#p<1K zm%5EN;snrJNodvh2PFNq`kb(p7M>@T1c>f5=I$~yU#+j*!}q4dQjKy6*&N@=v49Md zW74NM6Ne-~7)-sc!ULwaCIlA>K7xTHz%90G23259EDnAoIn+p6K6oj3p^Cj#cX$ll zaygX7Z*6iO1Op%+qkpDU6Q9tLU;-x@($DYb`^aqjvt-cr*b}IXJFQ3?NKB^DY71*x1Wx%Y zj&(*`3(H0nJDUBHrhi&Xz8SQbm99B+_5aH=na-`u4+kg-N>rjY}^A4c#+g- zNOoa1oOKFmYFvFfE->_55N3^_18=n=~TKf0$U zse`HwODUTrhpY;i1cD)zN+4g9$7H{!Q(_-aDo2G9_2BT6)Q1qiA(vw79VHFMQbfI+ z{=zf!a6rcmHKv+zg6NT$ABe%`|M#7|Z~vN7Izi#$Jhh7R(Qy=k!3`sGPnA=n+bk1rgx3beDBkA@&)!pZHjEv zu`MGetbF)p-!RNb;JR%&$gXE^V{@9OZFF{araD7tm1=L}K`AAdpjS&PPn~bc%E4|= z&=UtYK{#nPFk*d`kR#O%9UrcU{j}EmLxdnU3%;}$3ifM0$CK+3*Rhd93IH__<(T_o z4?}!~#-`TBKoc^MGy|qrR8Emb0f$4W;f^QKM?g;u6rHzjkzS@jW`EhbxA+)P?ROvGczB@WQk1il1ml|?a!*6yIqWeg67MrV_ zA*)B1*wWM&{WQNp9=sE(l443ea6+N&-otlV#ulb=-OYl*s$TAsFT+SD??3o>dw|_p zmx3=K;Jz4UMUg);F@-8D%3?Ezxs2asXXOsLVKnX`Duy4KQ2%`xTCC)V_XO!CWms|I zcWf2yI?DO20kp+4q2j2u*m@hm^L4+M$@obVl+^>WE7jNihlI2-H#W}4u`G&mTiQ*? zty)LGk~~e_h{7q(48-aq9q!3-9HYBr)TmQS?f1S_8MAJ(o*mJf8_R(z90k|bpLd35}E*TK)SCCv@shLD#xBYVI z1AcvkYLYuLhm_2TIFp~9Y2pPY^qVS>`3Nt-5@9vW6Z(AUDm;p~4jH;u0~ zf+)G%{WkIPc_hsuOS<~`zDF6H1V3GZq?5)BV>QeU3L|-`F`YXvb^9FNTiWeWscg(S zCzZj?JN&7ZbJek|Kx0^gg_)p9kJH!JRj#Pt?Iy{bvesn(r$@-&AC=Uo+X{J(XnEfh z?3qNTY<_;*YaAK`@8R(-cu8~&1I4=Pberkg)2I@V*f`qiwpl&>=4(P66fYIqZaD0z z_qZEa{8Ph(9Z~MtTBp~rS(ScQrv`wyGnZDPPSHHwSHv_9vQ->p%$P{u`ZcOU3Be=J zOCO%CNXf~l&L7d-+D!00QK?Mq&txe_uA^gjBntA&b5}<*Y{3a!>hk9SIkJL`+uQN@|zsSi`=>M*5 zIGNFHwAp*CO)wN_-Fd0ZD_*`oIOoVzYgxvhkOKVtE5-6NL z??DBydX2yvmal!5TLxwb7g+~^bqDufSei6*HbLYiUxo9Z6=_Q^9a1!l=V=UAxlBC9 z4}0!^e&x{}xj(aB^NpTT@t9&D-8GJUO2BHBR6w4jp;Dx!_tfTfkZ0+s! zD+lajT7&qr$2_f0XX6t+jFHqAAO1_OMh6#~7Bl@;c|)-2uzb(DP=+egx=D zRNFqAa+-Q@4}+m-xIt_4F28YGAReT%2)P}Cn*TFhK=gx3>q+Az^G265DROcT#b%sx zR0%|qgV3Hm*MGm5CMoNB(GRKT| zZ;$eIh*u4y^ss4>!cen-Sq@ZhoXAp20u!>byS_d!r*92($UAM08xau)v`Qi##}Bh2 zsEO@fS9&Ht9+9#YriIxq1q2b$k5noOe4siu}<)L-NyeL|1#??NmBq491VH#VC ziS=4Rc5kx}{xU^x!wOy65fkV~tHEo+Z+19+gn2Pp>+8ZbjEp<=;&@BQfnR{347Cn% zy#+ZION9;Z2YVc*_fUqJK9Bda181Sv-B3u#Sy|)t$B&D;-mei)cjnx{#r%K!d0PT7 zdJ~ckKuz@2{BI z&(2^;e0Djsw|&-paiNykkJs96UWLQvE|`CROfb}WBu5(xyik9pmsn#HpJ^t7O^Q=v z8$==nQD;6JQdF<@aB-CH*Y6s;%OQ!sF|fYZG}C2k*>h`imav1z&aqGZF%G<%D-=)s zJek%9>;C~l9^+Bg1T9K^bo;-AK+opzpvGcS#_lOu>#qxx7ZMeQh#P_Ms=KXtmhV~S zx*;7PO9_7a{ntw`>CTwWEFo@-vXi zH*m2`v1j3XQL70l2wm`{LT;Slm8Pjkl(xc#JZI=bl%J)*onbH9Hf6|aOh?P4LFoUV zHO~cI2<8p6g}vVFu%XOEIq2MDqJyfV;jomi^e<#(&MtRd!!(jekIY4SGL2<*`G#77 zo%sbiEemacjE$TQ%`s+9Dg9f#)CQo@x!V-$fEodG*p>2I&-^MZ{H<|9g?VP+HQ4#2 zv%W;~?IB@a;=e;Z=10N%YCZn=Ye~XC)w)eS;~2LF3MIJ40j{jZ1#fzJBOW;`2HoBj zo@x5UBfpq66gNu%rXY;S}1W@9gH;N2f{xE3{JfVwLb&S zIWi2~;J*=RZJECaC3-QY{s7T$&ASc#&Pu=Wh;&|!l75cS5^w>C@S$)N>`vSH<(Tm* z57OaOC5Mx*op$MUtW2V2g&sa?4ZDtK@?pQjQjQLyiU?{jM!owY17zuk_UM;j5hJ_~ z2P08K%L|CA#p^M^iZrXV_9S-=Uc)Hxicwdh|MqLu16@&@vremEN&Jv*kz;Xw?#`+Z z1Nel=S0niUw+p}%WOJf? zrWtt_=aK=qQ6zc*D2}!RKheJGlPuJ)sBQjvI2N~f?`n%f)zo25m6}}u`6-eH76$&- z;Idr+zj7LtIB4M&kw?S5_Ah#?vJP0E|=LG3J&(R;+J|rGV|7PoYm;yT*7iV`^|2`t)YGOoB2f~)m8ZX#c zJN@1(z5-hNd1Id_8`Fgx?&TF43Wer)Um0@xvz_avT{6pbOgO1HXY(`B{3B=;GNoZG zxamX93F8eup(QS$GKO&o0~D*-+B^Q2sNCloL_;R@O%N()Fou6~L))Ehg}KUek((C+ z59$^1+s5xV#P*D!;UI=RZMZnG1`ZcygVAYv$xNg^dO9@J5O7oBUC9SrW@tOe*q`ri z5nSQNP%4krHJaY2atz7*umv*TXf4%iv<#0trhY6v5^i#fV>5%*K*kI{qtb-DE9Y<% zw_WadgUyNBNk$;nvrzq_YSp)`ukqVu2c|UWTZ+6V{VW`nBrn(`FV2dp0 z`&35!l_zi*Y(16|p?OuS`#d`L@a4bvj>-3-2kB=4o ze}g|>QBTnndcHAfT=U1D<3G73b^HB>M;yrh(eT*Shi5AE%Y7xw=72+41o;>AG+7Y0 z4|x4aaGp3|wzwLj7Vjza=a5zfYbGTtV&7R$w?EkfM1%>hXx6GKUGRAd^lQo<^r^ej zG#J7UkUx8S^&Y2KbRj}rWH*f1VnC38e3)wHK5#^PaUDr+ryaJq?}DIFG5|wtdx{uZ z(o~0BxVYE_dWRe_l)fnz31GrpAj+i&xI3$W&) z%==8D%s-JJUmyte23s@Ou7WWt)BSNj`I-O@k-hdfAdffNNgLG2H|UTlx2LS(Q{f2L zN8}|Sm{1z5eF|x-QIn1EkE2I{aK)n zy-!%ou;CHcmkNbOL!PEmD7*I`XsHQUAXI8k&drdA!5TANjBv|F?=!9^>+CAaZTNb$ zH8eyOz6EonR|)#Y@Ber=>W4zQ4=hMASo)Lv3p&=hLZyWAvu_tI!rR4W)vIIy`JFd2 zH~`#$SWJjkfQa8_Csd9(N$Ck0W%uu67Dq&ExCIUJE~F9_rko$ii{Ux`5R@wCYr0Af zogP$AzP)`un?K4U2s|Tx6eHlh4KWodw@f&!(-Mp4p`{7WVA(U7CmtE`@P^M}9pYN# zY2(nKCPnCvvxqzbL7cO2H!j@sOiYJfjAULr;bk>FNx3K=J+3QW3j%;vEJL1w6r$6jP!C2?X3TkY!wEb)@{N@$lQSfob4cX>;-WF zwi(B8()^zLdQvA_x_W}pshSmx^E!~(HND?9I~Xz;M+CnI-k_v*xV~k#dOR;{=fSiJ z-3%bsb?-&Y@HG{v8MJx4y;h@n2;2X{JjWC-?1+Talm&%sCqXKwc#ISuAP8f)!4OSu>KqN(Gv25ru1Sfv`3<<3~aI4Y>shOE}13RyZ#re=nPCj&FC-^bppd zZ-x(oP7)t(8Au{0^5mX-zJghacpjyPUihA?#b`~)I5TFaQZJKFh6Gi8YIV zrMJ*#y$A`7QHWcX%K>(k|eADtQi_gC1`ww|G! zypC1gLkQtFWvt{YxlMQh50%y>BSOV?Msit}`Wn+=a5ZPp9Y zKgz5}eZu?eg(~tHccL9a<6aFj0bWq|!rD&A*r5}AtVQO6(3661+F^z+*VU9v&0v{f zN0B;S(}r`rnOU(YEn4y=-GRDw(2uL~BS?T%f)(*`O<0H#^{WOT`u_$N#%I%bQ0+zy{p%akL0C(R`h9tr`HFRM0lyx3j@ zp;KRe{Z?^z9_jf5;?iEq-SU#z1Oxg{ae1&~#9D;RSvQYH@18$MKLY>pOo;NVa6gcg zmn8-8j@R0${?Q_}gT76_vcks2s#iHmcvLBUo3I3N}{FN3wU2Rb2l&Wm+?@;lH*!*adf$}q+qqhpx`{(uEr$IjsOxnw|3a;K;&+ttq z(%new4eg4TP%eG$mmimj)#9>WHSm1Ur(OU-d3F_5>xg?jcF}@^GvQ^BlIfkjiHTo% z#FlH))GgL;o8yW>#v+dZ*^Sv}5|o##7Y81N5(!OC$+%fgXXc=Fhw8+|F8=Tv@KUoq zaOZ(m21PXuS~(=sIO3gplJ}^pB*q9+(nDYJQ}@)L(vp=1j>Gmqxh2H`7&F~hC%SYj zphs&lk)O?J;xrd6UE-+Eru4f0W`Pc!xJ~xTvLiv}2#!&L2ze=7_ltC1QD6jXx;_Ng z%p4;tSak6vYp@%v6vrB?acrl}78Owu>ZnBWAw3upEC7k_|I$f{VwoXqO3PV^IsQxO z5M~&L7$>bXB4~i>*ce~s_b}5e6I_1}TX$}jYvcBsdM9jJi!L}A0$v7~W86jw{~=m| zG}?vWwg#KkR@X;Z3lYt;04y znaQnQc5PR~M1|-m$S9Brw=%yt=6Nin$@Z{2lTx7WgE?r+Ob;x+*8YLzu<{0%MTv++ z*)RPFp2Pnl=;xJ(8|t@y8%<&UJE$;m)7L0(^w;SYHMm|V&*BgZg-WWlQZekC#1^mB z5+tP!bkVWss>+ZBMgvCyHB9QaAnmc zIOzy$Og2S2UB|U%^0fSW<5%u?9xQZaiL6CGi$lZj5oV92ZHi?EOj^#Y^f*qP2A4uSE-Dw~!@}>B3U7VY zb3+5EH?Z}d(BCK2b3;B!@Z@Ne*wuR&nK(n|f}VLim@-#39aORqH$Iu>9I!`fk=>kq53pP(G?(B`G|RJy^q?q%D-D|Wm$%} z-&V0n4P65=9!helMc-e$t-v`Lr-L}3$&+&vkNAN|@Z8HHE-4TWn#22jyM2ATCZ&3+ zPi+!9?lZW0@b-A;4mq-a0vikc618A4D~&G3OuZfv%hFBHV_zv!#KX)6gkq#jHBYyW zTx3S|@it3~^*YqTZIPeQf$S>eviZLNj~sL3ecz9y)4*cvJhisF8p$V|qMedR>hh`< z;?n=O3plZhvrG71KLfYaTMWLQ@U?F9&D?$&&dx6e4;>@rn-rB-xzhZgNTK||HS!|U zQM-A$=bluq#!!)mEp3<$MbO9BagMW8F+wyAJhjTfINH+d%x+Csw}%*360gDm1iq?u z5>zICSb>rz#ZVO3t3;!ykW_aCYzzDOT@~DQv-=$t{pA3^s^QrCH(Z4cMAYL8I>mWi zJBfX8Dg0Wgo=!e1sxfs9DV(GNEzITgQ`}Gf0kwC*Z-xnlXQ!uRNVreS!8J=N5#JqY z@s{@-a%cXc0aJzqhuB(UhcX{I*t*3V_1y74BiYRA?81zgx=VjPNfXl!$ff-LgE8kH z1Ehq!T@}U7E^OAYhnf30B5w*WOmUL^ro!b=xY?ms1qKuyPdZoCHOG|lwAH=|y6RRt zdx)|0{XX8B99?Zo3qdw#H-QSHF1n0zPtTJ7_@L6o-&d%T3j{<2Ve-oV6QLPusux$gDNOMngcVo+oO6-``+e*i=Z5l=f10Q zUphU!C6HpZb{|`cWQ4P71R>?2v8uR# zGtW3e#e+mq$j7xqt`&c;Zf@~gpozp;!=L4hkW)U*m}U(28~>!-D<<1m1xrFopOIL( z2X+7`2=)O>P^dFE%oCgHg0vw}Je!1;PelWK!A3b7ji8M)?~j=XDW6-|w&6F7&16rj zwW!5Y)f0nwQQf6^;u+48;vDkjp^1Z)IWDyLD=W_-0`ujvN?YnAw(&CY;ympMJX!WH z9YCPP-{+z%-EOOH)t@pe6-4I{-e&j~8lJboxyGr#3)xRyY=GxTqtUicMfg^E} zlUmK5UK(L*DZgl&qpXRzfPNF%BCP@D$!!Zj>h7chIWB;ujeApt4Brh3(c1k!Vv!mO zz<2b8NSuWH;KS>xnzy5JE#A)UQ%DFKa!Ny#1ept#H`Z>PG!*FF4ZP`C_ei+5f-t&r!_gM`wAXj`8xh7>nnM~f2 z2RZ0LdACqJ5{2X}hvUcghb2S6#-DX@WVfI1lD!uO*fz>%LJSKQ_E4dNp|D;~0?p?3 zFc_V*?wW|Iv2WxFRiq&0oEj3XGBdl?^rh2zuvA<@5}w&gBa)0Q`uVip>z*nj@4#P( z&@l=Xc$J^~1#_IhG%x}R+FV41Vn#^BH!b#*93hsRX)(EpBR4N5;gmzY9$vs_yiI+k zf!ha`!cF*q$-kt$9&w@J!tYVWT5#mm4zhpX-s6|gOO@)la|8Ti=A-+8Mc{SOLvR8k z{y*Oha;Eu_db>Dl)5+eu?T9?7IVgCW^F%VMqI)NlrTk)T)hcbP*JZfY;0701lD|mT zxo91PXMZAHWlwwyV$cNa0+ra2jf8&9zEl-Va-HN6;H1B^vj~bdmD{YAK|f!csQK64 z0@){8RlT>_Dh3cKo=MRc?^G!{CMzZM$XOG(D!mp&hd7rjY`g6!uleNa>Y~r^?S#(( z1cZy0KRM*v%LyL!%B2*h%d>@Lx+z!-bV>!952#A}Y3VL(=0bWTCZ^8(V;m)o23Dbu zsoXbyEnedkRweFnW1z&JEhJ;oZFI71k%-r&&&u-!E49k)cZ>S*XB7_R*~Kv}H+gaD zNnRai_bW-BIkMvpYRIb*WS%ohIcmXb@d9vQJ*(&4-(3xsWNGp5x+-A_L?O-NE_mT- z<+{e3Q9%RF0zxgm8aMKytvFN^BzeN}wLDs^t?N>Fi~8D#DB(L_{D}F)|!z zXBI2wt026oaxhoTx|lf}-MIR(?5<=g;WXxOXTHYQ8yzAU90Fb^Re7Y~r{li)sw4<$ zC@Sd1erOEVNMF4=;qi{APWfpiiS7`a(l`*#EvYB@m5TeHE>_Z+mZ~S<$7{}Lqo?4F z9GYqJT;UAboffARIwD|dqQo`ctkW#2y|X`uSd_I^-mBhk`YB+F$+XZWgOSpiUZ(& z>h?dyhE?clc(hTJBZ5w7j>ri{Zy_8J7EgA3b>KcU*lF3i0%~1Q==Yosz}|+YK^q|vt!k${E1z2n~xQLcj4FrtGq|>eqV2{gUqLD7E+4pIitE)sm~`+Y^9J%49Ji7QSma51Q5XvYFqS%`MO^@t zsF^JUT+%mr99pm3W-dgLd#-BZ9EZAGO|^WQ?$Z0}c5S}x`PO^O(QMMvusbA&Jh*RDKk__gugXq<}{tdESyg(r}+ED#V|rPNbp<$#XPVDv=Ox zyuUEdv2iAkP~{i<^F-730G5*xfU{u^wfsh!n6Aw&Ddf-u;h2bJcmdV4b2QBbm&(d` z_*-lyU~yzi_nTd{gFY+^CGN`+I;#bF7d9lpuKDTzpyNV-D$-YL#oju5^Wymy$XY&+ zYYkXE92awSTeI4PZ-?3IL}n@2Es@hmp3Ea}@qU7V37(WyJYa;{Yh7V@YRN z*zC^EUb{dHd*rsjU9jvuMRw+2Pp~0ow->Y0MSJnv`V6Zdctg;bbBo(8zy%uerJd48 zgk*g&R4X--lm0>e@bOty;=R`i9LVDeEL&`0O_Q^1(xp*B>#g-vkFSC;k}Y(xg{VoN z4DT=Op^TItd|Lnwb-V@u?8St%Rwi`4!g90LVFS8Myqq_F{3`8_1;H}OjNq=Ts;mFrSYsXHHGN!GGR-1 zX#7!vY%?844o59NtBq<)LnEEjiz|WlF6W!t{($@oX#7hmDLm;9fA7=Og({^HIhz$d z&&?xcfTTW~7U8WI$r7iWr%PkvW3zh1;@M*PtYHuP;x_TR759c~`y~fdhF03?>&m`G zfm_GatA2V)VmZQ*s8g1O13?8>nzJ)syZyyn|L20^CX!ish<9W*=uGLbU4ml|t>N9Q zx*SM#zTVBRrRmqur`9RWfOn@b%^_>c)D8FbR79{m21)sog)0ZpS=lx0(#U^qD6xtD zP+d=`pBxmeQS{ z_-i0kus%X~Xidlxs72cGmK}+`s-bHVZJ2RUmDD5s@kZXzkSz(~4A^K03pq@1%#f$X zFXCOGEqioI`g$?T6>r=*hxoZ4~JwQ5n5xF|{Bd7Nk7;AX(q5k$gPAiu2wxkRma zlED!U6U8>@W_5R+{*JvB(R?H_9Z3>nicaOI=*w^f+6-TpJM z0v>3fnIkCS8hYj%&I@t_)T01yWoX|01QoI;M zx#?(C5VcDbHZ(ER2RKwDC-IskOD&o^+?qqft}?MTw#F=CgEM9$nXK5gLniuV_!}`l z`nWgylo4zx9}a(qJi#$C+n`4m7!W@rGF>rAtx0ZJ1aN53XQc+JG9m5^I(RZJB9@3} z>W>p9a{&jbo%rJM^=EW~r<`;S1;n5$?`3y+IEk-h{}xq|h6@?FcqRh!N}pIYk^ z8+h`winJI`9jW#8Ntt;+eJvq3ix-d38JS75)Oq0~FZb6uyP0YUupiXmY0VIY3H}Pj z7>vY(i;Ih!x!vYYnbE37R7V`F8u*BrAzR6EWHlf#s9WiAmEwz!AgF9dwe(e+G65Jo zl-rY)%85slY*!63W`a`Dd=p~%pfeE>+rYsKZ9xjpDe6+nZncf!r`c+ixMgBjLafU~ zp#CD>n6+gsk1m@|RWYp-<>2VBca@H*qJQW^d)vn$ob2p2JlYDW1qO9_=qwyrm z6TzEZA24YeVtE$ttYa!vm>zXFX~&rnq9Qt@646t)?iTq3)S}tq_W$f`O;DoViKIBo zjBwP{+=u6=@Nv5oJ3Bnq0dWLv)BB>;&#JMJkdQ2zYAW=%nJRyE0}jKe%Y&_3=&){z zzT46=eHsnd|8{DHveOIMh%nN;UQ6dUJ^>mmrhBjt=K(_7aRH~x9@4csj722u>JGc6 zkCBlNX=)wRxyd%!8^i}DQD9q9z@ik#BikIA=1EO7zf!riws?sJCH@3`05!B$*d_e# zv3SPDilJz--z1KMdiI%)I?DX#5bIkCXo4nhpXATa7eLT)9 ziu4|Q8Mn4hlLBG`GI9F;YC&*NTxD>uf0Q(%r2WR(vykV0PL|`YC_yIVXw)Nk)NeFR zM3`tC*W&Km9WXEs*(6h7-7owlVnD1!DmNBZ*^wIQtBZYaWB4JCeV0d*ZQZ+(`hBA#57U;>+E_C3OTWH*W?$#&`C`FJ+RF&Xr%@2!5qmZuE<|RA^AB#WB5Y)#eN&jshQ^G5N2`N^!VksoP8~;=sgf=UXqxt0dbjJ z)kg8AL2*WBpgy@J@e#Fr?F-(G-p?~`>>*}doYxB{vUhC299!;!+J`Up@;Yd(yvKWQM*@`ckVYmS`W}p zP@zcX-Vy&i_%1_cDl}g8{Sa@|LfS$`^B3{a6i9pZYgQ8za-q3u`&35y2P8kTMpso8 zqM}Z(#}_CGKDH|63sYI}ZV=ar<@mD$5yuD=%AH~8wYI4_+2eX4l-3`^>K>2;bVnm7 z67H$&H|qfa$4ihy?MpTK=gf#uGYXJobtV!@8g+{<*c%(l;(4-}aDW+{mifE7OA|!5I*TvDr>?h|_h6lVJ!fG3hQbAH~V7$N_g3ORd;~5D}MAr_Bjj z%ehp83QC<#hgz^wiwc&AfM^qBy`Jg*OGTlc%y>d~OHZab(8|Ho0n!ys=LzLNyiT%o zw_8r)1oThggfuOI1kO;2qVPXOzIZo4)}MrdSrFQ*r>6(xl!@Sx#}$K?88=3v_B$}F z`0r$pwZk~@X<5ksIVkPGFj+JQ;JrEju13@9jEJnZairDgm z0_tIrMK|z6T?<~Km`kofvbQeReop6KDe=|kn zMks;nXP;4jVq`Nm8trN{Sh7h7*HSzr!#X)0O|#qPA1}Va#Hez5tQP!|)s@9nQe5ufe-YZn)rQF+Tc2eA_sPxtL_RpwffjXLz&mw-%LAVGHFRk)Nc)Nr42 z#g(ebE|o(@C2gVpgf`HTBUww@yP;0HYz1yBYN9i5x-yd|n>l&FD6!@aZ z`qS!RZreTw$n?b83;_t?Dg+=EDfq9D)8wo$SM=)i{*F7$6y4++$o6p_Kv~d@4{;J> z`pVv5&^>MlyHv_R__}jE=Z5O z_EV@uyL-!8!Z<$qZfsfGIF;q5>uE*5Uz4T#aN<9DgiK=RRaVC2_cfUbgWg|Mp2VEh z%Cf*5#Wd>wN7FfYRrM+fA5k+pej}u9>{!WKEiEzR&0Pu5W)p zd#%0idiH%@=XD$$s>L9yJwSOf3*~Se@UZc)^7$e)8H=;a?vFW<>w)aY_XWK_gVfnN zEi75~A*1*sG)1ARdE|94^6>QOO~%in2gx2A*#8u;@S3u^HwFf15D1#8T16X2)hBQs*xeTMm3b z9pKcX$^rR8(m{ods`tG%D-8IO6NxV%I(SYk>LhWAyxlH!K91lSL#vF* zkK)i#1Agi`K=)B=)I)d*odNvx!Lm@^AZY7l6Rzqt1dbFWJND<>NONnkrh#qpRq1EGGg5rb z>=){kH19c`BVl4vd}P68xe8R$m7ql}og(uNrwzp6=MXf1(C*1*k6)1}aO=VihvFoF zznx@cp{)phMPi9t-XT3R0vghgZg74hQ$rFG*3Roc0I|ErahK<*3yCEv_GJIyb|Zf> zRT_7^1!XV`-}AO?f4}OV@OCagZ4BJXer;GX#W+@?L1-(@S&o>-&%CMf6~Y1>KEBg0 z2j{af**!wllso6Te|?x==)F(*Ig8-+{%6LN z=PmDI%MDP~ye*Af*iTv13<%$TNHpAUdMqeev!suKOSP zBzq$D>lXyRcjh>~?}xTDgj;QHJ{>S~RKkYb%5KKs-rV*J$?7XlN=!{6QB;cRw zQxz+HZMJrVHKD&ud`t*b<*5FNv^(biFesWEDX&v8f$m4u{RqLnee0@M+C)3Ow{Pfy z6_p<;P<@0^F*QB=)8Tv==fo;@Daqu037_3q5^HWJHTTs9RIXBxkk)50ksL)9_z37` zhTmp{UzqSIvUYM`vMzKF|%C6@J}86S=&U*!FNg{0)`j8K*aH*ot?T zszM(|C9}$HXa3&~7PDbH^nrY9%ET zO!^P_k!UhuOb(Nvb8?hQG-Vu&zI45Xx@E2W3&=hK3fm7V>LkYGaZ1%IPMB}-Z^Wh{ z!t%eOd!TdC(BOlh~7Xg`Q10T%y6?;ZWbUBu9HYhz6Dl|lFO*}&V=N^`?Bb{AG zcke+3;A!A-5+su_nW8gI_WyYKKt{ood}^~_W_g@FSc!lC=n(b=x`XPw14}Taz<*9M zNxZk0M5C_{-S#1ouY2|EDIr7G4uQFNv%wy2|v6R-ipY@`pTQr>){~UNZISN zRLXm%U;AO`y*T8GCry;Y%gu$!#-B53^2#&k=pX16m(onpBlrQ!7d-x#Lni3Z)tb(> z1)p3gq8a0zX=95<_J9%epB_J+#%hOecByWaoLRf_boFA3jrY%^%@D27@{qrVy2r4s zvu+=YjMBIXIEf2p{l(-M-oBTbewspog$bn(7MsmZ#B5vv4fh{Ftb=A(YL4WX(3tj? zmblj=4`L7APVAjkLwG}c?d%+4{1NJ_3Zb8e3IJlZ;MWL%XYT}<4L{z))Wv5q=A^&U z*L}se$$l)wb|wPn7JhmVaUnYo&qEIqUk&BnrS}&b8t`?&I0NM%`XZPRi-i0sW>kg8 z|E`^;4ndK67@|!NMnNm)>^I^|jo~C9lZn+QcP8!V;mRi(Zzk_a{ic;UT$B7uo>tIT zu>=ZCK;>ig*$`fTew8wB;o&d8@8I8;xE%}q4E-zN*4gKAg450QfNejtZfu%Aj7A40 ze3=E~a%EFRZ>@D&v0OX?_h`bM(bYI)Uwtx1N;?#7WCJSjEOISWul~*Ib-AeN=)c@@ zIT9^9S3Wk=HE>d`Uk2zH^7uX1UTl2qn`Bn$)k!!Fw&_=Ev$QscWM#FO*nZ5i>N4N= zEgSp6{8_n%xtW_aJlIai=rBk>GsvD0Yf4rrM@nxr1wT~FWmXA}zlABQ^BR?@pZ!`{ zQOk|J72uvrM8FXvtr^kKZ-}-H9WOU0r(v{0V1=RKv_g>F&}=UE8UEd$9u3Ufrfk0x z1U(Ls^}au!>LTm%0pj^$(gmYja*F*TqAE-3ao&FRBO+*s_-v(G#i8$Xk#@rIUbhL% zse!oq{OH8NP>Sj{ndbWPORar+Z8{^m;H0!9L2yJULbAe1csf6tb`UUlIlFx;e z>tsWR#>-byL$na=)N-b%2+R3hABp=*-RJV5^tuGf9Sjro^*GEzQkVxx9y1-k>j_%6 zyxFg*pHG+)eI4B#Q%g|tlVyIgn9v7G%>?f;N|_RMKwoPJkM98ILDQHp-=hQzx0N5W zjs62-?kKQ5;x#YGO7U;5`}Ba9EEWDw^5t04LOzH^q*J!KwhFl3!U=pa#T@H`z$x|= zpnEsw5Tb?dSjquaj@!G9#XRyC*fMZmCh?+anMX+z>&y9H7O>a2jPmtqu7>-+yUqkm z4f(|aS~v&R3y&BwVi7}R3QArKBes2Nq4v!y40;ApOXY;iq?!!xwJ)<=cD4T$QjWWb zcAYYlob#tRl%<&Kr|;8$0(xW`VOb|ir>HJXN&04nB6!69spGR$CDepX22fHK|d8Wvv4O<_Sn_!lLL1I=}}B29U^vTB2}gx0`9 zGjBWA&t40X@&oQe!xou5K@fxhc&y2PM81Dn7(vj8$iJOOs{vE9Lc~&`jm#|(`xdQ47E(E z3OClaFm{uFB905>C&E{kA*Sp5U42cNtbKvL^obH9`{z9gpUA53(jc{f@g_fO-JJ{H zM;IPzd#{$i=`54y^knL*$DAQ}!xlTL{clm315zyoYo%jEqX(`Of9s%t@l=qzAsY-cilnjgTM zOaGeW{g(Cj{kpB9_wl7K%1NB@6ZZaFKU;SzWp3*pg7d|@PzKXai=pZW(<Towel4V&q^LjN5Y&{kzx@kA)3<0l8c1yVT9Qh>9Ta8?bJw>w7PPS_s51S4L1vE$UDU(}RVCO1+U!yT z#x*IKH86OerlHJcQLuIywlPTy`b<7i`T7bJ_JHHXk;Bc9wgzH?*Ii+Z4`&JzH{j3y zTW0A3Y=!+8{g#)wg``Jza~+ME{g;qdu@B;Zg2h3nvp3$~AH4tpu6K#sd@k#USl6n0 z%-P~y@DEuY5FG_5BABt}PNFiBo%7`+(D$(z$}^NW^X4cXDf}DvWD8UT1>zX@*N?Y{ zJqmRGN19E@JoaZS9#BLPt=GS`2<3hh@6Se2MFRzyn%=k$c+N6WC1i!NBWVE90Ed70 zzXIXUHIt$^mXWtwP#Wgg<=@3Q)6yv9j5jHJ5C7?j~ClNS`l)Qjt)FO8ri* zlSN=#pL&-8()NAFQj~4M*29Q`&*WvF=64U1%yvq<79O5g@qe{y#K|OVylyf!4Gg+1 zCvxt4`zIf5F(rY8gCgsH3?O8HA!mgh5~Ro_~iPswm z)DB){+}pqgDg@l>?duKM%gWgO`5!pas40`D>w|CUEF9n})>;eMEfZ*{As-KOhP*O- zg@T~go-!#n3l}5byFJ8mlv2Z$h*TO=S#aW~?+>mj6pE;)af#~8ZFINg;v2K(M=Yd} zR%2%VHVUPrVI%XV=If)ru>mv@>sgUfx;PUfj5AqH4nw8~JlYo$Wzm|v#b=$5y-qpa@vpNxE6UUG6m_8bXHDZuHv<;tk`^Etn1Oe&%6 zdojq+ZL;GyW_S&yFf)DyKMy3_x6k+=a+t`ipk;hEM3%i?5D0|)$;URB(RVEq?6CEA z?nT{j1yxPLCQ{t;y0Kq<{rDA~ilhpnR#U-yq}#_G#CM#V+UQW$;@+q_2i+g8Dh*Wy zBl&kzxqkBC1gt!@%xfONfv1NjhpH>kSmU9eK;c5X3*#ftg=`A~*JrnOT#lnp30IQh zL{}n`4tO4Pt%zHGiQgf0+`n?yLavnjiZg+3+AyFe^fxyie|^~~0B7<1-)Tu$HJE`W zO>Nx$nAK|tg@>5e17F{kds+StKHhVZhB7{-$|CvRwVHj^h#x*`QXw^=Qtw{^w|q+1 z30<>PH#~KrF8E|TiL%v9EuxU}c4ZG~HxUMIQq#&td=!BCVtJJqG$uh4 zqrDZGs4m&r>XoWIJjE53QEDdLo!olzOOj?cZyxJD2C_`?bVz6}kzr@5Aa&*bcrj%Z zIb$hEZRZmw{BxRJ1*LUr4*GueBaQ)=A;L3hw`1c&qM#_P67kft<286jesu7_|^KZg`DS$|?hCz(V+>~oS8^_1T3 zDWQ}*1!vA)iZH1uxo6ULHE7L#IX`ku_~kc8a!}P9h{xm>31;HLL56gbi;2j5;}6f} zyuxR#n)y+jNsT>RM&}yWiW(3{1}k^0+ilX@&_;xjO{(&+)Olj?tqUh<6Ey0+P zb$r+HgAt96KGI9!kRBC+Q%RZBv@x_k#K@)-2IXFbD)kM;xd)22PgwRNa@II)h^7m?D=M>Mp5$QP>P>Pa(jVuc7|siAD33vMK7 ztcApiuqGFA!fL0`EODeZ&S%tPKf=9u34M_4JQu}gn$inG2-MnA`BP?lK^ZL8xG#G7 zk{<}kjuH?pDPSxA#Lc;{4{*VQpKp1+$jFB;7W?K zL2#kN*hAs9%^Tc^H$jo0A|l05Fn2KKGtFDGOr(BV#W+(yJzvTtlkw5+!K#;crjn3m zQk2VxCf98;BLHVGpS&iQp!#B{O0+Q&SdxFyt)igp7VJBgI+ExI;B;vAJ4i0>`U*At zTAx;M&!Jy&mdo6u=ZjrRl9R*LpVY=sDDj)>1gpM0tnVHUJAJ|~+ln~*=-&>cIbnh3 z1aaCqS2DoV$GRoxuCQwaa{aWJiyU6HKJqIzSVYHE#CO!%x{bUZ>R;fH7YI2fR#|oC zC~wWA{;TaqGQ>dleA{^R1Y@c&^YQKyc?LZMr8Bj5?DnDBRfeZU;-Y^bO-lDdE15Fu zrLNv&{xt8}w)^YG*2MN$6N%cZPpT>rQERMKJslZct!~`M@})i&E;X(GODGAQA-R0M z>bpKQ&XLq}M{0L7@^oGj2jbFv_-D+Me@1IxB?uykgq$DnUfR#jHm>*LQn2T_`gydh zwGVDxAaCes;yX_SsP@)dxZ_?VbkQ)#s0S2rrqKD$sN5DG@FSEC*~vR7!uG7lhkWS7 z@=5P@#tlGA;|?YJ!5+&vlwxKpya#s(RL=^kDwx$wAW<_dN}nZ|3|^9j8f{o&HpRAm ziJJXi^)~b*xRe}}#6JyD++hpI*@@deJt^bM4kIfy&{C?2@g}ReH6tY5G0-=x;XXsX zpmo3Qmmv6w4s%X`U1IFGCt=FvhCMKoNrfW==5V=vzevqgNUh3y@CdEi-W*P8O2Xre zDOA3N-SY?yMTl>;$->hj6d}Z|n1Crs+{b4}0p+;s4@=pMq9OpgkT3adoWIZ?%!%=7y)qt*QEnyp0bXgoqt4?`mImMB64G|C82f3r9*C` zTF6(!U{ex)^R2gwiyQL3W^R1oCWz))Xcx6IF(%A~RCMZ`N4_1fv`3+_+u^D>&EdFu1BQXTkQ`|vCp1W z^ghsTuy(VhmJpM5WA|G{#VFQov1#d_TAU}?Ysx47iakep>PyiZ3yx}9uUK$h z`*->-c5QakNK))NfGU7Se6nSAxYpH$+aODmvNKwr_rEM4OEGeSVg#RDWMl%1z}6Hi z1P8vsU=r;P<(`cGFB}>%f3)_D@=DrZAr5T9XZ{8H4ud;0nW~A3jxq>*9lf~Y(n30( zxMHwPY>%r_5-pzlQ=23jN0!3a1J(p5$@iP5*L*xxVg$ddC@5eui-BsC*{s$8%BL-LtaC}7k2r!{u-T6oBPoQ}-T zN5uZ4G1~T;9#xCz|HEKC%;uHGuotLOkRizT;_yXX+M+)t8K-H77l^s{n^g~>FQf{8 zV_<50?Ms+4e4&`(*Z-X^e`crB)M8peHKO}JZ0u6UUEuU* zOOv%K7-XPx}Tc~`+Mo3wG&}20XfM>U=`VXO7C4X5eKE5kSeZjexP0deMSyj~-9-UK8s8(D47gQfWaOJY@NOT=}4IWEDfZDM=2%`nSqD zl#(vO-5bHCu#91M#EAs?_FNl=jej zBvaR0m-~|CsFWpLc(pu{Y@*@?3Rvc!t2@+0MzK%jW8h@it;yI&LaeffI26ZP&{YURr*c{OJ5lC)@laEL?_63yy;laum~^z@m* z>>%yQITVXJhS zS&0*p%Ja&FM$LQr+Ttzx(JAduD+x*LVLdeT7Vut4W=+07cA8KdX|O47D*|KlnMz#X zjpkyF`a-e37hs=4%J3rwcT|+|X+SC<-*3&HEWnU~>a!$?Bi{iCz=^oeS zflLg3ENH>Xe7JHoDA|xDn1r|N&>T`Q^G=h;`At^rJd-%OQqZMd;TelK++N(?&i%V)U_dPHCt=}yRqPaPnuEj@ zjR%D`5B8p zwYbezre;_zM}@Y(N5@cLgX=BAjH)L5+J9zEx-1z_Bs0Z~^T!tAy*B>1Rar<8u0>R? z9`L%6nb7lu>i^y;#we0R^E%~hjA*3kji#=+g7<@Or6mh4UGIZcUl4s*f(E_LC0Q@gOTDUI2}C7^y{`&etX|KbM|6qplHK*!vzlIM^Z;IDl_oSKMK+hN03}9h0sEh zF%rJAr^xNF@1)sQMG!_xO01JNT7_L!@~E?$hUsi`Hxh9ZZ`}+H)z#HGpt9_8Uus|4 zT`oyuA^ArsLMN7-Uczu-Qg8pXi9CrG4wcK|(s(piq&R78u*35qW{4py9#m_`Y5QV3 zpAGROr1@K+Ns7WAnST^}`HC8yYw7ofrhr2{yTK6${4o17?WW@IdPb~8fCCm^L`ccN z7Or~aX`xWjxb0)-rUlR-aSaU(4eW2@61YHPVwg;zdvm=o%FM{rUq8N2GAyO;3*S+j z(j(jGV=jf%ga(*sg>_)&aV4kH#%5+jL@#Rm#z`9}c=9(|2;)4qIELz=D_ zWB^XeR`XI8=ZK1o)D_;r&v;`?wY2CRKDMCvk+p58h)Q6dplJ%np=N z{iH=PA@elZp#&xymkKv8C5>-YW`;D{0$o}xN$h-8sR75%oF(#rJ`2aEW&Cn&6_pua zL|T~aj+vmRmm;t+uGMzQm_cELAI{uK+~$_AgMuxyt;|Rv2s5+u)kJg^xnm`H$~Pnt zAv}Ap({4gTKvLY)D0N=}1YU=6{s;I6j2 zqL^6t@sTRmbLFCLOpdX5*=l_inmAwX2_AB>I7NuHzIp>g#M^9(Lxq8BXC*6JKSk5B zTbWed&|HTJ(P)cacF{^S+*?;Z7~jWYQ-{z6-AUW>Cm1$vBfgwQo(OgI8d|8T-yUb|=^fE_mIiwUm-i zSB##ZlHVn^y2cQd{K6=)S_NK0d@pk12$hw^oA`#KQ6A5jr#Q%NPG<8h*IJIEFMZ28t9A8a(`e&U_sim zakyDCdG`Ln&eQD1+#oc!i``G4nnDtP)(Y-q(QmJVAb9DUAX#-ThE|>J3pYoB6kk>!aq!3fb5{955XoTyYsJl7XPA$brA?kOAs8FWu zwqTAC$P>u*sMfq}vuL)_DKEq6*!fm5927H4RO@nyQh9gd zv+__%f%6;A2Crb-ub7WNcJ73KWZW6nC;l3JTgYnay55~h{U<+5`FA0!1m4vEO{l_I ziaC~c0++?r7Hf$-$lJB0Z1WlH>rWAoAm0=wqBfZ45!iCpW=F9K;;KGKYEQj0=4X|n;xAM?uEff~~>6C%DC zO`=Jt0O0gXpYzVYW@Z0YTi~|R>e&nNqt6f7%X@NoVSceE$;M1jg;M6++h`R4y~0lS zzwb-VZ%Z?Q_bpMRf%rJ~w$3F7dNxs0&&|W0!43EK_aYw;A23`WJBiLeU(SEdp&J;t zdpu?Iy&kCI8-F|lls9vZ=a3^6)mo><*h?&<@OEP$tkyB~Tm*RKmw$f&=4`aBM_M)n z?4?d59Cl6P<`^KtCJ$ztH0BCb8A{@Z*3|v8RCvP&a4BA1UU(eWTJ07YJm%7w^-;-$ z7168HihOr=%;Yih2lFy%iOJQ$tz~38c*rEM^+2EDTD3`6nxv95dhR%enwd=%w-g`G z9+Z&yTfQ@Ms??@qWNVw=q{O1|5fwc8(il4~Iy62&TI(q9k1WCSsZ@z<^e9C<1Z>8j z=(}o}5rU){JJMF8qf#IoFjp)k+Wd(3gOsy2)E@s?0LGbqu2A$0n*JApAn3E#-6W3O zs{^4^ng9J4YbpmD{E)uxQpbpVB+1-H#Y-n5SpG6Q6UWO55z}_4C5g7cmz#o*BN^f5 zpsn7%mp^?y7n^<+o}Nkf!ZDM;}Baqs2fqQaQu0Uw#Ojbi-^ z{YBV6;pd|gKx`yw`ycWxD&jyRr;lz+b!zg$;(0y3bX1PsLhX!geJ+k(dKXMxH$MPB zuXP1>y4X(&7sMV2zZN-&gA=*~Yk<6To3`tQ?ImlgEHGd2aTANuqd2Kmj(kje4kMC% zxS*jPLKGPk?e|9Gd4RH9e}BLI=RRc3yHO%%6QKo;+8`6r6KN8fJ;ESy6Sfj!Rx`l} zYXJd)E0P=;iZtLx(j3!%|o*4^VYQN1;Dj9>$%cDTM&-WOlw%>INYLXqpp~qEJ>qq0qHYGxW%Y10DFm4 z=J1trk(UX*453ZtdVN^+19bVb=w9;+fmCw=j{WE#HO6SB?YXrAywdQ8Pl5^7ZTdz! zI(V=!+=`x5!+TSeXjV!2=GBYb4-U6+XI~Er0W`+>zTJ1g%wb5GQxm;{{>vG-_=bgr z^}YP;Q=qF(G?a@pll>*F6$4v8NUtkC$>Bkz- zd@%+TUtu|=3st~@qD_f;x#&ZKfdY3q-No}5$;eD)^X;_&z|-B4Z*$H79sUi#G@=DQ z(*|AB0`0z&j@~=w*XPBCK%9or0`Fz_86mHwFV;_54?sVz`!Al?#~j(4noN|3$IGb5 z`4)+MHWs zw?2#m#1H>9qO9|K1A(@SDl~I0&%;g>nJ~NHZA^~y=wZlM0nqNW&W~mvoBv-H;8R|` z{wwIEBj~4BA=xs}1Z4rUB>09}hLO-_-`)T>SbBwd)aeoFFed!9j=r~lK<5wsAX!e8 z5?qWTju4HHfFiz;orThIq#~w&R@xnj8W~cHym5of{K$2GS?M|T+-bx2ZMT!X43B;8I-+Pq zyDS7+WB1zwVJ1Re8=iP};=g!xIqHe|Ju0jH8!KZWAKwP?dV@ti#y%d&yf-p>Z_EDE z#)&-7C0^!DV^)6J&~|}AEB-F>(jxNn{KTH6=XPFcM&#vh(EDHDEV$SG`#eF=hQ-og^F^RG%0TQ}zhcoB>AZ&SYxzrIkRxdw2I54qr%VFz zzGvkVD$SJ_+QKA5BlD(TF>2xUV&O3 zwt__LAU#o};c)sXk9zVcql$V$`o+9V)`PPPv(ASde*-!mvnrZ)jVWtcR=lO4;HMX8 z=yrJVBE(*vGoy=8-b-e6S3wdmPw)SY7$z4inl|;1DY{1l1c!Z`w-e9j6ynDoY8Yt>$clPX& z*U^!oNtrC?NU$ssh6?EUIR1EV`41@PpvLf13GO3d(bF?SJ;2+z^PmRnC#bV`IazM+ z7qBbRrnlMtPYIrAmJJOJMRXM@B>*6Be->1Z%-?_aP{m+@+}=aFC(_|--O-U}HK{WB zc0H@dJ`ra02ssDT9E=Jhu(+bmftuh?ydl)>KtOOPIh8CAf$4WS?7@&E=!g(5uA;(# z`yV#cdHD+86?=CXL;~B~yc( zYo1oI=DgJc!t}FGBp@I`1Mg;2+=ANT%ZGlnhJ$(6*8?#b5|kG6`Y6^@eFY~ zE*Z}6rLw`uIAN|gT>1m<0F1hwO|$J&bQal;aH!=;ovz3Ue_;wv)U?$CIi*{FI~7f< zR$L=;Mf1+RmDQ@)t6U%UZ2jgrT5$W3;jBodnvl>FYJCOI%EXv>Kb_5mbVB}&z#4~} z4TAqoG)s3mySZtUn)q2+-Y$O5{K)-zVpj#>W{-}PEsw!MqY4p4 zQEOR*muUuXkvc%4YpkLX7N9B>QHI^4`0BFIvbjpu%fpHdVHmwF27O!{*{YJV@FJXc z)znXvvCl>oPX|kV{`jeLEKSwfU6va%O3$mB06i~&BnT6SL&2;GAq0n7Z_rDTrwBpo z<>`@*I5H5@3w-|)OiOj@?*Hkyc9+XdI^3aN;Y$cQ3N=#$=-xkFo{T3k2@&0W0J(j=&wLE^S?BUK;=-4CHPM`ZET=(QjAM zml`vk1W)n#G22C)axt>&#Agjmu}v69cVaejcqZ#;VEQ*kb$U)>v|S7jylmtIdgD}O zAb&BvC8bg9)f^^j@+_*ROV8=Lo&UxK0^Vj#q$aUNhM6y&vB7(QSC7-t7gxTX>hjZk z5p{Twaw=3XepXCeI%6&WB{u(GEROkflt-uyvPJiBJ!C`Keb2aS+qlRs^h_j!YeKWt;o~F=b$GA@D5O)T|%9wL;QoL$a7Tr-}CD~ zfNqRVSeXA!&em|)56Bv9@)NJ#8xrhy;4z7uz24w|zzCG)g?-TsUIZx-B37$f7ASg@Gb2!}avtjFae9;i?fu=c}2fPs3rJZ!HXh11P zuJ}}KDP9XWQ~47+;O&X<6t8gd55YMy2g()8z4vWL^dJ@;UnGKd39ARVpi4Nwjzr6f z=Z&)36n*SXH%TW$d<%9(^ZyLymiT=6Nl4YU(PRMfR%8_`GSXT!V(p_Jt|%`!EoiR0 zQ~a2?U!BZ*8{!o@9pyLt9n2`6V$fo>79H-^z_E$%TGtyh$ZkD28G<$BYtvOQnwi-) z^NKj@b45WQKPfaJ%y;9T&#f88fdm4?*qJL*!YN~JvAfXe~6CX-7hEpv+Uy`o5iyGqpInySo$ zZnT4Y=^!XkanMi++Oj#SDQ|xrtD?y_gaz`Nk!`cKV1-cn1=0vVRn$g?9p=m0+jyml z%Eggc^VFv0(6=i(ya4fVH>*Nx#vc`el7$I+J71J>3?#E|=}g|#Q2awJy*xc}el1qY z1n8pCqvLoLGx}7!E^4HW%?1&0Kui*3Qv2-Fwo{OjEhbD|a>6X(gT{eoe(&qS=LO`l zk|k2g{rdWqHC6;{Fy*A(JO&6}?O4JJERj7=pB4%OQJbgyEH8)B z{bz|DO*^7o?aIJ^*OxydqBsRHX&oA1bB z)HnJNw#|(EddmCGNi%DtNckBwZRoWD!>3%)3r~3!Lw(C?Utb6k7A5N!j-$qRw#QPC zrUIqelD1vsq)#->PFKveP30w$C(%kaDe}4yo5A}1ePWS-(IRIk@{Rgy?DON7nyJV5 zkAY^k$y8a^=kN}w6Dp#p{GXrSsq`~k?br#f1JDgAy$=B-nw>WZiFdqjwyrDtY!w3r z(VZxYFS)d3O8oJ^lv{}4r8wm?eh_9r41T!omOLAZK^yM)B&Vq|M0(L8ukt8s6Sj2m zQPi#tKdgkSI$@Gc4nLW@o7B7 z`2(nJO_-ChzR>0`12kG%_lg9T@>l0J;;6-k_xE3mz%t^tq{(+0o#I;gRw@z^*u2%N zHjRubUr@d&taI22ahN31(UfH~BgZR?#pl&Uh5<^HRQYv`Saukk<0uH4Rnps-vA(L8t&A!O z$KL$K`Fu%d5Ic?|3FpO-^#5AW~tM`iyh4PF`O$<7^{I-ItOr9A;YJ@2K>u zPK%OGkWfn{AEjn*miUGo9JXg;7%zNRvwxNSU2Ib(qIPN2?rV7)qTU|~4>>1UKbiuw zaEKDp{kTN?tVlcGNb+bJ;o^3kOXb)^OsHCItrW=%&mB$Wn=j6Um*-I*J2Q)$|osn9fMmMuADr|d)?g~;z) z_O_5o5__+kbbus{REPKy9Su=JJzeEgF!Z?dfM8ev8v3 zsc)eZUlP1bbqkJ#$-9x}kA;RM!;Xa^lkm}zIMP^w+t%FW#dbYf9_UGrVm5DCbp6g| zZ`BcfEUAvAt0n1ARfVR+u#1N=fsen$@sRZu3V8+O$Tb|Nw7K;?^zfYLcU1&pn5=wj z<=)AJnWMcVHowmjOXc4M>Md?sP%*ozs>+>oTX1xh-2cs*2vZW+6}h_ll8oGnZ!4zEI7{R_h$1z9!;u#&9As!f z&8k85Uw}bJ9E23*H2;l`2qGvGVe#)w7T2ycw!Y}2i9scH!2V{nal`qdvLyRk~+P}}P_)%;Yng_Ow$`*#0Cg@`Y@<_E*eAE8q)7bEAHy{MosC#}rJT}WG42d8Wk4&ZV~)o!$RRS2C)$=6Li6THaE9VW z&?rtTF-%#$-cC{XdRdz8?&!{3pst0ct+eq%US2QYJi=$xA~dC1N0YN!yR>Rd%RD<4 z+BJ&)D{B=ZgTWW3cQT$Y%$>E~&T6TSoMu_l`+xqJa!hRoy<#(bXzWHSvcTyk&6wk0 zOY0R=;-=a3cftN6aqT%i8KWgsfiXii7_B#Vi3AS!5BepLBIwJGnxP$~Ag>w~R`YY< z$PIzE{NJ;hPH3=d_53Afne^$+*G4<0qCVOf(^1wu{FvNMkxUfHVKCqqy|bY9eLv0B z1V_Yg$Ly`Fj()bI@=es4^Gm`vi7T(hFX)xvpZHPz#O*(rBlb-u$&lIUF#5EcT{z*} z(y%vPnaQ*tN2-C=*!T3LCwoLSiRE|&N`?&{BW5)e>F(l90D%`@O!}GvR}-x(rKqI7 zZb?fvhY~ENOkX~tAyV!o>q~K5*wOUy;kuBjAAjpyp#awj+lL?GOhh@@@P(${r~J1U zo{Lvm;0ETW^Egr@(?^A)rd*en|78Jj7A#?`jmXDDWZv}{+g6k=H3GD!a1 zuE#z@gKBrgq+OR1Xw1Fb^0>0UQjPu|JAG7FORP1jDWVVxShb)bpPO<9izx1oJrFWv z_Q4;B7$q5oCp4@25b!)B89xpJtB;R%d8~UYAZU_ZosHQW4dp@gzlL)Pufunx|0+pu z*e9^h2fVt~?zxTd9*;(6-LcYRM1UFKE?F;>Kn3xi2JOoV6uCh(Rg=MHwNP_CI+Tb# z{*No2)VQD@pKSLc875Of>kqe#x8Gcn9=2h};zI6SF=_LK(Ma;F*tirlrr}J$Vv6td z5=%8l5BrjuZ{eo>@b{Cevg~cS%`wYve-@##o1kUpfOxm}e(U3pWrktoH^3j5?l_?d zU!&9T{-03tbn~Hi*~rh)#3cCBY#JM9nOhpX?g}8q$eQ`fnC3>4VybIwe1I|V=fAjU z>uqD}=`u>hALwoV&KL4q`1X0{9e6~(4zE+ih3c_n=x)S+1bMt(wUwTKdwYrjJh9z2B3bI$1&jPpiD%dTXq81X)?q! zi6ob`k@m{w1H{NTeSLjb5froTXz8MolPo<}_B3FgStR~e5;QIRa&~_HpYsfmb6Bl5 zTSlRh42H3?E!>(`6ZceUBI>O8w-y8bo851p&vnB8WO@|_>O&00TI~uLg|L{(JEFeX z#sYihk@7%%KFQ2#1wE!9Ei{4HqA-jK8dK6xZmPt$XPTf`Kw%#|En@XweknHajXf(_q5r!VtnzOiSbcAmE->B1=ttNJ* z4D(2IE9HL4Qx~>0v|Dh@lj=?W+Gjg9(6N5mk$}7M)@RYL(+-Z?cW7Z|I{PpAv0tti z^1j^ucshT;Wij~Sx;I*X&)uM2kBuanBg~sX>l2_A4zhRZg!YcO{^QnJQ{Q!RyP)#1 z)Y02!{Q)6y5KN)CT_tuHL)Z~i$Q3zf%am%#0$Omr^yW@^|F`x2PlhZI{pa|?Oi!cJ z20u*_Y{_7@>GhcOTjB$I2#fnr(Tq-=UR%J+J)nWv<>xmYjU)I0$*q)l<)L?|!b~r& zFc+^l2eH;_i)9C+{VPt3PH9!5dV6${;U29O+fUSGf4oS(?Dm)OJ4LD-Y|4L&$g{KP zlRADDX=9_AM(D;rYKq<~kqJWu*lueP7$W(H+uJjhd6m@c(_pI^zE#Aug&#b}JNuiT z=IFz_H_ErHGHGLcP<89|`af9<-w>FI<{@M?b8CcSikLCxiv$U~902KEOqus6f%Wa( z-CR+)D!kMVX)4o}{@oYhbhahdj1JX8+mTqDU~?eBcm^Us$8}I8(yKz9h{j=&;_C$T zv?ie{2o4F*m-8D<8MF@v{2(hB&i5`|^%oO#gpp1l6hDzs6A}`#p~=2i`M6a%Vr->b zUP2{}B3dEZOP8RIObCk*7-&aMijF(RJ66pi*J6iE zvqGYVaOc)b9_4bhh@)QqVz&My3~_^B9DUP5E=df-fm=#;q_r!WUbPG@pob<`;;UzH zJeOvE&q-Hriu+{#ens}d)>v(jlAwugmS!fV?kZ;r6nPxhLy~kR4l)8nYz;HfT z*!KX>diakwP?|u2>*_f>J>J8m? zAQKSVKeT<^8~>+yO8j_C)ScJ;jqa@0G)C%&+%V(^0ks9J%{Qn+bH5(Rh#=;|vw)WF zdoBW;#}Y_*wqBc%SbhXMm@U^E2K!~D-q0Gq4UuiSE(88QpY47K?3#tbP#Mk~Lkv45 zgfd3UO5Clru7mNSu#3KPJqIWoc!n5K5E&T*wx{-(G$E`3Z1{eD_>6j0Fd>9OsI5jt z=;ud{H2Km6M_|c)^Lztfj{r_92wrB!Vm;VOEQj-}F)}!YsJO%n{Lh!Y8AiScW&+P} zaqre5F9f`lCy~XZ0k>*rE=T^iP~79d;wx63KMzzUo)g374Z>2@I0_e|YSqXj2k1>^d5{__Het}6!QL|*j!U}E0u zf1VEtnfRNK{eUn48H80!2P+*x{Aazg9=NsD$^k|Pw8B>i-B->Z_s#?7K(e7Cu5bwq zsfeXEfP_3z@Om785;VPkO!YnS%;LY^hi!rpeubGO6M$~$_d?u@e-_DZj(E1Y?bLR0M}ty(fu-^O9t@bF-Megg8T+3I~@AscVj*PPQ8 zgUJ(^%N_mGckaQlG;*KfI�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 y Date: Wed, 19 Aug 2026 12:48:28 +0300 Subject: [PATCH 30/66] generated screenshots --- webview-ui/playwright-ct.config.ts | 5 +++ .../playwright/ExtensionStateContext.tsx | 42 ++++++++++++++++++ .../AutoApproveSettings.visual.fixture.tsx | 31 +++++++------ .../__tests__/AutoApproveSettings.visual.tsx | 13 +++--- .../__screenshots__/screenshot-1-.png | Bin 0 -> 93655 bytes .../__screenshots__/screenshot-2-.png | Bin 0 -> 49081 bytes .../__screenshots__/screenshot-3-.png | Bin 0 -> 40472 bytes 7 files changed, 71 insertions(+), 20 deletions(-) create mode 100644 webview-ui/playwright/ExtensionStateContext.tsx create mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-1-.png create mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-2-.png create mode 100644 webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-3-.png diff --git a/webview-ui/playwright-ct.config.ts b/webview-ui/playwright-ct.config.ts index 3eb0abac7b..2263f08588 100644 --- a/webview-ui/playwright-ct.config.ts +++ b/webview-ui/playwright-ct.config.ts @@ -58,6 +58,11 @@ export default defineConfig({ ], resolve: { alias: { + "@/context/ExtensionStateContext": path.resolve(dirname, "./playwright/ExtensionStateContext.tsx"), + "@src/context/ExtensionStateContext": path.resolve( + dirname, + "./playwright/ExtensionStateContext.tsx", + ), "@src/i18n/TranslationContext": path.resolve(dirname, "./playwright/TranslationContext.ts"), "@": path.resolve(dirname, "./src"), "@src": path.resolve(dirname, "./src"), diff --git a/webview-ui/playwright/ExtensionStateContext.tsx b/webview-ui/playwright/ExtensionStateContext.tsx new file mode 100644 index 0000000000..57adb65b2a --- /dev/null +++ b/webview-ui/playwright/ExtensionStateContext.tsx @@ -0,0 +1,42 @@ +/* v8 ignore file -- Playwright CT-only replacement for the extension-host state provider. */ +import React, { createContext, useContext, useMemo, useState } from "react" + +type VisualExtensionState = { + autoApprovalEnabled?: boolean + alwaysAllowReadOnly?: boolean + alwaysAllowWrite?: boolean + alwaysAllowExecute?: boolean + alwaysAllowMcp?: boolean + alwaysAllowModeSwitch?: boolean + alwaysAllowSubtasks?: boolean + alwaysAllowFollowupQuestions?: boolean + setAutoApprovalEnabled: (value: boolean) => void +} + +type ExtensionStateContextProviderProps = { + children: React.ReactNode + initialState?: Omit +} + +export const ExtensionStateContext = createContext(undefined) + +export const ExtensionStateContextProvider = ({ children, initialState = {} }: ExtensionStateContextProviderProps) => { + const [autoApprovalEnabled, setAutoApprovalEnabled] = useState(initialState.autoApprovalEnabled) + + const value = useMemo( + () => ({ ...initialState, autoApprovalEnabled, setAutoApprovalEnabled }), + [autoApprovalEnabled, initialState], + ) + + return {children} +} + +export const useExtensionState = () => { + const context = useContext(ExtensionStateContext) + + if (!context) { + throw new Error("useExtensionState must be used within an ExtensionStateContextProvider") + } + + return context +} diff --git a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.fixture.tsx b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.fixture.tsx index 1bb100d797..c77a1d9f18 100644 --- a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.fixture.tsx +++ b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.fixture.tsx @@ -4,6 +4,7 @@ import { createInstance } from "i18next" import { TranslationContext } from "@/i18n/TranslationContext" import { ExtensionStateContextProvider } from "@/context/ExtensionStateContext" +import { TooltipProvider } from "@/components/ui/tooltip" import { AutoApproveSettings } from "../AutoApproveSettings" const i18n = createInstance() @@ -39,19 +40,23 @@ const AutoApproveSettingsFixture = ({ autoApprovalEnabled: false, alwaysAllowFollowupQuestions: alwaysAllowFollowupQuestions ?? false, }}> -

+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 a=azN~`a3HU2jQh@_eM}L*l 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%0AFemu@ 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 AO8@`> diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (3).png b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (3).png deleted file mode 100644 index 1e827b6a04726c2b77ef331932ea702986f8e05a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 152280 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°o1&O@t=Uy=0)IH9eQ*#XC|wN<$!)NA>z$*}hKA)g42CM*_O%pxe9 z(Yaf17@D_Pzo3(j#9)2;#c*ZU`Dba!Mdnp@D|x!Fo?Y~qpCsQ$88pMq%4;pfPEF&x zxGbqY9L2p#`d*(lViJtJ|h~?&7z?3H2Wq(T*=nA#h`Axy<`ssI! z&@YWSbLXUr#ChL3`Oox?VLR>~Ya17HW6zJ13s{HDOT^jG+ilzR@vI-GM{vp2nHy|8E_0e4N&q+C-0IQ#-!hGdv zp|@uZI-O1={#$rvF928-{NrYemd<^udYLZws_{RBUV&wMf>~}DG`Rah&47|+&$}bE za2KU&TNRtgc|HK&*V6h`;o)Aqqa1Hhr4pUwqsAC+Bbxbpd|@a1LVqGU;%9%(zJeH8 zsID5q@+)->B<`6%Ou`b6tiErGS@m667neVrHKJ@Zah*upnC73N`+~u-R;5} z?zh;$o9n5HdW@BrDs+)0om#0xaRT(G{rt?gEpl# z=4nn@1K|;AVOmYW2@ya*Qp2mrG9N-Ws(NRS-RqD4M<)*JgaSnHP}4i@@PV<5(M*O{ z^qLkk;(=2MG_F6Jc{Q{sD*RA{&9KNmSQ&q4$fqUsW4A^G>{4D1D;L$hakU5&^C_4{ zM0(ZX;fLjXq4M`0`Dxi=c=DvcRoI%x8CmdsD+P(LT0AaLzWTWvQfKU zzh)#-OO|!`#7!L=k%TO>5w@tZH8UAi3c6QsWb5yuTiV6gEW?<|jkUy#)h2z*GbwFw zx3!ffKgUNH^I}|t_l5gcNX1Ddl9JJr>8;|{=6&i>`I!$(fT2o9mvTA$lC6#46y)Z# zoeMd*maogi$eiH*F>vbq7pygsNDQ3t^AH5pc8usAPldgKKwG3>s^Y_c>Ei(fHv{Ij zG7Zt`(t+g5KRkQe3f7J=j_WVxvM=?dyqA=sq#!2%-<~T4!?OaU=SuT#4OW)o;=NyA z-y0j?T=Z{3NBsVMWoC<3=+1hP-qeJIw-avSi1I7kw61vxtP=clv2n4)h`f%mh0(22j>Z@yNC@3j44Dv8P z)8E|4Eb}O#!&|(bxH=VKdTAejzcreWy}jCT$baS@bYDP=0SvtXmGh|n=E!8=X?@1T z8pnQWcnjy7jbjn=N+e&^eb8qRFy<8wTb|=CjArS0HXsrMw8*|i02GUiR8%DANV~){ zLhak{-$7(yJS-qQa~uG8Grc-eRiYo~s#JaJfYp`lC-3Dht%4z~k4XO0 z>JfWoz9g?OWepfEV=rlA4b4_N0b%T~d}Ua+nvCKWINUi|3u0|U^tLgb&Yo8UcRrQa za#MjTkk84ciAC2LhEg?Sgglw;9UKaCb8W!JaOP-wuOjBX>%@TCpjpMBP%RQpkz@@v z^nD=hjF@7P?;A1$13GJ|cb<27UVpnlK>ffWCI5sRdpm3?b^RJEd)J^tHGWv9$u2~u!%7A}O zt1%!kdIto0l__^0FT=D-aGk&@Ex;rZ80%n5$l@=lr+DI3X?i@?rEov(H=W|1c|0Vo zLuUwPpBps0fz~<+W`w4~Cr{6_?6;g(2(CH>i(n?H2g4l61`hi8=t60;cZa`?_;VLnC%(2z;QQTt^zVb~#B_yK8-S~Lv+%EJqBh}Z zC(sWuNxHOr`GzV2htQ%Y|30#wENPUjPD3w`esc$IjH(ZGk6@bU3BcO?pdX-FfYCHO z`fJuxbr*d4bYDxl_ilUvMB>5)7HKz2a4N*f9>Xb^HS%b%-aCQKubafk`JlG5P$q5ZS(5)z*Zp7mubbA3F zZd(6D=FW_Bzy-8u59AA73cHoSzJ;mcPzvsiJMS`2$X^?hu>bqG)eEM|B<#>C!~IVe zQ1k#6MHbSs^%2B6E^cmA@!dEDgzrLZ+=9+4v0vRhnK28#(7FQ+-8#-XmICgi$5yO) zgQ@xHw_B{fvrqjMn&Gxx)((%i`f%DS_%Ohb;PbUV9}RjMNtRgNt`~*4?j7KLlOrQA zR>X$H;kJOuJUl#H?KbxbOvsm7_;*CZ@}zRXc*%3 zfZ&|Ri|v!!A}^2=ctX@aF)}^!{rgS}XFNbM^MKSsqynIPZp;P1Vz9J?Ut$w1Nl%S=wW!?z zqFZEGCkT+l9!|@3RRf>-6!602o?m+Y^B3Xu17;h&;0vp;@W=H}Fr{#gng7|d16rjQ zxS7Zs1p*bJzO8({%+s&e`o?M-?|)*tfPs}6u~!<>ypJE@OW^JMya0RIDazBg3Rw!&%Ie5+@{ z_1c*3##lx?Ufmr{ImPe&+=#v{c!Q8B2r!zA;~-b*&gaj>i~eA&3{7e{=158Df#d^N z5M*r?@HN0Dj;RFU7-*nenPrgv2jU z0qz1U#4P9Q_HVKth7gqsh>;-!{TEo*-G#=&?5w4y=e3t!ps_pKh!6ZD-3vq`oIv{F zk7}6dI4gS?+o0cs{Y4hErGH?6f*pT0tnc8zuejezc^85`U}giX50A;}aC;f|KVjy0 zOnHxj{ktBqC|o*Dl^Qn!-mXitt>FIn4Cjjv8a!$Oya&BniC5%d5E#H^YSEGEgBF1xIX15SiJ7tr9e{7g*%#KmmXQZ@`-rUP+rX zi;M@sb$qx@={Qe#`Z#S2ED1Oj6tqxU!Ep5^$i*QY0&w0>OPPRt^F|S!KaWEPfbb6A zg-aZPmuy833#|`uop8(C)$)&Lnh?2+7xd4KDzA9W)cQtbRYK znOnf2ebJ9TQpWBJvZsoOhzQgR72BhL$bjSMHbe}RSbP}SJHcHnkY+*?;0-?V_J&rd z#fL}GUb=k!5pMYh-UL5wG;SiLCR?{F6g@uG5TNp~V5mJ_>x z!%88L z1U{CaSK~_T27_hrkhamIBi9E1O6Yw0OuB0brEJNSmzS@>pv3J~P-pGJE1Rf|^^!!h zf}+T*(!&mfFQ7zuDFQ2wqd<5W{jdXR7=9E;a^ZRY7#MgOO)oFG9|(r^LU*LWo_S`b zPbLWJF`Th43L8o_MnNV2drTN~yzqp{FI7cVLJbT6w1<_?QL->DX5Tg%-%bX3ZWd~ z$mhQ*{m=kOK|wJE+HJ73hDxk3zy=dBatLD>;v1w9plJfzf=b}L^`^_f8l<$i2nb&# zo-~oFkC&GmR8gAm(xu(;zwN@(4(}EPeQkzC}tFIZZy$aUvE!mX^ZC01NL#Em(5HPyBs_a4O4q z<`{{XoF%9}m%Sdtq6XWQtCQ19G;aTaV(rlv-9zH)pJ@qgNob&u5reWCO2g505hfPK zFZadr9hqglppzRi<0}^aNlV5o@`K;X)w-vQk=+*79iR zb2fdr0WY#*m73_j72hk>D_7VPl&S83eL0L!+-Zcotqyiz&}nQs*U7JQ>4o4WSu6=+(UfIRch7^twpj81TOsf{}P96rP$Yh;6 zr;spq7!Y>1wuNpy1VF{UY*tw`4bRBJK7m|cFGDWU94IeqARvU|>1Y$!)sP#p2J=Y^ z&mZK1kN!>vz?dLXUI*eCF!MoTdogaACbfb|?S<>aSP2yZI8TsQ@mW7T78bP1i@X~f zLj62(*&a(I1c;c{m>l96C~wt?`Tk4P%2=EN9q||m{p}8%hP??WF{i*)*vF>a+@M1DZ8=*|JY9ettQjm56rmcGp3Tp{qEjhBe(rkn97D|B>x$T=Ne%Ei zi`64NgAkncb)Yqa%c}`lhWXf!3tG@0J`u64VOfKb>bE;?AAk9JEgUNVVWai{dor9O zl)Jp|UBU%(UaXb}MU;#Vw)J(5>uXWa8OrxfK+Ken4+L_o!7c;3T>y~`gi?SBaux`l z0#N1!fbOBtSnh1_CXUGF;8vBK5Z6@`nwY678Yh8XPp9{}jC7+mo$OcP=MIe^W(SG@ z0}IP(5BNf?1@3*AIsPpb&w5?f=1?4=L}TF`Ys>nWq+;|pAWg*VxV8-y0kFU!4M`XY z`7A?Kn_>71a!EJI_}X|;*dfN2D%ZX}?O&VK%R>`CCa~xZbfg%qngLK*a|*$U1LR%TvPgD>Y0ST8rX3OLaLnGz6|x)c$~LPj}<+i`zA?yFkG zoP8(t7{5ZTT|Te3lsY!@BSXs`tH0(lv+#BT*YqTNsB3KcwTYMC z{y64t@nuX?fwiO3$m!_%n#<$AHOV8lCfw;41F5J`f)hYtT2wrfnHC^@<54dM&J8fE zIN#B#QBQjSt<*6MW;aOupqeSXn*ES;XI|%uCum*aL(p9Sdhh^}{`0GJS?HuD0fet< zk<$(wU*<00ETd7`!JQ7-IPPgtLB^N+?;v&y=G=`~@cOr29S0El?v-l1By@MM!ROlQ z>aki2UZhA4uh!jQGXwlTsz*5TbW{$MpCHiX5(dKT^#>?^dFS2q7yhl3pNwQZzs++i z@h*fDeX29yH^C6GU!rQTT^2(?zXYz?mp13F9Q^#)7aWziToB|CVSZ~7!>7zl`D^P{ ze!kD6zmIpr=&HVb`zr49Z+vTBTX`p^W}<#*#q{$9QqtY5TU<(xuE5s$gbvY<}ip|mt$)5W9r z>c`}uS(z^xoyEcd9^%hT^NjZt90^%vy*|6A8}WOC6F@JHi&uoZo>Z#c z?au*oKTNA^yNe8Y$e)eZ-WH}0d*y=lG0%_M&)??QfBQ|tIp9IVay}H_ zA0S*RdWl9&56Yl( zv_8wQfGcdii1+_>_1;E6vk|}56NBD^hiAJFo8io#Z1+amog)fo#ZY$p-EWAM1NU>> znGUWS$JX+7a|1?Z-jk~e*G9buHdg%Z78x;u!2lP&cs4nkAQ z4S2f8uofw-;F!>=GmO~n7aA_;>%yz;F{c?RfTU`@$U zi*}iq2K6`;PzKRmv4WxdpiTb{**nlK2|Dfy0;hL4mEd|JK%Bm4kn!JN2MI^Nkn&WmJ})m8WH^djullmOLniRv(6Os&8qcZ`Q&>J<3n#AWh^-_eLp7aLWJ|xqP-h@9X3?oE`EKidQVRM zz*damtLia0{#8Tq35+@@=RnhrY%)MvZ9Uc{v2g)LF(|TU$?j%)#wjl&TIeCX5%_5C z%!U-28lWR0zpRl=tFh#FS19F%EWKd|v4i;TiwkdWrj0B$|A3Gz>s|a?`B_9BDZZR} zw_M5AE*wO$5kos(L!%2$LyjIOM~;)kk#S$@;TbFjN_Vzqo_K&BcuAd#|Vyq|x@7x5&T_%!f z%b_$WSxa2#F)B}AQ)2d;SZ6|Q@s}vkk$&0tR7?*=5n{AutNg~L<549q-V z1YpsBUH8PX)Byr1SfNXfYyCop%XPepJI)64tS&XIqA6KQLaF(D<^*5RGMjpfJ(X^H+>rGlf?P{(Pk-)$4J2(B) zlXhe91N%p%^J+0&!@yf{%W1BOU#h_QGO7OB(!YNS9zTf@NNu~xOPcH4w`u4VBApZz zzJ=ad{reXVc$z`EEuUJ6+4aj?XJ##~C&yk;_vb0acINayXQYU|QVOPu*KS?CsNqDz zQ}iezntwcTe`!N+X|BDzg(ohDVyaY2|6PoYzyH3e!BN}8uB7B+8p?-XN89{v^wRNo zR&Qtvwuz`_vNS1CKcghu(M7b}L!-1}@3u=M=H;OHz$|mSKrsL`dbrcivKK74nY1d1 z?EO>QG2foL77=ZFgxd*$GMlsejOlOw?iA&3Hjpw0A~X#;?tlGorUlQDxa*TX(wUJJ zWi!3LYmvoI1AE#j3^PkY6Sas%bvgOQBItaW=`zcU@mw`N5_*enB0ArceW4)hxHEsu zp5;)APz@jwjG{C;)Guhk`1vb4haoqb$K+_VvB1#aMJ6PCuQ~0DJbX5IQ9}Bd?X7X2 zYPa3+7wfzKik!gnx|0*WjXy8M3_A?uRr$t?S6Q66os3F-Mfkn;1BaJiBE(gQGvL-5 z^m#1@_=Y3<%arf&Abc~HCUCCOu|rnPoy2fvVn?RC*5IW>$%yr)^o&hbvUBaEDDBIk)nT3sZyox&_DRIaPP zhWuL8GIT_)y^1N`X;ivNm5bK5>3FERM~tv^NpMVy6vi(NM2~)}wmOvp1MXa_$>riy z(Iowz7*V3M;70=5Bu}T;MabWc3pj9xiAW36MPq_p(+sGB(WU_w+T+td9v>a<+&FhG z5bLq{_r2a~T7yp?OOFV6#|T^{KW^FM4R&-RZ6O{&qw$Gs-04Hmadv8z{WaDOkv5^R zcPE;`LVaJNt1j9ktf46o!4}F^{3BIZ>wNJQ?JR9Gey{25&j7c4Z?<65o9G4Nv^kIa@+f4!rA@V1r){>B~J^}m*^12|Z z3A#ClOn}ZbtpPS*PP_q?3be^*p+_^_;O&fyGq-_uJ`_WfP{#xM@DCW&h?Z-8%@y{2 zEHPRwEf=^IMXcBkcfdsZ4)6@C0h`ouEF zEyDvY5~$W%84^f=f)JU~&_zGwQVVE->rmj4?vLM)r6%QSZKGrDnno|d8xax3%TLTJ zMEqGypiPqL>+X2w-|3^Hg|BjPU;1MhXm|XYe@poPZrk!x*cOzxN_33VKF?P_Xk#X6zRyJcwjtbG$oK_X>0 zXk`9zj-9-pcad|4lwt`QFj{=BE-uVsw#4Z17m`$iwViR7Uu$wT?UX*0iQ^FHr1UEN5N(|)|(>)WuL=6u^*mWGE1Zkqhn6%a0^=D+D$o1y90IH;?*Y)lopL9nVIHv#Te0Asx^?hW3t9B* zn)rd!bjFBe9g{|psCwUm%aCU8mAw#bq>3tX7KnKp^}sc!Xr+W%?IGkVmuUMF2aDdn zO&g9c@-o<#&j=Sz*`*+volotwu4E!bw~f9biihD8)qPh}^Sw#{X-dkC-#f_=MaBN< zcI>+{(qR2Rbd*+msN-0CwTy+V3SBrX)iV|adqZHM{^j%6gTv)+aox-=zKH72RdKZ^ z6X9#~z3OyZ+2r*DEONyxdz0d&sWuAb_8Q)f>ONI(LmhwCAY;E0FX1qy?ACs_EkN&Y zmctpMpQv2X?jbEZACvnovO8e>dyXV+beMs`on`3s>I7o`B%yP5qcCDfmT$IVg-pR4 zx4&-Y5(pF7QnW>MSdUfhlV|4Q20*Fws=x8@UON{$C7-nwc~O$HXK}02lzd3P5EEyX zT=s;jBx^)wjGUY7^_yg1mhO_d&mZIyAJLtYKh}rf7gbaRW38BpZqOuV~a_CBfP_7X_ zNzS#xs3QY=ZahicZ{1{iEFMy1~po$l#6he z6rm)#5PJ1-iJ_Q;#bGP7^u=CXC<)V0@UJulDG9-F3*PrEF77uJN8-BC;_2{tDm>-N zC)bK6#%l#bA-KHO)x^jMIMZ+v&^JLsl5Q#3Z(hB6V}lwIv0se)1O1ngh)>qKGwu{+ zx04M7ejn|u`oMzKEAz52l!^dTwgJIjM*P2|TAl4FZC{F5^Gz*ti}; z={Pz(44!n*;67*)4xNqh0PJ$v*E5&q6tvvY2fep$jt%_OVbz2u#*uz0%al2c8sQQv z1<~!eX!*(dcTmDi@DBIqRu5H90aAiH%f5Y!*Rpp~!NG=m&KzzWN!#b9!~$k~ETmZC zQ<9Rb`aZzP-(*x8LChXXRXFeB@O3W$lPpP zm6CNmNP3uBJ^XM~;Pz?n$=mYc2m%C$47(~xif3T^lFva1A);cpev#-yR|p&1SA7&8 zBLblrVo@Th6yx`MuZ25OinJSnI(NY(eom$~e z8+X2s#dt0AhE|TZ5^OLMkNs7X&<>9~q2B=DH#Mg^oLSSuZu3=!4LK`p-_iij8Id_g2 zM8s*pU;+VLv+o)mxVa|?x7Oc+B+T5PBPl*^&OBgw(M0N8$#rBzKXz|?I3Y>90}$EF z9&84i2On_~!!wAj{{>%wYc~AnrVIC7wtW9eqNwgxbw(GA_-*RP)x{|IrOL`JD4r#B zwYk6oNc7Po>eDtVE}^$1>`jL4G!xpt?>ycyCQIzLwXw;~ceHzd8c8+p(;Q?yln=vM zh&I}a?mOr$X}nW=t9J3uXX?Q`7qojfZobT0m!H{!bbvCuA7+(v&RSmqI;yqus%Ck&y(Q6mr@&#E5vxi%Q%jCj zaQVgQ0}H7h!Oi=|H%@}MNGwy0zr54dxTzih=K ziwS|j_I}cR)Nk?49*`IS3bv7i`6v@NWFys9wkO(46*xL`{A~u9fdMD0_sWZli_6Ls z9{owRx(!CZ;piyOxTcClzcK8kwz?vtFI#ed=pX}LDCM0iQ=(&x=oEN;gfKCiT*dZ3kodzHPrSJ4z zQPDE4w}@NCI_9DIfg=;)EGrwJz!n0S30@uf)=h_qC#ZHlL=h6P-_%D>SQNTlUoOr4 zw^Z6>I=jY!Cu=AMsFq^^wEoVFT&b*;GgEl^pFm9m^Vjue33>O+K2?H)N18eVw z@5idD!7VwXLI&sxf(>p9Jx&9S($;>j@9e0B-?Cz$XokJYaU1auKkwf8wFZ+}EIMYbq>IBj!Vr0uYq>@6FJoF4bfz6+Sghp0)4p={R5-Vx%*{SqNb2Bd|gW7NsRnzI}Uq z=Imq!QtQ~*LNOT3@f7sJvy`7ngW+rY!bU}2PIk5xa4s?yy}i7AGYT*&n-HH^wm4Dy zx2G`L8WuTC|IJcted1P`nZ_ql zWvgd{5-Vod=0m;u+;1&3zxOegFQv(hsrm%;Tf@-L;u` zt~2Md`ukuk3Y=?jdw;(MuRAS`QH5Bt{4(I(`HqmPCORRqfLVP?FeSoZ6H=EE5!%A3 zx}P_H@uBezT~l%gvt%s(OqD>115OjHc-*E420Twan}G7=ufU3k?OI6P*0_0fMC?ub zN01n1L#fGU;6$sPha=HhwS@!q19lfRN`?Kb1!*ukc|CKS4?ZPD(4c(JwHLu8@R76f{axa~fOQ6lv;V6L>p1!~f74yl)3pE8NHvTO>{&OT2*Q_5g2Ro(V zVJ_yoj_p4lsvLP)^+kJ8aKC`{)Z9?}ywpV*4T3BK`Pv63zn^Km=9XZLt7+c<(&<}V zwbZt;JNZudQUz9;maNQB_HfYKV5+PuQw8`)LfA~a1bPPPZQqTnay;z?w{~uBZcsUM6Z2wC zH^K~zAlzBMp=_bBFrSP)xI%vgdo+F{k?}h|9Ql$LE}lh%%Ukwus5*DZfJck?HyugJ z(1WL5jchM;wA2y?TVyn{ABZ>c3`os}h9qdxwBTPG-O(8m(}~uvS z!x(NIJdw8TJbaa>23>oFoud3Xd0o7kh~f<;Eh-w`4J-mt?5;@3#()%7q)&I)< z|F4gbT=;p?+t&a=ojF+N{Wx^7Ay=mNimWzY(MvR{O{5|_qimIMbVyuR3lE_*Jz8mk z!fPpdaH;s(zoS4Z0yxgNGqbk?V;Jfkogulo-5Aj>cZdk0A}Cu0y)-!OgX1ytUk!G< zEJsGk`ayBQ%sz-rrLl5Ub{LZnqq?7VKU=@w`-EVM2uX-wx0tB)tY^;9!33!#jk&c^ zdKZb3gXt1D#A$Lh_%!zZ@)(P_PK@8Tq|}!-PZKn4d~QyP_|TiMVfzm_053X@W`wAm4)7A#5VL z?@R?iELr%E9Dyjz3@WC~0tGnVhFrYoT`;2S`2{vQP)U%y*BA=!GDoAuY(FPJ6At)C zd*Vj_8Iz6CG949IOQl?V5T7>wU**|ZZCwe8!c-v%7ax{8nnBQdpvbt($XwyqSoN+QM|?&6EhR-?2EMg<--eRgKWfL z#lw7ljo{dc`7V4`OG`_R1;CA3hSkK4ZGu0Pzn|d8UdLkeAHQs}h2bYtxafyQp^&+j zZntRSt%i6k7Md18T4Y`MnZ&dq-+&`P59K&fo9_tpx&1N7N||`%J8G@?a($;r0pX?P z#z>_?4z$z%h!Zz<5f-Bx;1;*&Q4a@msDU!tw~_LhO!*Aa7t5&24$xRnzi-uC**wRs z>cV5QluG!Toy31JduOwhFO;})Etk@-z3j6i{v5SAXv=Zyvpvb@_467bQ*YhYm!_e_ z{z#w_@#V`GmFz4Gzp$`T_VCkSE zC7m4=GAP4|3fw=>g~vy{_Pvias7rl+_?dH>Iat!IwsL%U?f>r}Ugx41YVzf6j0ep?gjxRodfUGpjJDHMFQZ}nY ziGRS2I;#LyDGA-Hf`anh*@Vhj7+{M*PWWoEb>&z9!znv71lG4bdLeg-7i(u{Cx7rm zh4_y1wN5j0^U4Bt#H=$PcSASK$}PE=#qI6yjViv8Noe15^x@f#X)o~};cFNIl2=RC zcB?Acj!;=22w~jNYJB^^G(apPBbev;)=j$UEnpvG(0__9vVU>}jU~t<5u-`yFPl|^ zP;$Z$R^_0EtH|aKMP#GD08rT`0x0i0_XYJ)@5^1HHtyt=Z(f`urpsHZnHySdc%T8NNSdB5lXf?v>wS%bgAhGf+H`rvKy;0(7X9C8*zm^DWNnn>wKJmmP9 z-f;y-gl+*B65AXY*)3lVa-bH5m6yG?D`$vkS){k zaelH^AeNW?(#M${#@S~B#$KUkRQ9yGk_dg2`;`kJY$-kC4OYvvWxg(Lk2Y_9jRG^a zYc^^5R>z}~u2`g4WQs2MVI>2b1qK}Unss^rZ3}Ea)vVNrlffhxjrMf7`+sO}7F@rB(zEpljq?;yQ zRA280bTQa~>vJyt6C$^K!=iDiVLlZCKxjUsXK=j^jl1;Q9A_>^4Hk2M9B(ac2Grs5 zgudPhyRfMNk6h&D;rH@D@Ae34oNfe;7P>>*a^(dZ+I&Da#wh?Om?Y&+wue&5$phLb zm4~XMqM|?>Q(jWy0>mAl)c+eTp8=#Dy4D|n&5d(-yw}9c^Z{I~P<#sk3vY9@)Y?F_ zr=f8k0d?umA%=-s(I*f+)1Q6gAuvuLJ_@Qg!MFujddTaAZdd)xi54=0+Bp2%>qA>P z`PQwE+CufV-7i-mXDSKU34lx!BFi`VPNs>eRn~i1GEqb@qK(j)loTGCNWt=lD%Qbv z4l2}rTXKCv;-&h$AP&lcvkD9+V05TmrB(1)SAJ5Ak^L@pO`TmNEmDRT(W1WqOX{;i zN5=fp%U$lwi(GNFtyx?TPCD)#hpipqn2ejtE`EM~lCS@EzyG#Kx{>IzN{Nc^L9DoP8G#1d7bA zaKN(mGa?GJMkj7UhIiz1A5=*gG`oBx)OCj30yeVcw=o+$VBueMF_W~nenC2PFcO?^ zfRx+_PhPlb-&%IcYUvIs9Wv>Y_ho~-lK$=Mtvedeo8H@iGCVN;TW1bnJ1`yOL z^b4uWHw%V*AcFxqk|4;*!zjrR_38|9VSqUeZv^J&Hbto~{=1*3fLUs3`G5SIQCU}I zSmL`FZ0Hg4bGr_Y24bu~$+N^~a^VMGgkv&f@OZ|3eV$0LEUrstZe@rHm;oDAp2)4k zCf4{ai&3=#rswt(wZb?3cbU5eyc>Z_2Uc9r=lDO8t^=Iv{r?}M?2%1&WDBWW6cOnp zD?-RDQ5j`sWGh5CrG$*^5-Q1#kQ7R#LP(+{3fcT$-`~IP^W5il!#Usc8SnS|wI&5F^OaU8klv`npBSGOXyeH zPn+?Tx4q;4q7b5TGgZ6Km-*0zE}8tOYoar?t|r?KsJ$P)8EZ-wXWA4PT{bDKS?-CZ z4~)qw`Ob1Da25fiJJbkzHV`xw@56FG|*n<2N zy9E(Rt(=HcSRZFwPuP+lWxT)Zj{hex&=*0s2S=(+^|dFgt;}A+!>aL!1P3uXxY%{G zg5)(fv;P{Ef#c8glh#D~Ra=5k`+q~gb_j7x#8!GS&F-yA4o!X2D=)*SXz0ZtGT110 zYK=p?)uKe$<~qM*`ed|CKVcDBh?d8W@z6fo*}ZS$?cp7PSqo3QLp<7ES(i;#J@VIt z7{S-qx5GuH|BZ+Bjhx$rJOeQbYU3XJW~&O7ooPG3vLqHZvQ@G!tuJ9ZL*$ZRO3>=` z2cN&F-PJ>~8HlC`{{1^hR!(kK&vk8izHx2PnNJMquDMLE;1Bzj9@{tH%(UZG?dn@( zm5eNOX4yh)LZ}H_xh=s}T0MC9a3}Gf2#8=51I_$HncWJ$fLTa=4sM3z3afi_`KcGwHYx9TSeBR_A?!t~G`x3*N{eNVw){`An5 zu+GJ~E%f6R{-%BKA3Ya-y8TT)+vus8M-O~h-ASLg#X{z;86(#-rCdrSG;CE>$LMn? zPU%#n7sXY-tb&480HrE){+yUFkl=V>_Dd#c_E0Q4wG?y0Ysb*W+}y8(hajxB;JUa6 zl-BEVmWq(kfZ04$>py*=dxK5DwpUfz0zv7Y4=|fRL4aMY^8&!=~v4`YeA8l(lhCUL64w zKQ}kmMB3_xg*2DiI0owkxo}i%XzjQEgX*twXCBo513wQ&Yx7!qUYo{xAv_f^lbMU>q~@4FX5k448pE zs(q!)AzfXX8(LmngevHBND$I(A}pr>b8p3)a86n$Vp9mxBF7clP_KW#n7o9sjs|M| ziRe`|s7ml&LG9dtpux?<Ov+z;F#-Jp2xV!hp6$}ubz}uDq`#M)UQ%Sn?_64k zeykDqnnmd`yZVWAjB3gn8bUGXxw*rAS6?E8lkZgV8L>9(bOJ{w3H!y;( zdL(G`*!?}GKDF3tJ|9X-ONqQJ)EVb&hCa=GjwvXJ8EMh~8M8f#5%4p9%(kf!Fd8TL z#q8DYbi+lt?PIm~=*!MdWKH?Q0vF;k_2_}t3#XhN#IBR^_cy*bitPLHZsOa8&8``< zD3L6V9cutbak8(`?8y_qwbC86Mk52tL_w-Fq;Bf8A z!u#|3QPcCK(w_f)SY3TsYFTDwv|pLJVKPBz=f#QP{kKo_m!EI_TOZ`tSovF0l6oX4 zb-UqZn-86nCp4{|Y>cIy;A+_8_v*hZHzjG3wp{n{)G+tY&aHb?nJdp9ziW@GNp8uq z<&Cub&&QK2=N|}ao^JZ`d2sT?@gRqdFT8zae+Hahzw1cQ*_Za8&rH*^nl-R#sENoL zh{-4W9$a!8JTA6oSW}O0=h4pkUTAf`Wh1lu``KQ1_tUoP&nq)Esvg+QYHm}y_|9M? zsPm3hm1|#@Q2&>~#wS&kb%s}lo2_?_R?U~%YcBq~Z3Bh@0NY7!!LrFUyE~?0w{2EBiJ~}zAyOD!OPBs45_|8 zAg=86{Bm1c8;DN_#7*adeayOkC1;3dZ@o-QlMvw5#T2ar4w|^To}QkYo14ll1Z3I6 zlw3if)s|>PAl1s1w088ia#W5u2DGk((9*HF{6u63hP-8L5Xb*Z5ABiJte&8oyQWpVzSVk=_QJmZ3im z+yA90or6F`}`BRmhjm=gfgcebE=KIW>jsl zko{|%T-i++E+{s`FrCEAr!)+_7zdZZi-+fGac6@(p)s_?S~L4%r*88tipn+Ea(B;) zXZ>>J%rIe%a*E*!xf7gI6oz|U2!fegXS>id{B&>%!7Y%S1PDLrCF;`koTj#A=Q!lZh) zi=fU6EThtr66TgBLslZQ7$)Oe0w(Q40zYvYe>v1pwctl!)@04i zyVP*T6i=3xkufE=I#sm9vO&JHMBH?s^T3v9T$3lBVQB47)o@VKW?~m>&!s&5mk^e<*hdj{zl~`1gH% zL~VQqgMZ)vMC(PkX4Z4+AWh(-CA~Mm2z%f67NF?=Lb~M*d25vm-wj)oSb<;v$WJ?F zVF9xnh6D6(1_o@89s5UEt)k3}aw8X8X~LgWp);5AGhv(O^qjT9^#JRk; zRg7hm_+aZ89EiUI^a=%p&B3bzzKGl-ss#+XV*7h~hF8|n_=8;Ul8P^u1MeZx_p$5$wIo**rFhlB7@1;#XF(spP#N87H} zLZF372#65ga}$s=K)wO(d;`?0*szXPpL_>J=~Fts0c;^8^|+iHN=km>F{KxXO*bns z_xVBxio_~{SqDdFBGCcz#H?`;%1~j|lm#IS))4OtMKAc|_A0lYt1+A(1-#M5SBkD5 z*#I6MfK36%YJiHRtE-E`4@WhT(S{ul^K(Bu5sc2N4`fr?M*k!xvJw&9rsR_kKc(4+ z27WAeBzmOj6{1Z*t;Mz7PWja!%63E>grb;%6ekZQ>>dv=&wt9_d3`pcaQug+dtc5F+Tx)pq| zO1oMtY*U>3DMQoOX%aW&_1a(m85=deSI$`sa}T3i|MLeyTiWMqXYTyz&zCBU8|?8Z z5iY{$v4m(jtmzt82B&*If|E_N;*MqW?#q|oHNT0rXh-k})1IN=o#Ur2oat;~+hB7} z*m-}+>afZ!2|EifQrI(%N98v~oD-&?Lk8E3P_Q@PdjZ9QdX%_0a1KID_H;SDHF30V z?(66K({)odiZvZNm!+}-npIx|U4lz}(c^6^O*Cx7?*6U4rO>gz>>iwL{rvfJIO;i*T;q+5Us=66sB&)uCMIb^Cftew{i8PB`w`#BBT4Gaoc-?Z`Gy@#szLC zebSAY8hF^vIrHUrePm3cn%6|psW$buKZvg*`uf%AcoVH(h+}`BX!jTly+qRY&2d|I zi|yAGcCGn-Wq9d2m_c$Z*gnR9RVf5E#DPhm801I{9yHyeL(at=$ubLR*M-H zA@kn>_vdJF7!+(bVz6?~<&4O=vNL2>Uu~x-kpA{xRqPRATsrc{1K?hUcCkG|JfEwV zg)l46xUiX#q=;NjQF=&`*+_{Z4*Teg%&#oQ7QOPNbAP<0gF%d3oiV#jzp;~7o)q@D zd+(l)dwFQ79AnHd>{-8PJdC-M#_HrrXP z^aO_4S*%VJYO|v)frjzF5S`0zKPLEdxWR>Jh(8<(V#m%C(p-j_8i||_4N3IDyzd($ zNH=phn=_mGsy8LnmTeuU`m1VkO~%|Zha!I6qF1%un?$17a+6l~cM11lA7jIn2G4#! z^~|axnHLfh9z|@0D|7hqcbA`ils4Pv9h-UFgwIfdmW}0%a`RWFBfaOJ+G+~7JAEjx zF*HDO(96Jm(-T#Q0bOlUJwo9vH)IXJ_EIX`CBv(WMz6NiWu!h%SvtYZJ)K8ihtFAu zt3`la{7Qja_>O4y160llD)bRyW};E6@9oztG=(?T*+MU$)qFQV9cD6y$>vCz*VVTj z9V`Q)^wl2PY1?TW1xN;)%*c=K##N@qYaLkhiM;;YP+xS$*62!C;BXM)E=9Dmz?nQI zCHZ23U-E_{U(K;E4>qD^r4rHE4+gn!y`8S0aihaUzLSGv_`pe}yHA2Ga!Fy*WO^z| z>3n|St;+6PB*BkQ9vt|VPl-BD3Nu=fyPi^0#;|3grhp=-dfH)oDl4^!cF5d8j$Hnl zYn2n~C%MO34ki|Po;GmZ8O{~gbnsG`iQZ+}YmD?KwPhMiqI}j7eqBtW-_&L&7Iwj2 z#=%zk`{8R*RK3)C5{}eGxdJuyaqi*fQQlM(uR+UqmgXi$*zsHW2sJk&eGd7MBn{a- z`!cCSdiparoB!czMTS{P>6a}mGeH{m2Kn?BQMo60Vl-|Q9B!u8^RkSp&?aY7Oty2= z7juaPaLn*AoYXFAerQ}QVXn+0eT~8>nqs!fz-4lTjZ6Avn0IiFG))0Rb~tTwHH94R z!bM@$X6U+XM&3ed4)Yeg9@TX?tfh&Git_bLouIZfdmL}HiJfc#y=9btmLNIYyGM0@ z@q@6RF;3}H9Rr=;WePkmuCes71&hh_apmYxW#wwi2GdEm^y=~PGSWK6xltF9WEqZ9 zM*pdiDBE-=HxBMi+p@1?*zt<$MOrg5*ZC|}Hzdv!l|_{CsOU-LfRby6d~HGnX3xLr zhPuL_TkJ_|)Y_5O5Dt`;d4K`JYwNY&cyb37Ehm>%Bas_QY1i>Xr6Uoy!PDI)41;%DPD2&LN@tt0WUqzVs#u6~zkUzvfB>BY)YG1Rh^C&fUsB z(o6Mf&)0z~Z#LhfYavm8=!^M#{f<+CLsTy*@dIs;gM&+)a*R22!+r2Ipt^TWw#k>q z_n*?%$S7eM$sg9aa};VB`5wuPxB)YHHjR;gMeF=+-<2paMhk92{!zV5zXHS02#{rD zoBUiGwbKd?d@Isl-1dy2Pa=#&P1&SFE>;^i-$qS8BH$|6dYG1!L#gOmd0Q!Od&u$U z_XJ^Ty_I6O7I_M)#Tw3GXH4FY3+))tgq!r zqE|Pk9hPp345v;woU7C@e&<%TOM^*|ssc|ElbGgE`@!ZZ>lj(epM$ZI@>{iz)-#J| z2y?~j^{Sdi>G@FA6yJ$TNin4rZ5Ck={$9`=8c1T-&z@n`-N9{V`E4R+=j9xd{L6x0 zue`Dhrq!7OCg(xZp-YM9H0t5JoO+=9o`ziRbuk`cF$|D8i{`=bTmY z@YPeQ1JViVBP)y4S1ny{HSs?t^W`;(`Chs@cHLm4ZIyd@+s&M2$xDmLS$@KP>h#9u zMLw|`@h6O5JknYcjb@*ak5yf7P-nP#YU$cW^aZg7{&co`PR+lL+`RL=qmr#X@?hMa zLq*b;$5~=|jXqZEG`}8>RH#(`C)Aa^=o*mIvZMK2P1>nou7LWPhZALf$IkhTB$-#W zJz$lQ7P)N|vB1#wVa6xZc4NVuCP}=`Sck53g*&{g@Q1|2k1Z{cEFy{nOYMBF0kcsW zVuKfN#xxbqo5!x~`}6Gi%=4VrIzd!+Y*NP>M$bHo>3LtnnAhQ0omaTF?J+5`d}I~2 z3MPCSkDOYaOnV<45P#DfTFyvM!r4C|IsY!>r?Y5=#7ymsc@&)opFX&d&TKY8VocQ0 z%gG4?v5xHTz8$m7JaJ}JcI-+r3BQ$r+BC6$rLA+tv-(fnixpe-TyE=KND;B z;ZIRZXtXP>;{>zoG0lHTrYE9f!y+`Qb^EKj9g280?1!J~35eh5cig=xKg}y(BsfrK zPSttjWUI{h<2AePgqM?_M{5h~=wsOlTeTrqr@3=-d&ND0BR%PLME~ZA4fg zP(OXKdD8(a&A1ru|AP6b4zB5*O=BS~ZXFBR+ug!7#?PGSoGBN_@}nk^xiLxkOpMG` zFaD^sY4e07w*4x%4x~tSIXccOHI&OU^@dqREh#7RF0lJewQ8_GO{u4rP0i-w`ob)o zjGXRJy=wERuk@KZetC~520-&vP^%~pTBuYJU3ED zSN)ntXzd2SwKPRgI0ohFI%eE+?1MS%8O92FDs)C8oF`gZ={Kk4*tAOMH+j!w9@6W+ zV8>hf_l*byx9Fqba5ite@=`(P;pL&rZLHfCv&PW{_XL69??C6OrcSjvqXFr4c7 z8GYeI(Y}G+Z9Tok+S~ZbdRkncJ{f&Ju3FdMLbvmlAtHN5>JqzB-O__o#aCsplUciyhFW*OR-lK(+7M2=l6G_AmM` zd#aUXO*_g$ttV6+L)q#ZIe*jTMfE(cX0m(OP*dahLM0)5_>o8h|4Z3Y4>Oq}mz$kq zHM8mf10A1bnK62vUR8XT&S;Em*LsEl%mw{j*<-^sKfLE)9Av+@Ktr6U90jv7x_*{d?u7*)T*9>J|$xa<=8bsNdCiIvp+ALCF$t5Y>&my5~^Qe+vQ zNCW4xkJNvixcGL)^AtWDGPJbmHMy6{&XLp}^x1gfpO>1=*ZJS2v+P;nO34QFGBPsH z#Kq^@D})Yz4Bu6^MOR;F_x1@+hiaPCsEOG0f-9xI=0{r}Q!9#UcDHC#jn{#&e>6Kl zzFK60d?{zGm3(x7J4-jXx%(_F$+9wl?(4wPA8|bRDPY<6?)@^nWlqw*HC#@ov>cgp zhMzY4TtDC297@)=b++m58MoHGqTzJYAA5Q?_{8HDpDA7C58V>uq@)^ay5nrFH~E>- zd2yr54_{l3X;UZ%sJ3z4r7rd zzgz7`DZRFVxi)9alRos%a0&4pZlbC?D%5_Z)ydL6Wd3BD9f;EKi^7x+^aMhy3Kzg_ z_PNHJBenN5*3}7~ysMlQ&z4f)hAy5D3NBDWdah`Tt)Vl8@8J)i%s0(iVp&+E)dwds zoF=t(UH}r=%qBcAFp%K*`elZx{je|*t zE4(_aK+r)PAu(~p#N(r&u+$s8*cah_#$mW?g{5A4%;3~LLq`#UtPkt?XUIU@j>5$KL}e^20O~z>VXFkx{+# zUaU-4k}!#SjbN#9*9(7qU zd`To1U+DUe?)E1ZVO5j3Fb?|Qq_D3EX6)gXhLX;rAtM^$mhbqK#C?slmk(^Z@$CAH zG`$hGf&H?uRJLhE;}tGZYWDqyGVpIYHFX|7Q%MG;Ya%1-XWQE0Vy;5k#qYrONP#?9?JA* zb*W}vk2i1mXtTWH1tl6jTvp-hDC|F%IjS@xKO$TyG*y*DSLXafz~Zfc+>J8+4DJh` zZn~LBS`3#q(QVRzu`LM)7P>Y5H7h zBkuK62fp6d+5e)cHK;@3yN{9d;VTB11#A`Yy^%r#P5mJ=c3JeMlTh%$4pIjRbSInJx_L~Wh0j? zAOPAOd_ZIiuWkA<8h%@Sc942oN>SLBL;Lvzu7}HM_U-oh5ft#*TPi?dCa5?ipk?&E zvYMRB&c##1>H#_XX#<-7JiJjh;<}&Ke6yg$mu~^F7Z7MQy0Up2d%#P7=NSE{?&6ei zrnh^1+ltMaTgHVR2qfN#FlnCDRJ>XnUDs9g>=t9N;O@&`^lt3?(@^sBr>1-V?#&^5 z&bXte>t^w$@MN#+L{3R#hCY3-AUL0csIK$qVS+`NcG0C0F+k zq~$vof6D04mu%0%tdI9ZK#n6HG3ms7c%i{(fNgBQJf-Z;~M|Il=HrEqQXfJ?hKeTLl4l|*@+tJ_Xj?f zYi6u~6`+S3%K#jx1#A`Gbz0cxID&P)F2gz(#DJp^!AW!V$RUwZ<`kh@o&k8y%@`e^ znJ6`T;m!(18L*22Gy|h$fHvE31H)1Yqz|j9@u@dtr24{yPI1;8Q{ zBPT0chFmFNRaI5HJ1Ys-8vs6V>VPROyAH>d=aBqItcDY_)A6oM_*!w=qTB)OTvSv< z3L`u@ztpe%KS$}-cwoRAxP}ek9=H#PD%k)`I=pVeqcb2?6LUPU6>8@y4_{lE?;l$C zYYL-+OoPbeDl*OUv9o`AUeft2jJpuwL2wL!q2kK3(A}fZc^u)vi0unOQGtu>4$iG= z{ikpx^Pl?6P5Z1aa2Cq|F4kBNHlFpnPWNOZ$@39RLP24a zJnxRSZzCWre1csn^HmIC69oS|53d#qCc$Y9OCN3!27Z%$Fd_DaonT3EaUcZU-@EVN z_N)PE3oGu!hhs8hzI}FkurlCkywaYA$uuVC7?r+IV(zbko+|6&&tkwg-4I^DLH2(D z95`R!KDpkh#{%qp`I1nP12DJ`6PZaB{RBQ`@2>~)&Bc=gU^{~`CES)l8fB+Nw(05J zslpgg67t`xq4^Z7A(w z`clHtMJ?%EaUjRUgp3vW@+JAKVhA1~5=TMU9lCJctlH@LL}A$^X2_W8+tm6gkZdsr zg&8oeKj=$ZoxEXWOF`xI)^Ph#Q`0v+J?#3gXB0E`h13+d!JD>8?>Dkt8Axnet6n%E z0PutWJ0Sc#52q<&I6YYINHe~Qi;&nbSc99mKElF>Nz4V99V!{BFc2iXK@9+3<(e5B zxUQlu3j{~!WLg{bIJ7u_*H@;;GZ4`1v(Zpbz>MR9M_ldf2H_ga*|mfZ2Mcsz(tcwZ z^@oq(IJ}Gj!J_PXF~+3!{eU<@4*``Au2w<#6nnUvb^oTaJK_9+!)wUupLV$Y!4ndn zYYLX7Q^g{{ioI5ejdmv`&nk8_C;KpA4Ko4A)QLLBcL`sy|Iu!3LWN zXA*v@(rgvjDMUemZv_kLe|VmO>r3N1Y^v@(emsw}ObAk>--ERTK?UwnIEJimJOQ4-&jMNk?%u5p-rs^I7`UeIT%`$z$yyDBY=x28xH?Zl_z1xjmdf! z4#Lp&**kRml>nWf{sV6r>OP!5L`ohol?;`WFR{aZtgNFlJyvFW>-8zlD^c_kUjht* z%W$eFDBx^yhasJU!ee>DB9xe=6V6n2c6;G-b#{0Ez`$ASV|XM4%Hg8&ALRK~@_rqX zY4>nI0DQukLpUqKEpjGCaM$?*78dVuYCOi1Kr#6Q)JU9j4by}*yTMDGmGMyh?(zHe z5ss7R$H=1ZX6x{lh*}!Hi237z*cF7Cm$#0N$Js-N7)W!Iea3zBIHlm<>Ix8xTnwB~ zf~D>rA#lQv#$mPHD5Dy2zJz}`R9V261|YyfX-`NV@ywOmz}kwzlllGWp_Kf-=Y{v+ z`wX{EY?MI4ep47GdB;8u*FSnR2WCtlU_s&tfC_-{!1YDKYkL%kKxTc0D?f)=NErb4h5eFRPb_>FBtnglpQ(5yr>GL#m;$lq`T;sX zTJ;?{g0+wg!3o12dLej6x1<`voxETPrJE+Zi+62 z6sEi_{~c@(2#-t0md%e;s$+4h$>c*1M?h?FyM}rjrcP%$#sj}#VS`)55#RcENt2`X zjbWZ($i6#6kdx`_5k)b&t-Moq>Y4hM{y1J#?r$exA`irzw=KA;5Di4&_wF< zz3|lbbsDACVI8*>QUb$KgFo>MbRYMOb5uewr>CGN5yC;>EW_|OxQhyIM+V{;v zd3ZoPXY%67lVhm<6XrKntGcPFC>g1Go;1(7kdiw0y=Yrq= zKj^{xxBwWDuu!?WR}0c0%ClBE z-@)>r1ErqRwv`{P9mu4;hPvw%5AaeShdj93$f^P>P*( zcNb7`xolQ~*VxdIrA*-Hxc(eR3=0j(o(XSpN#^n-7r3?eA6MvYUt%7f

`?) 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ξ?Ym#9#&V%IblndOuL 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�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 y Date: Sun, 16 Aug 2026 23:56:03 +0300 Subject: [PATCH 19/66] test(settings): harden OpenAICompatible mocks with partial-actual imports --- .../AutoApproveSettings.visual.fixture.tsx | 68 +++++++++++-- .../__tests__/AutoApproveSettings.visual.tsx | 13 ++- .../__tests__/OpenAICompatible.spec.tsx | 95 +++++++++++-------- 3 files changed, 128 insertions(+), 48 deletions(-) diff --git a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.fixture.tsx b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.fixture.tsx index 0002607348..1bb100d797 100644 --- a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.fixture.tsx +++ b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.fixture.tsx @@ -1,26 +1,82 @@ /* v8 ignore file -- Playwright component fixture is covered by the visual test. */ import React from "react" +import { createInstance } from "i18next" import { TranslationContext } from "@/i18n/TranslationContext" -import i18next from "@/i18n/setup" import { ExtensionStateContextProvider } from "@/context/ExtensionStateContext" import { AutoApproveSettings } from "../AutoApproveSettings" -export const AutoApproveSettingsFixture = () => ( +const i18n = createInstance() + +type AutoApproveFixtureProps = { + alwaysAllowReadOnly?: boolean + alwaysAllowWrite?: boolean + alwaysAllowExecute?: boolean + alwaysAllowFollowupQuestions?: boolean + followupAutoApproveTimeoutMs?: number + allowedCommands?: string[] + deniedCommands?: string[] + destructiveCommandGuardEnabled?: boolean +} + +const AutoApproveSettingsFixture = ({ + alwaysAllowReadOnly, + alwaysAllowWrite, + alwaysAllowExecute, + alwaysAllowFollowupQuestions, + followupAutoApproveTimeoutMs, + allowedCommands, + deniedCommands, + destructiveCommandGuardEnabled, +}: AutoApproveFixtureProps) => ( (key === "settings:autoApprove.followupQuestions.timeoutDisabled" ? "Disabled" : key), - i18n: i18next, + i18n, }}> + initialState={{ + autoApprovalEnabled: false, + alwaysAllowFollowupQuestions: alwaysAllowFollowupQuestions ?? false, + }}>

+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 a=azN~`a3HU2jQh@_eM}L*l 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%0AFemu@ zXfLy#m`-M0{0tYGP1(c)lVHWx>L{~{B-Ij87Wp`LoI$L@%Pln~fqpv_w{Q!>3?Kj#^zn{3zGK*N@Ik%5&e*=ecE*L=5 z9lc;Rf^!sT9tKuDc&V;Ubl2Mqod5Vu3*kidbuLpIO%;znd7923M^?y*)iKrMTY-}w zn881c#!e!Fwf$Gk1a-1J_Tjn^VJ#14p8&ArP~k#&ZxwR@T-1?WG#EE+d}3WtU?jqE z*OevkwC_61qy9xD4!*9bXg%NI$uViM;`@_^AfqD-CwsLTN&Ul9HnFe91v-)#^9tBe zPNBzjl(P$C5zO*}3jv4FAj}?I-XR5ff^&pxw?zywy$tH>ik|#YAIw--xVn{cgnLRK zd`5!|4c#L7-OBI*TkfcE)i3vjlzHDr#rXm@(2^l0%P2!vug;zw)AYKTjAsLSIZM)g zvt{?r-NGP=@uU!M@*H4aQvW$_Nb8Vrvr(|c)Cco1{b<3_T{kAwZSn38r@!S z5EJQf^#F)gXj8?S5d*o>gxt7i|85}CK`O3LnAJq1@1`~-YtiE@EUu=cw2NgpiFy?C zQA8o|?%j6{{VivZVm)!n)kvr`|?!ZhzUvy&QcM8 zu@#_#zCFZ{+Io;N#Q2jWeSY}J*BWM5m~(FhMCovp=6z?Ql&BV_(-7BYd)^hum*yNH z6s|Dt8GCEqk0OAXmyE55Q>)kilRM6r$7H`>m`6ju7U+8pH?<6W z8PBhGy5huQ6^+q?Y#k2h;K?~zfU}?c!RhX!|42WX%AhlTtINCcZWFgl=(R(k152*R zpcU#J9qlxvqC>Zuwvv^A+UTkKQy+x(=+i^o^$FIQaYVOsmn1c{4kL;2erH`Cbxp!!yLSl7 zmMt&U@#IiYB#u4|fwGL98*$FGpviOlT5=P##&-;-Jw~$&$`=Te#BZ~?* z5!;t!?u4YP@`WHqI&fJt1}`-Xh1$v0EM2cPp}|3rRTrtykECrh+VK7%L_AhV!*-QH zSm-jF2$bI8(!i&{b8kcpkRb#Rl_}&u5ZK-xS6F2c2sM1VJN*}zhHF}QqUd*waW5gB zR3JG1rhj|MfI!e9D#qTCAtbyykVwQW`kf+D3ImBOcbv5Rlokb&d!jfYWC#T$2j?Xw z9mI$XiGt@PRtYj21R~X7;PPv1wM#~~o%J@@C z#V1N8p5N=&yf+LQT<3v31qGFEbFqAA*W*FF*E1;%W|d57D6Fs8#?uGvei|@U9%}mkMcYi06X@0LE=p zT6lNq`!Hhqi35d#rhS^~5bhTffe;a$&$5DY>y6$8qF38f5#jS`K6%P(Z~x#UIKqOt z(mf)^kk_6w$$6|mF3bP5ckTa7?|*#AB{YPQdtWJp<`N_KYbLcs2&oiHluILW35{ku zQgo$KLg`@Bn&cA7rKA}hx4BPIBg*Z#?)!4Sf5i8fv)}gFPoK};pU3<4eqNAuk``1V`LA`jjx-YTPCY5!QNAm)g-bQ2o^j(EjK=;MMmQk;zgOiWjPrdR2GjUK-u#bjvsUg2P&Ya^RxaMz#uGW}~vK_=o)LEW`$4 zwE)q3{EFgCjpV-qK<456W&kQHvpXPQKiJjPhY?b*dr-2qUS2FmD3Ab{YkwC9CAld4 z`jCaKcTBs2ObIvE@{v;+YrFa1AWwu=6F88}E$`Y&(PLudFP)BPR?swOo zUj=MyZH$8$#+=tdoeK#Dlba<_v&eH8dY9JV5kWlQrw=2qD}l zCLjGGWa`Jw-rTJc^ZU8CVUTE`vlf{Vy$~aJ@bc6jD;q}Ym7ipXhK#(7)25!MLx$9s zhou5Kh`|4Tl(9H<)kZ=#KJ)%p5iEte%{5sCu30EmnD#QNMzRjw>4%_%qnZu!RbOxW zWWe1G(636;_E%4s{qky8+ur!rY zBT!)1dS*9dp^$y#xjXK90ZucIg~|^Hl=e#>S{{K&zQTGJzm}#Lrz z`=5@-(89n@wfUurX?fb&F#GzWm=HF{G51Lz&eD&n6 zJEGGCE{Iya=Y&UF<)_~}`|QEVUeqTmOC!&vX?2kY;=f0!;to4=f+$40qn3|ACvNEa za__H0%e7^Oj#>^EP#-1rPVd-S-=44Lu$?uKaCFWhr+l zfqKg(9EJ~ui-`2oyIOd5$(GN9@D2^$0dK`_U-swD9tlMR+P`{=8>6{r?plgiH9oXJ z6md64j?~0g7Y^#c%1j6LNPjoMZ@&mpU69QZH@w5-rhbpLJfm}SQ~+_mN4FL5cR+W|b~Kw1+GfokMbgQgU3x?Q zg=!U}Eh$Tx@=}!FQg+J7ilwbgvf0khj@79te`VMOx{%-IEz1plUN7b0NC6#vJvuFI zc1JK8x~|XlFVQs)_;fFt@D3|G62zNFxO&&5SbY;B$MSFblzY^ma=cDFG;p<}M?H1S zr=C@?aq!mSjDyX9n$)BPkf@$q1|d(E!<+7_v-6Pps4o@cKiL;}Ig z-aDn*qcRX~aTv z8KMg?Xyy&$n!xa-VlV-MdEsjWp4spNCp>km*QM%kENyhg2I;1x`g5o3N|j3GkRdOq zM%h4QVPADKZ*m$zy`}xr(^^DlWGl(OPn7^g+r=+lq;z2;xF;?&__#Q| zLDG-tv|ouM?4BtgeV6-&LIZ&A51|8{@A(7L=3`~jd0Vhbi8X&mlQ?QyKhK)88L*uj z=jfuy&%^=*ohTR1J(%oX4fi~87y{w+8^8&YeL33}o_)Y$}(kzoY z%SOo?2(?=KUEg^wbmg=?91kM+Ltd7ORfgRha|ri7Mv=l2OA zs&#rrKc1m%Y2d1rw3X6gyGCkNh@-nBsU7p}LT{$T_^A@o2EFWKSOhYWv+R~Xg^9b@ z(j8A>^YsqtFMcN2OHo*7@Y}6fa;qvCaWx!kZ)5}?8Y!bbU28iS%>GXJd$mYZFoMdU zzdIlMPR#cCkfYN&g(X2Gv|91Jo2&-|`EL223N`PsMrbcgakrL?oVIb>hZqhDX-c;l zLJYs^x|E`>mLcHcV4bI)??};lc$Xn})lOCXXnkFepEl_-mkKCBfayhkw_xEey?MeGh)S>#X{y9UqzCB_fWBEinyt0I2Qo z;mLa%I7+iOVU^$q2j{$hzyA9){#^|JpLc<$>csP`72k$QLBPk^;h=q~?TO_70zbjC AO8@`> literal 0 HcmV?d00001 diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (3).jpg b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot (3).jpg deleted file mode 100644 index 24cfa6692fdf0f428a7ffab2e2f99063c5561729..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43262 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°o1&O@t=Uy=0)IH9eQ*#XC|wN<$!)NA>z$*}hKA)g42CM*_O%pxe9 z(Yaf17@D_Pzo3(j#9)2;#c*ZU`Dba!Mdnp@D|x!Fo?Y~qpCsQ$88pMq%4;pfPEF&x zxGbqY9L2p#`d*(lViJtJ|h~?&7z?3H2Wq(T*=nA#h`Axy<`ssI! z&@YWSbLXUr#ChL3`Oox?VLR>~Ya17HW6zJ13s{HDOT^jG+ilzR@vI-GM{vp2nHy|8E_0e4N&q+C-0IQ#-!hGdv zp|@uZI-O1={#$rvF928-{NrYemd<^udYLZws_{RBUV&wMf>~}DG`Rah&47|+&$}bE za2KU&TNRtgc|HK&*V6h`;o)Aqqa1Hhr4pUwqsAC+Bbxbpd|@a1LVqGU;%9%(zJeH8 zsID5q@+)->B<`6%Ou`b6tiErGS@m667neVrHKJ@Zah*upnC73N`+~u-R;5} z?zh;$o9n5HdW@BrDs+)0om#0xaRT(G{rt?gEpl# z=4nn@1K|;AVOmYW2@ya*Qp2mrG9N-Ws(NRS-RqD4M<)*JgaSnHP}4i@@PV<5(M*O{ z^qLkk;(=2MG_F6Jc{Q{sD*RA{&9KNmSQ&q4$fqUsW4A^G>{4D1D;L$hakU5&^C_4{ zM0(ZX;fLjXq4M`0`Dxi=c=DvcRoI%x8CmdsD+P(LT0AaLzWTWvQfKU zzh)#-OO|!`#7!L=k%TO>5w@tZH8UAi3c6QsWb5yuTiV6gEW?<|jkUy#)h2z*GbwFw zx3!ffKgUNH^I}|t_l5gcNX1Ddl9JJr>8;|{=6&i>`I!$(fT2o9mvTA$lC6#46y)Z# zoeMd*maogi$eiH*F>vbq7pygsNDQ3t^AH5pc8usAPldgKKwG3>s^Y_c>Ei(fHv{Ij zG7Zt`(t+g5KRkQe3f7J=j_WVxvM=?dyqA=sq#!2%-<~T4!?OaU=SuT#4OW)o;=NyA z-y0j?T=Z{3NBsVMWoC<3=+1hP-qeJIw-avSi1I7kw61vxtP=clv2n4)h`f%mh0(22j>Z@yNC@3j44Dv8P z)8E|4Eb}O#!&|(bxH=VKdTAejzcreWy}jCT$baS@bYDP=0SvtXmGh|n=E!8=X?@1T z8pnQWcnjy7jbjn=N+e&^eb8qRFy<8wTb|=CjArS0HXsrMw8*|i02GUiR8%DANV~){ zLhak{-$7(yJS-qQa~uG8Grc-eRiYo~s#JaJfYp`lC-3Dht%4z~k4XO0 z>JfWoz9g?OWepfEV=rlA4b4_N0b%T~d}Ua+nvCKWINUi|3u0|U^tLgb&Yo8UcRrQa za#MjTkk84ciAC2LhEg?Sgglw;9UKaCb8W!JaOP-wuOjBX>%@TCpjpMBP%RQpkz@@v z^nD=hjF@7P?;A1$13GJ|cb<27UVpnlK>ffWCI5sRdpm3?b^RJEd)J^tHGWv9$u2~u!%7A}O zt1%!kdIto0l__^0FT=D-aGk&@Ex;rZ80%n5$l@=lr+DI3X?i@?rEov(H=W|1c|0Vo zLuUwPpBps0fz~<+W`w4~Cr{6_?6;g(2(CH>i(n?H2g4l61`hi8=t60;cZa`?_;VLnC%(2z;QQTt^zVb~#B_yK8-S~Lv+%EJqBh}Z zC(sWuNxHOr`GzV2htQ%Y|30#wENPUjPD3w`esc$IjH(ZGk6@bU3BcO?pdX-FfYCHO z`fJuxbr*d4bYDxl_ilUvMB>5)7HKz2a4N*f9>Xb^HS%b%-aCQKubafk`JlG5P$q5ZS(5)z*Zp7mubbA3F zZd(6D=FW_Bzy-8u59AA73cHoSzJ;mcPzvsiJMS`2$X^?hu>bqG)eEM|B<#>C!~IVe zQ1k#6MHbSs^%2B6E^cmA@!dEDgzrLZ+=9+4v0vRhnK28#(7FQ+-8#-XmICgi$5yO) zgQ@xHw_B{fvrqjMn&Gxx)((%i`f%DS_%Ohb;PbUV9}RjMNtRgNt`~*4?j7KLlOrQA zR>X$H;kJOuJUl#H?KbxbOvsm7_;*CZ@}zRXc*%3 zfZ&|Ri|v!!A}^2=ctX@aF)}^!{rgS}XFNbM^MKSsqynIPZp;P1Vz9J?Ut$w1Nl%S=wW!?z zqFZEGCkT+l9!|@3RRf>-6!602o?m+Y^B3Xu17;h&;0vp;@W=H}Fr{#gng7|d16rjQ zxS7Zs1p*bJzO8({%+s&e`o?M-?|)*tfPs}6u~!<>ypJE@OW^JMya0RIDazBg3Rw!&%Ie5+@{ z_1c*3##lx?Ufmr{ImPe&+=#v{c!Q8B2r!zA;~-b*&gaj>i~eA&3{7e{=158Df#d^N z5M*r?@HN0Dj;RFU7-*nenPrgv2jU z0qz1U#4P9Q_HVKth7gqsh>;-!{TEo*-G#=&?5w4y=e3t!ps_pKh!6ZD-3vq`oIv{F zk7}6dI4gS?+o0cs{Y4hErGH?6f*pT0tnc8zuejezc^85`U}giX50A;}aC;f|KVjy0 zOnHxj{ktBqC|o*Dl^Qn!-mXitt>FIn4Cjjv8a!$Oya&BniC5%d5E#H^YSEGEgBF1xIX15SiJ7tr9e{7g*%#KmmXQZ@`-rUP+rX zi;M@sb$qx@={Qe#`Z#S2ED1Oj6tqxU!Ep5^$i*QY0&w0>OPPRt^F|S!KaWEPfbb6A zg-aZPmuy833#|`uop8(C)$)&Lnh?2+7xd4KDzA9W)cQtbRYK znOnf2ebJ9TQpWBJvZsoOhzQgR72BhL$bjSMHbe}RSbP}SJHcHnkY+*?;0-?V_J&rd z#fL}GUb=k!5pMYh-UL5wG;SiLCR?{F6g@uG5TNp~V5mJ_>x z!%88L z1U{CaSK~_T27_hrkhamIBi9E1O6Yw0OuB0brEJNSmzS@>pv3J~P-pGJE1Rf|^^!!h zf}+T*(!&mfFQ7zuDFQ2wqd<5W{jdXR7=9E;a^ZRY7#MgOO)oFG9|(r^LU*LWo_S`b zPbLWJF`Th43L8o_MnNV2drTN~yzqp{FI7cVLJbT6w1<_?QL->DX5Tg%-%bX3ZWd~ z$mhQ*{m=kOK|wJE+HJ73hDxk3zy=dBatLD>;v1w9plJfzf=b}L^`^_f8l<$i2nb&# zo-~oFkC&GmR8gAm(xu(;zwN@(4(}EPeQkzC}tFIZZy$aUvE!mX^ZC01NL#Em(5HPyBs_a4O4q z<`{{XoF%9}m%Sdtq6XWQtCQ19G;aTaV(rlv-9zH)pJ@qgNob&u5reWCO2g505hfPK zFZadr9hqglppzRi<0}^aNlV5o@`K;X)w-vQk=+*79iR zb2fdr0WY#*m73_j72hk>D_7VPl&S83eL0L!+-Zcotqyiz&}nQs*U7JQ>4o4WSu6=+(UfIRch7^twpj81TOsf{}P96rP$Yh;6 zr;spq7!Y>1wuNpy1VF{UY*tw`4bRBJK7m|cFGDWU94IeqARvU|>1Y$!)sP#p2J=Y^ z&mZK1kN!>vz?dLXUI*eCF!MoTdogaACbfb|?S<>aSP2yZI8TsQ@mW7T78bP1i@X~f zLj62(*&a(I1c;c{m>l96C~wt?`Tk4P%2=EN9q||m{p}8%hP??WF{i*)*vF>a+@M1DZ8=*|JY9ettQjm56rmcGp3Tp{qEjhBe(rkn97D|B>x$T=Ne%Ei zi`64NgAkncb)Yqa%c}`lhWXf!3tG@0J`u64VOfKb>bE;?AAk9JEgUNVVWai{dor9O zl)Jp|UBU%(UaXb}MU;#Vw)J(5>uXWa8OrxfK+Ken4+L_o!7c;3T>y~`gi?SBaux`l z0#N1!fbOBtSnh1_CXUGF;8vBK5Z6@`nwY678Yh8XPp9{}jC7+mo$OcP=MIe^W(SG@ z0}IP(5BNf?1@3*AIsPpb&w5?f=1?4=L}TF`Ys>nWq+;|pAWg*VxV8-y0kFU!4M`XY z`7A?Kn_>71a!EJI_}X|;*dfN2D%ZX}?O&VK%R>`CCa~xZbfg%qngLK*a|*$U1LR%TvPgD>Y0ST8rX3OLaLnGz6|x)c$~LPj}<+i`zA?yFkG zoP8(t7{5ZTT|Te3lsY!@BSXs`tH0(lv+#BT*YqTNsB3KcwTYMC z{y64t@nuX?fwiO3$m!_%n#<$AHOV8lCfw;41F5J`f)hYtT2wrfnHC^@<54dM&J8fE zIN#B#QBQjSt<*6MW;aOupqeSXn*ES;XI|%uCum*aL(p9Sdhh^}{`0GJS?HuD0fet< zk<$(wU*<00ETd7`!JQ7-IPPgtLB^N+?;v&y=G=`~@cOr29S0El?v-l1By@MM!ROlQ z>aki2UZhA4uh!jQGXwlTsz*5TbW{$MpCHiX5(dKT^#>?^dFS2q7yhl3pNwQZzs++i z@h*fDeX29yH^C6GU!rQTT^2(?zXYz?mp13F9Q^#)7aWziToB|CVSZ~7!>7zl`D^P{ ze!kD6zmIpr=&HVb`zr49Z+vTBTX`p^W}<#*#q{$9QqtY5TU<(xuE5s$gbvY<}ip|mt$)5W9r z>c`}uS(z^xoyEcd9^%hT^NjZt90^%vy*|6A8}WOC6F@JHi&uoZo>Z#c z?au*oKTNA^yNe8Y$e)eZ-WH}0d*y=lG0%_M&)??QfBQ|tIp9IVay}H_ zA0S*RdWl9&56Yl( zv_8wQfGcdii1+_>_1;E6vk|}56NBD^hiAJFo8io#Z1+amog)fo#ZY$p-EWAM1NU>> znGUWS$JX+7a|1?Z-jk~e*G9buHdg%Z78x;u!2lP&cs4nkAQ z4S2f8uofw-;F!>=GmO~n7aA_;>%yz;F{c?RfTU`@$U zi*}iq2K6`;PzKRmv4WxdpiTb{**nlK2|Dfy0;hL4mEd|JK%Bm4kn!JN2MI^Nkn&WmJ})m8WH^djullmOLniRv(6Os&8qcZ`Q&>J<3n#AWh^-_eLp7aLWJ|xqP-h@9X3?oE`EKidQVRM zz*damtLia0{#8Tq35+@@=RnhrY%)MvZ9Uc{v2g)LF(|TU$?j%)#wjl&TIeCX5%_5C z%!U-28lWR0zpRl=tFh#FS19F%EWKd|v4i;TiwkdWrj0B$|A3Gz>s|a?`B_9BDZZR} zw_M5AE*wO$5kos(L!%2$LyjIOM~;)kk#S$@;TbFjN_Vzqo_K&BcuAd#|Vyq|x@7x5&T_%!f z%b_$WSxa2#F)B}AQ)2d;SZ6|Q@s}vkk$&0tR7?*=5n{AutNg~L<549q-V z1YpsBUH8PX)Byr1SfNXfYyCop%XPepJI)64tS&XIqA6KQLaF(D<^*5RGMjpfJ(X^H+>rGlf?P{(Pk-)$4J2(B) zlXhe91N%p%^J+0&!@yf{%W1BOU#h_QGO7OB(!YNS9zTf@NNu~xOPcH4w`u4VBApZz zzJ=ad{reXVc$z`EEuUJ6+4aj?XJ##~C&yk;_vb0acINayXQYU|QVOPu*KS?CsNqDz zQ}iezntwcTe`!N+X|BDzg(ohDVyaY2|6PoYzyH3e!BN}8uB7B+8p?-XN89{v^wRNo zR&Qtvwuz`_vNS1CKcghu(M7b}L!-1}@3u=M=H;OHz$|mSKrsL`dbrcivKK74nY1d1 z?EO>QG2foL77=ZFgxd*$GMlsejOlOw?iA&3Hjpw0A~X#;?tlGorUlQDxa*TX(wUJJ zWi!3LYmvoI1AE#j3^PkY6Sas%bvgOQBItaW=`zcU@mw`N5_*enB0ArceW4)hxHEsu zp5;)APz@jwjG{C;)Guhk`1vb4haoqb$K+_VvB1#aMJ6PCuQ~0DJbX5IQ9}Bd?X7X2 zYPa3+7wfzKik!gnx|0*WjXy8M3_A?uRr$t?S6Q66os3F-Mfkn;1BaJiBE(gQGvL-5 z^m#1@_=Y3<%arf&Abc~HCUCCOu|rnPoy2fvVn?RC*5IW>$%yr)^o&hbvUBaEDDBIk)nT3sZyox&_DRIaPP zhWuL8GIT_)y^1N`X;ivNm5bK5>3FERM~tv^NpMVy6vi(NM2~)}wmOvp1MXa_$>riy z(Iowz7*V3M;70=5Bu}T;MabWc3pj9xiAW36MPq_p(+sGB(WU_w+T+td9v>a<+&FhG z5bLq{_r2a~T7yp?OOFV6#|T^{KW^FM4R&-RZ6O{&qw$Gs-04Hmadv8z{WaDOkv5^R zcPE;`LVaJNt1j9ktf46o!4}F^{3BIZ>wNJQ?JR9Gey{25&j7c4Z?<65o9G4Nv^kIa@+f4!rA@V1r){>B~J^}m*^12|Z z3A#ClOn}ZbtpPS*PP_q?3be^*p+_^_;O&fyGq-_uJ`_WfP{#xM@DCW&h?Z-8%@y{2 zEHPRwEf=^IMXcBkcfdsZ4)6@C0h`ouEF zEyDvY5~$W%84^f=f)JU~&_zGwQVVE->rmj4?vLM)r6%QSZKGrDnno|d8xax3%TLTJ zMEqGypiPqL>+X2w-|3^Hg|BjPU;1MhXm|XYe@poPZrk!x*cOzxN_33VKF?P_Xk#X6zRyJcwjtbG$oK_X>0 zXk`9zj-9-pcad|4lwt`QFj{=BE-uVsw#4Z17m`$iwViR7Uu$wT?UX*0iQ^FHr1UEN5N(|)|(>)WuL=6u^*mWGE1Zkqhn6%a0^=D+D$o1y90IH;?*Y)lopL9nVIHv#Te0Asx^?hW3t9B* zn)rd!bjFBe9g{|psCwUm%aCU8mAw#bq>3tX7KnKp^}sc!Xr+W%?IGkVmuUMF2aDdn zO&g9c@-o<#&j=Sz*`*+volotwu4E!bw~f9biihD8)qPh}^Sw#{X-dkC-#f_=MaBN< zcI>+{(qR2Rbd*+msN-0CwTy+V3SBrX)iV|adqZHM{^j%6gTv)+aox-=zKH72RdKZ^ z6X9#~z3OyZ+2r*DEONyxdz0d&sWuAb_8Q)f>ONI(LmhwCAY;E0FX1qy?ACs_EkN&Y zmctpMpQv2X?jbEZACvnovO8e>dyXV+beMs`on`3s>I7o`B%yP5qcCDfmT$IVg-pR4 zx4&-Y5(pF7QnW>MSdUfhlV|4Q20*Fws=x8@UON{$C7-nwc~O$HXK}02lzd3P5EEyX zT=s;jBx^)wjGUY7^_yg1mhO_d&mZIyAJLtYKh}rf7gbaRW38BpZqOuV~a_CBfP_7X_ zNzS#xs3QY=ZahicZ{1{iEFMy1~po$l#6he z6rm)#5PJ1-iJ_Q;#bGP7^u=CXC<)V0@UJulDG9-F3*PrEF77uJN8-BC;_2{tDm>-N zC)bK6#%l#bA-KHO)x^jMIMZ+v&^JLsl5Q#3Z(hB6V}lwIv0se)1O1ngh)>qKGwu{+ zx04M7ejn|u`oMzKEAz52l!^dTwgJIjM*P2|TAl4FZC{F5^Gz*ti}; z={Pz(44!n*;67*)4xNqh0PJ$v*E5&q6tvvY2fep$jt%_OVbz2u#*uz0%al2c8sQQv z1<~!eX!*(dcTmDi@DBIqRu5H90aAiH%f5Y!*Rpp~!NG=m&KzzWN!#b9!~$k~ETmZC zQ<9Rb`aZzP-(*x8LChXXRXFeB@O3W$lPpP zm6CNmNP3uBJ^XM~;Pz?n$=mYc2m%C$47(~xif3T^lFva1A);cpev#-yR|p&1SA7&8 zBLblrVo@Th6yx`MuZ25OinJSnI(NY(eom$~e z8+X2s#dt0AhE|TZ5^OLMkNs7X&<>9~q2B=DH#Mg^oLSSuZu3=!4LK`p-_iij8Id_g2 zM8s*pU;+VLv+o)mxVa|?x7Oc+B+T5PBPl*^&OBgw(M0N8$#rBzKXz|?I3Y>90}$EF z9&84i2On_~!!wAj{{>%wYc~AnrVIC7wtW9eqNwgxbw(GA_-*RP)x{|IrOL`JD4r#B zwYk6oNc7Po>eDtVE}^$1>`jL4G!xpt?>ycyCQIzLwXw;~ceHzd8c8+p(;Q?yln=vM zh&I}a?mOr$X}nW=t9J3uXX?Q`7qojfZobT0m!H{!bbvCuA7+(v&RSmqI;yqus%Ck&y(Q6mr@&#E5vxi%Q%jCj zaQVgQ0}H7h!Oi=|H%@}MNGwy0zr54dxTzih=K ziwS|j_I}cR)Nk?49*`IS3bv7i`6v@NWFys9wkO(46*xL`{A~u9fdMD0_sWZli_6Ls z9{owRx(!CZ;piyOxTcClzcK8kwz?vtFI#ed=pX}LDCM0iQ=(&x=oEN;gfKCiT*dZ3kodzHPrSJ4z zQPDE4w}@NCI_9DIfg=;)EGrwJz!n0S30@uf)=h_qC#ZHlL=h6P-_%D>SQNTlUoOr4 zw^Z6>I=jY!Cu=AMsFq^^wEoVFT&b*;GgEl^pFm9m^Vjue33>O+K2?H)N18eVw z@5idD!7VwXLI&sxf(>p9Jx&9S($;>j@9e0B-?Cz$XokJYaU1auKkwf8wFZ+}EIMYbq>IBj!Vr0uYq>@6FJoF4bfz6+Sghp0)4p={R5-Vx%*{SqNb2Bd|gW7NsRnzI}Uq z=Imq!QtQ~*LNOT3@f7sJvy`7ngW+rY!bU}2PIk5xa4s?yy}i7AGYT*&n-HH^wm4Dy zx2G`L8WuTC|IJcted1P`nZ_ql zWvgd{5-Vod=0m;u+;1&3zxOegFQv(hsrm%;Tf@-L;u` zt~2Md`ukuk3Y=?jdw;(MuRAS`QH5Bt{4(I(`HqmPCORRqfLVP?FeSoZ6H=EE5!%A3 zx}P_H@uBezT~l%gvt%s(OqD>115OjHc-*E420Twan}G7=ufU3k?OI6P*0_0fMC?ub zN01n1L#fGU;6$sPha=HhwS@!q19lfRN`?Kb1!*ukc|CKS4?ZPD(4c(JwHLu8@R76f{axa~fOQ6lv;V6L>p1!~f74yl)3pE8NHvTO>{&OT2*Q_5g2Ro(V zVJ_yoj_p4lsvLP)^+kJ8aKC`{)Z9?}ywpV*4T3BK`Pv63zn^Km=9XZLt7+c<(&<}V zwbZt;JNZudQUz9;maNQB_HfYKV5+PuQw8`)LfA~a1bPPPZQqTnay;z?w{~uBZcsUM6Z2wC zH^K~zAlzBMp=_bBFrSP)xI%vgdo+F{k?}h|9Ql$LE}lh%%Ukwus5*DZfJck?HyugJ z(1WL5jchM;wA2y?TVyn{ABZ>c3`os}h9qdxwBTPG-O(8m(}~uvS z!x(NIJdw8TJbaa>23>oFoud3Xd0o7kh~f<;Eh-w`4J-mt?5;@3#()%7q)&I)< z|F4gbT=;p?+t&a=ojF+N{Wx^7Ay=mNimWzY(MvR{O{5|_qimIMbVyuR3lE_*Jz8mk z!fPpdaH;s(zoS4Z0yxgNGqbk?V;Jfkogulo-5Aj>cZdk0A}Cu0y)-!OgX1ytUk!G< zEJsGk`ayBQ%sz-rrLl5Ub{LZnqq?7VKU=@w`-EVM2uX-wx0tB)tY^;9!33!#jk&c^ zdKZb3gXt1D#A$Lh_%!zZ@)(P_PK@8Tq|}!-PZKn4d~QyP_|TiMVfzm_053X@W`wAm4)7A#5VL z?@R?iELr%E9Dyjz3@WC~0tGnVhFrYoT`;2S`2{vQP)U%y*BA=!GDoAuY(FPJ6At)C zd*Vj_8Iz6CG949IOQl?V5T7>wU**|ZZCwe8!c-v%7ax{8nnBQdpvbt($XwyqSoN+QM|?&6EhR-?2EMg<--eRgKWfL z#lw7ljo{dc`7V4`OG`_R1;CA3hSkK4ZGu0Pzn|d8UdLkeAHQs}h2bYtxafyQp^&+j zZntRSt%i6k7Md18T4Y`MnZ&dq-+&`P59K&fo9_tpx&1N7N||`%J8G@?a($;r0pX?P z#z>_?4z$z%h!Zz<5f-Bx;1;*&Q4a@msDU!tw~_LhO!*Aa7t5&24$xRnzi-uC**wRs z>cV5QluG!Toy31JduOwhFO;})Etk@-z3j6i{v5SAXv=Zyvpvb@_467bQ*YhYm!_e_ z{z#w_@#V`GmFz4Gzp$`T_VCkSE zC7m4=GAP4|3fw=>g~vy{_Pvias7rl+_?dH>Iat!IwsL%U?f>r}Ugx41YVzf6j0ep?gjxRodfUGpjJDHMFQZ}nY ziGRS2I;#LyDGA-Hf`anh*@Vhj7+{M*PWWoEb>&z9!znv71lG4bdLeg-7i(u{Cx7rm zh4_y1wN5j0^U4Bt#H=$PcSASK$}PE=#qI6yjViv8Noe15^x@f#X)o~};cFNIl2=RC zcB?Acj!;=22w~jNYJB^^G(apPBbev;)=j$UEnpvG(0__9vVU>}jU~t<5u-`yFPl|^ zP;$Z$R^_0EtH|aKMP#GD08rT`0x0i0_XYJ)@5^1HHtyt=Z(f`urpsHZnHySdc%T8NNSdB5lXf?v>wS%bgAhGf+H`rvKy;0(7X9C8*zm^DWNnn>wKJmmP9 z-f;y-gl+*B65AXY*)3lVa-bH5m6yG?D`$vkS){k zaelH^AeNW?(#M${#@S~B#$KUkRQ9yGk_dg2`;`kJY$-kC4OYvvWxg(Lk2Y_9jRG^a zYc^^5R>z}~u2`g4WQs2MVI>2b1qK}Unss^rZ3}Ea)vVNrlffhxjrMf7`+sO}7F@rB(zEpljq?;yQ zRA280bTQa~>vJyt6C$^K!=iDiVLlZCKxjUsXK=j^jl1;Q9A_>^4Hk2M9B(ac2Grs5 zgudPhyRfMNk6h&D;rH@D@Ae34oNfe;7P>>*a^(dZ+I&Da#wh?Om?Y&+wue&5$phLb zm4~XMqM|?>Q(jWy0>mAl)c+eTp8=#Dy4D|n&5d(-yw}9c^Z{I~P<#sk3vY9@)Y?F_ zr=f8k0d?umA%=-s(I*f+)1Q6gAuvuLJ_@Qg!MFujddTaAZdd)xi54=0+Bp2%>qA>P z`PQwE+CufV-7i-mXDSKU34lx!BFi`VPNs>eRn~i1GEqb@qK(j)loTGCNWt=lD%Qbv z4l2}rTXKCv;-&h$AP&lcvkD9+V05TmrB(1)SAJ5Ak^L@pO`TmNEmDRT(W1WqOX{;i zN5=fp%U$lwi(GNFtyx?TPCD)#hpipqn2ejtE`EM~lCS@EzyG#Kx{>IzN{Nc^L9DoP8G#1d7bA zaKN(mGa?GJMkj7UhIiz1A5=*gG`oBx)OCj30yeVcw=o+$VBueMF_W~nenC2PFcO?^ zfRx+_PhPlb-&%IcYUvIs9Wv>Y_ho~-lK$=Mtvedeo8H@iGCVN;TW1bnJ1`yOL z^b4uWHw%V*AcFxqk|4;*!zjrR_38|9VSqUeZv^J&Hbto~{=1*3fLUs3`G5SIQCU}I zSmL`FZ0Hg4bGr_Y24bu~$+N^~a^VMGgkv&f@OZ|3eV$0LEUrstZe@rHm;oDAp2)4k zCf4{ai&3=#rswt(wZb?3cbU5eyc>Z_2Uc9r=lDO8t^=Iv{r?}M?2%1&WDBWW6cOnp zD?-RDQ5j`sWGh5CrG$*^5-Q1#kQ7R#LP(+{3fcT$-`~IP^W5il!#Usc8SnS|wI&5F^OaU8klv`npBSGOXyeH zPn+?Tx4q;4q7b5TGgZ6Km-*0zE}8tOYoar?t|r?KsJ$P)8EZ-wXWA4PT{bDKS?-CZ z4~)qw`Ob1Da25fiJJbkzHV`xw@56FG|*n<2N zy9E(Rt(=HcSRZFwPuP+lWxT)Zj{hex&=*0s2S=(+^|dFgt;}A+!>aL!1P3uXxY%{G zg5)(fv;P{Ef#c8glh#D~Ra=5k`+q~gb_j7x#8!GS&F-yA4o!X2D=)*SXz0ZtGT110 zYK=p?)uKe$<~qM*`ed|CKVcDBh?d8W@z6fo*}ZS$?cp7PSqo3QLp<7ES(i;#J@VIt z7{S-qx5GuH|BZ+Bjhx$rJOeQbYU3XJW~&O7ooPG3vLqHZvQ@G!tuJ9ZL*$ZRO3>=` z2cN&F-PJ>~8HlC`{{1^hR!(kK&vk8izHx2PnNJMquDMLE;1Bzj9@{tH%(UZG?dn@( zm5eNOX4yh)LZ}H_xh=s}T0MC9a3}Gf2#8=51I_$HncWJ$fLTa=4sM3z3afi_`KcGwHYx9TSeBR_A?!t~G`x3*N{eNVw){`An5 zu+GJ~E%f6R{-%BKA3Ya-y8TT)+vus8M-O~h-ASLg#X{z;86(#-rCdrSG;CE>$LMn? zPU%#n7sXY-tb&480HrE){+yUFkl=V>_Dd#c_E0Q4wG?y0Ysb*W+}y8(hajxB;JUa6 zl-BEVmWq(kfZ04$>py*=dxK5DwpUfz0zv7Y4=|fRL4aMY^8&!=~v4`YeA8l(lhCUL64w zKQ}kmMB3_xg*2DiI0owkxo}i%XzjQEgX*twXCBo513wQ&Yx7!qUYo{xAv_f^lbMU>q~@4FX5k448pE zs(q!)AzfXX8(LmngevHBND$I(A}pr>b8p3)a86n$Vp9mxBF7clP_KW#n7o9sjs|M| ziRe`|s7ml&LG9dtpux?<Ov+z;F#-Jp2xV!hp6$}ubz}uDq`#M)UQ%Sn?_64k zeykDqnnmd`yZVWAjB3gn8bUGXxw*rAS6?E8lkZgV8L>9(bOJ{w3H!y;( zdL(G`*!?}GKDF3tJ|9X-ONqQJ)EVb&hCa=GjwvXJ8EMh~8M8f#5%4p9%(kf!Fd8TL z#q8DYbi+lt?PIm~=*!MdWKH?Q0vF;k_2_}t3#XhN#IBR^_cy*bitPLHZsOa8&8``< zD3L6V9cutbak8(`?8y_qwbC86Mk52tL_w-Fq;Bf8A z!u#|3QPcCK(w_f)SY3TsYFTDwv|pLJVKPBz=f#QP{kKo_m!EI_TOZ`tSovF0l6oX4 zb-UqZn-86nCp4{|Y>cIy;A+_8_v*hZHzjG3wp{n{)G+tY&aHb?nJdp9ziW@GNp8uq z<&Cub&&QK2=N|}ao^JZ`d2sT?@gRqdFT8zae+Hahzw1cQ*_Za8&rH*^nl-R#sENoL zh{-4W9$a!8JTA6oSW}O0=h4pkUTAf`Wh1lu``KQ1_tUoP&nq)Esvg+QYHm}y_|9M? zsPm3hm1|#@Q2&>~#wS&kb%s}lo2_?_R?U~%YcBq~Z3Bh@0NY7!!LrFUyE~?0w{2EBiJ~}zAyOD!OPBs45_|8 zAg=86{Bm1c8;DN_#7*adeayOkC1;3dZ@o-QlMvw5#T2ar4w|^To}QkYo14ll1Z3I6 zlw3if)s|>PAl1s1w088ia#W5u2DGk((9*HF{6u63hP-8L5Xb*Z5ABiJte&8oyQWpVzSVk=_QJmZ3im z+yA90or6F`}`BRmhjm=gfgcebE=KIW>jsl zko{|%T-i++E+{s`FrCEAr!)+_7zdZZi-+fGac6@(p)s_?S~L4%r*88tipn+Ea(B;) zXZ>>J%rIe%a*E*!xf7gI6oz|U2!fegXS>id{B&>%!7Y%S1PDLrCF;`koTj#A=Q!lZh) zi=fU6EThtr66TgBLslZQ7$)Oe0w(Q40zYvYe>v1pwctl!)@04i zyVP*T6i=3xkufE=I#sm9vO&JHMBH?s^T3v9T$3lBVQB47)o@VKW?~m>&!s&5mk^e<*hdj{zl~`1gH% zL~VQqgMZ)vMC(PkX4Z4+AWh(-CA~Mm2z%f67NF?=Lb~M*d25vm-wj)oSb<;v$WJ?F zVF9xnh6D6(1_o@89s5UEt)k3}aw8X8X~LgWp);5AGhv(O^qjT9^#JRk; zRg7hm_+aZ89EiUI^a=%p&B3bzzKGl-ss#+XV*7h~hF8|n_=8;Ul8P^u1MeZx_p$5$wIo**rFhlB7@1;#XF(spP#N87H} zLZF372#65ga}$s=K)wO(d;`?0*szXPpL_>J=~Fts0c;^8^|+iHN=km>F{KxXO*bns z_xVBxio_~{SqDdFBGCcz#H?`;%1~j|lm#IS))4OtMKAc|_A0lYt1+A(1-#M5SBkD5 z*#I6MfK36%YJiHRtE-E`4@WhT(S{ul^K(Bu5sc2N4`fr?M*k!xvJw&9rsR_kKc(4+ z27WAeBzmOj6{1Z*t;Mz7PWja!%63E>grb;%6ekZQ>>dv=&wt9_d3`pcaQug+dtc5F+Tx)pq| zO1oMtY*U>3DMQoOX%aW&_1a(m85=deSI$`sa}T3i|MLeyTiWMqXYTyz&zCBU8|?8Z z5iY{$v4m(jtmzt82B&*If|E_N;*MqW?#q|oHNT0rXh-k})1IN=o#Ur2oat;~+hB7} z*m-}+>afZ!2|EifQrI(%N98v~oD-&?Lk8E3P_Q@PdjZ9QdX%_0a1KID_H;SDHF30V z?(66K({)odiZvZNm!+}-npIx|U4lz}(c^6^O*Cx7?*6U4rO>gz>>iwL{rvfJIO;i*T;q+5Us=66sB&)uCMIb^Cftew{i8PB`w`#BBT4Gaoc-?Z`Gy@#szLC zebSAY8hF^vIrHUrePm3cn%6|psW$buKZvg*`uf%AcoVH(h+}`BX!jTly+qRY&2d|I zi|yAGcCGn-Wq9d2m_c$Z*gnR9RVf5E#DPhm801I{9yHyeL(at=$ubLR*M-H zA@kn>_vdJF7!+(bVz6?~<&4O=vNL2>Uu~x-kpA{xRqPRATsrc{1K?hUcCkG|JfEwV zg)l46xUiX#q=;NjQF=&`*+_{Z4*Teg%&#oQ7QOPNbAP<0gF%d3oiV#jzp;~7o)q@D zd+(l)dwFQ79AnHd>{-8PJdC-M#_HrrXP z^aO_4S*%VJYO|v)frjzF5S`0zKPLEdxWR>Jh(8<(V#m%C(p-j_8i||_4N3IDyzd($ zNH=phn=_mGsy8LnmTeuU`m1VkO~%|Zha!I6qF1%un?$17a+6l~cM11lA7jIn2G4#! z^~|axnHLfh9z|@0D|7hqcbA`ils4Pv9h-UFgwIfdmW}0%a`RWFBfaOJ+G+~7JAEjx zF*HDO(96Jm(-T#Q0bOlUJwo9vH)IXJ_EIX`CBv(WMz6NiWu!h%SvtYZJ)K8ihtFAu zt3`la{7Qja_>O4y160llD)bRyW};E6@9oztG=(?T*+MU$)qFQV9cD6y$>vCz*VVTj z9V`Q)^wl2PY1?TW1xN;)%*c=K##N@qYaLkhiM;;YP+xS$*62!C;BXM)E=9Dmz?nQI zCHZ23U-E_{U(K;E4>qD^r4rHE4+gn!y`8S0aihaUzLSGv_`pe}yHA2Ga!Fy*WO^z| z>3n|St;+6PB*BkQ9vt|VPl-BD3Nu=fyPi^0#;|3grhp=-dfH)oDl4^!cF5d8j$Hnl zYn2n~C%MO34ki|Po;GmZ8O{~gbnsG`iQZ+}YmD?KwPhMiqI}j7eqBtW-_&L&7Iwj2 z#=%zk`{8R*RK3)C5{}eGxdJuyaqi*fQQlM(uR+UqmgXi$*zsHW2sJk&eGd7MBn{a- z`!cCSdiparoB!czMTS{P>6a}mGeH{m2Kn?BQMo60Vl-|Q9B!u8^RkSp&?aY7Oty2= z7juaPaLn*AoYXFAerQ}QVXn+0eT~8>nqs!fz-4lTjZ6Avn0IiFG))0Rb~tTwHH94R z!bM@$X6U+XM&3ed4)Yeg9@TX?tfh&Git_bLouIZfdmL}HiJfc#y=9btmLNIYyGM0@ z@q@6RF;3}H9Rr=;WePkmuCes71&hh_apmYxW#wwi2GdEm^y=~PGSWK6xltF9WEqZ9 zM*pdiDBE-=HxBMi+p@1?*zt<$MOrg5*ZC|}Hzdv!l|_{CsOU-LfRby6d~HGnX3xLr zhPuL_TkJ_|)Y_5O5Dt`;d4K`JYwNY&cyb37Ehm>%Bas_QY1i>Xr6Uoy!PDI)41;%DPD2&LN@tt0WUqzVs#u6~zkUzvfB>BY)YG1Rh^C&fUsB z(o6Mf&)0z~Z#LhfYavm8=!^M#{f<+CLsTy*@dIs;gM&+)a*R22!+r2Ipt^TWw#k>q z_n*?%$S7eM$sg9aa};VB`5wuPxB)YHHjR;gMeF=+-<2paMhk92{!zV5zXHS02#{rD zoBUiGwbKd?d@Isl-1dy2Pa=#&P1&SFE>;^i-$qS8BH$|6dYG1!L#gOmd0Q!Od&u$U z_XJ^Ty_I6O7I_M)#Tw3GXH4FY3+))tgq!r zqE|Pk9hPp345v;woU7C@e&<%TOM^*|ssc|ElbGgE`@!ZZ>lj(epM$ZI@>{iz)-#J| z2y?~j^{Sdi>G@FA6yJ$TNin4rZ5Ck={$9`=8c1T-&z@n`-N9{V`E4R+=j9xd{L6x0 zue`Dhrq!7OCg(xZp-YM9H0t5JoO+=9o`ziRbuk`cF$|D8i{`=bTmY z@YPeQ1JViVBP)y4S1ny{HSs?t^W`;(`Chs@cHLm4ZIyd@+s&M2$xDmLS$@KP>h#9u zMLw|`@h6O5JknYcjb@*ak5yf7P-nP#YU$cW^aZg7{&co`PR+lL+`RL=qmr#X@?hMa zLq*b;$5~=|jXqZEG`}8>RH#(`C)Aa^=o*mIvZMK2P1>nou7LWPhZALf$IkhTB$-#W zJz$lQ7P)N|vB1#wVa6xZc4NVuCP}=`Sck53g*&{g@Q1|2k1Z{cEFy{nOYMBF0kcsW zVuKfN#xxbqo5!x~`}6Gi%=4VrIzd!+Y*NP>M$bHo>3LtnnAhQ0omaTF?J+5`d}I~2 z3MPCSkDOYaOnV<45P#DfTFyvM!r4C|IsY!>r?Y5=#7ymsc@&)opFX&d&TKY8VocQ0 z%gG4?v5xHTz8$m7JaJ}JcI-+r3BQ$r+BC6$rLA+tv-(fnixpe-TyE=KND;B z;ZIRZXtXP>;{>zoG0lHTrYE9f!y+`Qb^EKj9g280?1!J~35eh5cig=xKg}y(BsfrK zPSttjWUI{h<2AePgqM?_M{5h~=wsOlTeTrqr@3=-d&ND0BR%PLME~ZA4fg zP(OXKdD8(a&A1ru|AP6b4zB5*O=BS~ZXFBR+ug!7#?PGSoGBN_@}nk^xiLxkOpMG` zFaD^sY4e07w*4x%4x~tSIXccOHI&OU^@dqREh#7RF0lJewQ8_GO{u4rP0i-w`ob)o zjGXRJy=wERuk@KZetC~520-&vP^%~pTBuYJU3ED zSN)ntXzd2SwKPRgI0ohFI%eE+?1MS%8O92FDs)C8oF`gZ={Kk4*tAOMH+j!w9@6W+ zV8>hf_l*byx9Fqba5ite@=`(P;pL&rZLHfCv&PW{_XL69??C6OrcSjvqXFr4c7 z8GYeI(Y}G+Z9Tok+S~ZbdRkncJ{f&Ju3FdMLbvmlAtHN5>JqzB-O__o#aCsplUciyhFW*OR-lK(+7M2=l6G_AmM` zd#aUXO*_g$ttV6+L)q#ZIe*jTMfE(cX0m(OP*dahLM0)5_>o8h|4Z3Y4>Oq}mz$kq zHM8mf10A1bnK62vUR8XT&S;Em*LsEl%mw{j*<-^sKfLE)9Av+@Ktr6U90jv7x_*{d?u7*)T*9>J|$xa<=8bsNdCiIvp+ALCF$t5Y>&my5~^Qe+vQ zNCW4xkJNvixcGL)^AtWDGPJbmHMy6{&XLp}^x1gfpO>1=*ZJS2v+P;nO34QFGBPsH z#Kq^@D})Yz4Bu6^MOR;F_x1@+hiaPCsEOG0f-9xI=0{r}Q!9#UcDHC#jn{#&e>6Kl zzFK60d?{zGm3(x7J4-jXx%(_F$+9wl?(4wPA8|bRDPY<6?)@^nWlqw*HC#@ov>cgp zhMzY4TtDC297@)=b++m58MoHGqTzJYAA5Q?_{8HDpDA7C58V>uq@)^ay5nrFH~E>- zd2yr54_{l3X;UZ%sJ3z4r7rd zzgz7`DZRFVxi)9alRos%a0&4pZlbC?D%5_Z)ydL6Wd3BD9f;EKi^7x+^aMhy3Kzg_ z_PNHJBenN5*3}7~ysMlQ&z4f)hAy5D3NBDWdah`Tt)Vl8@8J)i%s0(iVp&+E)dwds zoF=t(UH}r=%qBcAFp%K*`elZx{je|*t zE4(_aK+r)PAu(~p#N(r&u+$s8*cah_#$mW?g{5A4%;3~LLq`#UtPkt?XUIU@j>5$KL}e^20O~z>VXFkx{+# zUaU-4k}!#SjbN#9*9(7qU zd`To1U+DUe?)E1ZVO5j3Fb?|Qq_D3EX6)gXhLX;rAtM^$mhbqK#C?slmk(^Z@$CAH zG`$hGf&H?uRJLhE;}tGZYWDqyGVpIYHFX|7Q%MG;Ya%1-XWQE0Vy;5k#qYrONP#?9?JA* zb*W}vk2i1mXtTWH1tl6jTvp-hDC|F%IjS@xKO$TyG*y*DSLXafz~Zfc+>J8+4DJh` zZn~LBS`3#q(QVRzu`LM)7P>Y5H7h zBkuK62fp6d+5e)cHK;@3yN{9d;VTB11#A`Yy^%r#P5mJ=c3JeMlTh%$4pIjRbSInJx_L~Wh0j? zAOPAOd_ZIiuWkA<8h%@Sc942oN>SLBL;Lvzu7}HM_U-oh5ft#*TPi?dCa5?ipk?&E zvYMRB&c##1>H#_XX#<-7JiJjh;<}&Ke6yg$mu~^F7Z7MQy0Up2d%#P7=NSE{?&6ei zrnh^1+ltMaTgHVR2qfN#FlnCDRJ>XnUDs9g>=t9N;O@&`^lt3?(@^sBr>1-V?#&^5 z&bXte>t^w$@MN#+L{3R#hCY3-AUL0csIK$qVS+`NcG0C0F+k zq~$vof6D04mu%0%tdI9ZK#n6HG3ms7c%i{(fNgBQJf-Z;~M|Il=HrEqQXfJ?hKeTLl4l|*@+tJ_Xj?f zYi6u~6`+S3%K#jx1#A`Gbz0cxID&P)F2gz(#DJp^!AW!V$RUwZ<`kh@o&k8y%@`e^ znJ6`T;m!(18L*22Gy|h$fHvE31H)1Yqz|j9@u@dtr24{yPI1;8Q{ zBPT0chFmFNRaI5HJ1Ys-8vs6V>VPROyAH>d=aBqItcDY_)A6oM_*!w=qTB)OTvSv< z3L`u@ztpe%KS$}-cwoRAxP}ek9=H#PD%k)`I=pVeqcb2?6LUPU6>8@y4_{lE?;l$C zYYL-+OoPbeDl*OUv9o`AUeft2jJpuwL2wL!q2kK3(A}fZc^u)vi0unOQGtu>4$iG= z{ikpx^Pl?6P5Z1aa2Cq|F4kBNHlFpnPWNOZ$@39RLP24a zJnxRSZzCWre1csn^HmIC69oS|53d#qCc$Y9OCN3!27Z%$Fd_DaonT3EaUcZU-@EVN z_N)PE3oGu!hhs8hzI}FkurlCkywaYA$uuVC7?r+IV(zbko+|6&&tkwg-4I^DLH2(D z95`R!KDpkh#{%qp`I1nP12DJ`6PZaB{RBQ`@2>~)&Bc=gU^{~`CES)l8fB+Nw(05J zslpgg67t`xq4^Z7A(w z`clHtMJ?%EaUjRUgp3vW@+JAKVhA1~5=TMU9lCJctlH@LL}A$^X2_W8+tm6gkZdsr zg&8oeKj=$ZoxEXWOF`xI)^Ph#Q`0v+J?#3gXB0E`h13+d!JD>8?>Dkt8Axnet6n%E z0PutWJ0Sc#52q<&I6YYINHe~Qi;&nbSc99mKElF>Nz4V99V!{BFc2iXK@9+3<(e5B zxUQlu3j{~!WLg{bIJ7u_*H@;;GZ4`1v(Zpbz>MR9M_ldf2H_ga*|mfZ2Mcsz(tcwZ z^@oq(IJ}Gj!J_PXF~+3!{eU<@4*``Au2w<#6nnUvb^oTaJK_9+!)wUupLV$Y!4ndn zYYLX7Q^g{{ioI5ejdmv`&nk8_C;KpA4Ko4A)QLLBcL`sy|Iu!3LWN zXA*v@(rgvjDMUemZv_kLe|VmO>r3N1Y^v@(emsw}ObAk>--ERTK?UwnIEJimJOQ4-&jMNk?%u5p-rs^I7`UeIT%`$z$yyDBY=x28xH?Zl_z1xjmdf! z4#Lp&**kRml>nWf{sV6r>OP!5L`ohol?;`WFR{aZtgNFlJyvFW>-8zlD^c_kUjht* z%W$eFDBx^yhasJU!ee>DB9xe=6V6n2c6;G-b#{0Ez`$ASV|XM4%Hg8&ALRK~@_rqX zY4>nI0DQukLpUqKEpjGCaM$?*78dVuYCOi1Kr#6Q)JU9j4by}*yTMDGmGMyh?(zHe z5ss7R$H=1ZX6x{lh*}!Hi237z*cF7Cm$#0N$Js-N7)W!Iea3zBIHlm<>Ix8xTnwB~ zf~D>rA#lQv#$mPHD5Dy2zJz}`R9V261|YyfX-`NV@ywOmz}kwzlllGWp_Kf-=Y{v+ z`wX{EY?MI4ep47GdB;8u*FSnR2WCtlU_s&tfC_-{!1YDKYkL%kKxTc0D?f)=NErb4h5eFRPb_>FBtnglpQ(5yr>GL#m;$lq`T;sX zTJ;?{g0+wg!3o12dLej6x1<`voxETPrJE+Zi+62 z6sEi_{~c@(2#-t0md%e;s$+4h$>c*1M?h?FyM}rjrcP%$#sj}#VS`)55#RcENt2`X zjbWZ($i6#6kdx`_5k)b&t-Moq>Y4hM{y1J#?r$exA`irzw=KA;5Di4&_wF< zz3|lbbsDACVI8*>QUb$KgFo>MbRYMOb5uewr>CGN5yC;>EW_|OxQhyIM+V{;v zd3ZoPXY%67lVhm<6XrKntGcPFC>g1Go;1(7kdiw0y=Yrq= zKj^{xxBwWDuu!?WR}0c0%ClBE z-@)>r1ErqRwv`{P9mu4;hPvw%5AaeShdj93$f^P>P*( zcNb7`xolQ~*VxdIrA*-Hxc(eR3=0j(o(XSpN#^n-7r3?eA6MvYUt%7f