diff --git a/webview-ui/src/components/settings/CheckpointSettings.tsx b/webview-ui/src/components/settings/CheckpointSettings.tsx index 7ea12ef873..e6c8558f16 100644 --- a/webview-ui/src/components/settings/CheckpointSettings.tsx +++ b/webview-ui/src/components/settings/CheckpointSettings.tsx @@ -14,19 +14,25 @@ import { MAX_CHECKPOINT_TIMEOUT_SECONDS, MIN_CHECKPOINT_TIMEOUT_SECONDS, DEFAULT_PER_WRITE_CHECKPOINTS, + DEFAULT_CHANGE_CARD_DETAIL, + type ChangeCardDetail, } from "@roo-code/types" type CheckpointSettingsProps = HTMLAttributes & { enableCheckpoints?: boolean checkpointTimeout?: number perWriteCheckpoints?: boolean - setCachedStateField: SetCachedStateField<"enableCheckpoints" | "checkpointTimeout" | "perWriteCheckpoints"> + changeCardDetail?: ChangeCardDetail + setCachedStateField: SetCachedStateField< + "enableCheckpoints" | "checkpointTimeout" | "perWriteCheckpoints" | "changeCardDetail" + > } export const CheckpointSettings = ({ enableCheckpoints, checkpointTimeout, perWriteCheckpoints, + changeCardDetail, setCachedStateField, ...props }: CheckpointSettingsProps) => { @@ -52,6 +58,23 @@ export const CheckpointSettings = ({ + + { + setCachedStateField("changeCardDetail", e.target.checked ? "full" : "summary") + }} + data-testid="change-card-detail-checkbox"> + {t("settings:checkpoints.changeCardDetail.label")} + +
+ {t("settings:checkpoints.changeCardDetail.description")} +
+
+ (({ onDone, t enableCheckpoints, checkpointTimeout, perWriteCheckpoints, + changeCardDetail, experiments, maxOpenTabsContext, maxWorkspaceFiles, @@ -413,6 +415,7 @@ const SettingsView = forwardRef(({ onDone, t enableCheckpoints: enableCheckpoints ?? false, checkpointTimeout: checkpointTimeout ?? DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, perWriteCheckpoints: perWriteCheckpoints ?? DEFAULT_PER_WRITE_CHECKPOINTS, + changeCardDetail: changeCardDetail ?? DEFAULT_CHANGE_CARD_DETAIL, writeDelayMs, diffFuzzyThreshold, terminalShellIntegrationTimeout: terminalShellIntegrationTimeout ?? 30_000, @@ -851,6 +854,7 @@ const SettingsView = forwardRef(({ onDone, t enableCheckpoints={enableCheckpoints} checkpointTimeout={checkpointTimeout} perWriteCheckpoints={perWriteCheckpoints} + changeCardDetail={changeCardDetail} setCachedStateField={setCachedStateField} /> )} diff --git a/webview-ui/src/components/settings/__tests__/CheckpointSettings.spec.tsx b/webview-ui/src/components/settings/__tests__/CheckpointSettings.spec.tsx index b08c15ace7..917bedc866 100644 --- a/webview-ui/src/components/settings/__tests__/CheckpointSettings.spec.tsx +++ b/webview-ui/src/components/settings/__tests__/CheckpointSettings.spec.tsx @@ -1,5 +1,6 @@ // npx vitest src/components/settings/__tests__/CheckpointSettings.spec.tsx +import type { CSSProperties, ReactNode } from "react" import { render, screen, fireEvent } from "@/utils/test-utils" import { CheckpointSettings } from "../CheckpointSettings" @@ -13,6 +14,12 @@ vi.mock("@/i18n/TranslationContext", () => ({ if (key === "settings:checkpoints.perWrite.description") { return "Record a checkpoint snapshot after every successful file write by the agent" } + if (key === "settings:checkpoints.changeCardDetail.label") { + return "Show full diff in change cards" + } + if (key === "settings:checkpoints.changeCardDetail.description") { + return "Include the full unified diff inline for every file in per-step change cards" + } return key }, }), @@ -23,7 +30,17 @@ vi.mock("@/components/ui", async (importOriginal) => { const actual = await importOriginal() return { ...actual, - Slider: ({ defaultValue, onValueChange, "data-testid": dataTestId }: any) => ( + // Narrow typed double: only the props CheckpointSettings consumes, so + // drift in the Slider contract is a compile error here, not `any`. + Slider: ({ + defaultValue, + onValueChange, + "data-testid": dataTestId, + }: { + defaultValue?: number[] + onValueChange?: (value: number[]) => void + "data-testid"?: string + }) => ( ({ })) // Mock VSCode components to behave like standard HTML elements -vi.mock("@vscode/webview-ui-toolkit/react", () => ({ - VSCodeCheckbox: ({ checked, onChange, children, ...props }: any) => ( - - ), - VSCodeLink: ({ children, ...props }: any) => {children}, -})) +vi.mock("@vscode/webview-ui-toolkit/react", () => { + // Narrow event double: the real toolkit dispatches a native Event whose + // currentTarget is the web component with a boolean `checked`; the mock + // forwards the input's checked state on both target and currentTarget so + // handlers can be typed against either surface. + type CheckboxChangeEvent = { + target: { checked: boolean } + currentTarget: { checked: boolean } + } + return { + VSCodeCheckbox: ({ + checked, + onChange, + children, + "data-testid": dataTestId, + }: { + checked?: boolean + onChange?: (e: CheckboxChangeEvent) => void + children?: ReactNode + "data-testid"?: string + }) => ( + + ), + VSCodeLink: ({ children, href, style }: { children?: ReactNode; href?: string; style?: CSSProperties }) => ( + + {children} + + ), + } +}) describe("CheckpointSettings", () => { const setCachedStateField = vi.fn() @@ -122,4 +166,83 @@ describe("CheckpointSettings", () => { expect(setCachedStateField).toHaveBeenCalledWith("perWriteCheckpoints", false) }) + + it("renders the change card detail checkbox unchecked by default when the value is unset", () => { + render() + + const checkbox = screen.getByRole("checkbox", { name: "Show full diff in change cards" }) + expect(checkbox).not.toBeChecked() + }) + + it("renders the change card detail checkbox checked when the saved value is full", () => { + render( + , + ) + + const checkbox = screen.getByRole("checkbox", { name: "Show full diff in change cards" }) + expect(checkbox).toBeChecked() + }) + + it("renders the change card detail checkbox unchecked when the saved value is summary", () => { + render( + , + ) + + const checkbox = screen.getByRole("checkbox", { name: "Show full diff in change cards" }) + expect(checkbox).not.toBeChecked() + }) + + it("caches the changeCardDetail full value when the user checks the box", () => { + render( + , + ) + + const checkbox = screen.getByRole("checkbox", { name: "Show full diff in change cards" }) + fireEvent.click(checkbox) + + expect(setCachedStateField).toHaveBeenCalledWith("changeCardDetail", "full") + }) + + it("caches the changeCardDetail summary value when the user unchecks the box", () => { + render( + , + ) + + const checkbox = screen.getByRole("checkbox", { name: "Show full diff in change cards" }) + fireEvent.click(checkbox) + + expect(setCachedStateField).toHaveBeenCalledWith("changeCardDetail", "summary") + }) + + it("indexes the change card detail setting with its translated label for search", () => { + render() + + const setting = document.querySelector('[data-setting-id="checkpoints-changeCardDetail"]') + expect(setting).not.toBeNull() + expect(setting?.getAttribute("data-setting-label")).toBe("Show full diff in change cards") + }) + + it("shows the change card detail description text", () => { + render() + + expect( + screen.getByText("Include the full unified diff inline for every file in per-step change cards"), + ).toBeInTheDocument() + }) }) diff --git a/webview-ui/src/components/settings/__tests__/SettingsView.spec.tsx b/webview-ui/src/components/settings/__tests__/SettingsView.spec.tsx index a3aa131902..8897b0fffa 100644 --- a/webview-ui/src/components/settings/__tests__/SettingsView.spec.tsx +++ b/webview-ui/src/components/settings/__tests__/SettingsView.spec.tsx @@ -460,6 +460,75 @@ describe("SettingsView - Sound Settings", () => { ) }) + it("saves the changeCardDetail full selection on save", async () => { + const { activateTab, getSettingsContent } = renderSettingsView({ + settingsImportedAt: new Date().toISOString(), + }) + + activateTab("checkpoints") + const content = getSettingsContent() + const checkbox = await within(content).findByTestId("change-card-detail-checkbox") + expect(checkbox).not.toBeChecked() + + fireEvent.click(checkbox) + fireEvent.click(screen.getByTestId("save-button")) + + await waitFor(() => + expect(vscode.postMessage).toHaveBeenCalledWith( + expect.objectContaining({ + type: "updateSettings", + updatedSettings: expect.objectContaining({ changeCardDetail: "full" }), + }), + ), + ) + }) + + it("saves the changeCardDetail summary default when the value is unset", async () => { + const { activateTab, getSettingsContent } = renderSettingsView({ + settingsImportedAt: new Date().toISOString(), + }) + + activateTab("checkpoints") + const content = getSettingsContent() + const checkbox = await within(content).findByTestId("change-card-detail-checkbox") + expect(checkbox).not.toBeChecked() + + fireEvent.click(screen.getByTestId("save-button")) + + await waitFor(() => + expect(vscode.postMessage).toHaveBeenCalledWith( + expect.objectContaining({ + type: "updateSettings", + updatedSettings: expect.objectContaining({ changeCardDetail: "summary" }), + }), + ), + ) + }) + + it("reflects the saved changeCardDetail full value in the checkbox and saves summary when unchecked", async () => { + const { activateTab, getSettingsContent } = renderSettingsView({ + changeCardDetail: "full", + settingsImportedAt: new Date().toISOString(), + }) + + activateTab("checkpoints") + const content = getSettingsContent() + const checkbox = await within(content).findByTestId("change-card-detail-checkbox") + await waitFor(() => expect(checkbox).toBeChecked()) + + fireEvent.click(checkbox) + fireEvent.click(screen.getByTestId("save-button")) + + await waitFor(() => + expect(vscode.postMessage).toHaveBeenCalledWith( + expect.objectContaining({ + type: "updateSettings", + updatedSettings: expect.objectContaining({ changeCardDetail: "summary" }), + }), + ), + ) + }) + it("shows tts slider when sound is enabled", () => { // Render once and get the activateTab helper const { activateTab, getSettingsContent } = renderSettingsView() diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index cefb599adb..5ab0916bc9 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -213,6 +213,7 @@ export const createInitialExtensionState = (): ExtensionState => ({ ttsSpeed: 1.0, enableCheckpoints: true, perWriteCheckpoints: true, + changeCardDetail: "summary", checkpointTimeout: DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, // Default to 15 seconds language: "en", // Default language code writeDelayMs: 1000, diff --git a/webview-ui/src/context/__tests__/ExtensionStateContext.spec.tsx b/webview-ui/src/context/__tests__/ExtensionStateContext.spec.tsx index 2dd0e0a258..ed07cf35a9 100644 --- a/webview-ui/src/context/__tests__/ExtensionStateContext.spec.tsx +++ b/webview-ui/src/context/__tests__/ExtensionStateContext.spec.tsx @@ -341,6 +341,17 @@ describe("ExtensionStateContext", () => { } }) + it("initializes the change-card defaults before hydration", () => { + // The initializer itself (not a merge fixture) must carry the change-card + // defaults: a regression that dropped either key from + // createInitialExtensionState would otherwise stay hidden because the + // merge tests supply the keys manually. + const state = createInitialExtensionState() + + expect(state.changeCardDetail).toBe("summary") + expect(state.perWriteCheckpoints).toBe(true) + }) + it("updates apiConfiguration through setApiConfiguration", () => { render( @@ -426,6 +437,7 @@ describe("mergeExtensionState", () => { shouldShowAnnouncement: false, enableCheckpoints: true, perWriteCheckpoints: true, + changeCardDetail: "summary", writeDelayMs: 1000, mode: "default", experiments: {} as Record, @@ -456,12 +468,16 @@ describe("mergeExtensionState", () => { const prevState: ExtensionState = { ...baseState, + // Non-default checkpoint keys so a merge regression that drops or + // resets them cannot hide behind the initial defaults. + perWriteCheckpoints: false, + changeCardDetail: "full", apiConfiguration: { modelMaxTokens: 1234, modelMaxThinkingTokens: 123 }, experiments: {} as Record, checkpointTimeout: DEFAULT_CHECKPOINT_TIMEOUT_SECONDS - 5, } - const newState: ExtensionState = { + const newState: Partial = { ...baseState, apiConfiguration: { modelMaxThinkingTokens: 456, modelTemperature: 0.3 }, experiments: { @@ -473,6 +489,11 @@ describe("mergeExtensionState", () => { checkpointTimeout: DEFAULT_CHECKPOINT_TIMEOUT_SECONDS + 5, } + // A partial state push may omit the checkpoint keys entirely; the + // merge must preserve the previous non-default values. + delete newState.perWriteCheckpoints + delete newState.changeCardDetail + const result = mergeExtensionState(prevState, newState) expect(result.apiConfiguration).toEqual({ @@ -486,6 +507,11 @@ describe("mergeExtensionState", () => { runSlashCommand: false, customTools: false, }) + + // A partial push that omits the checkpoint keys must keep the previous + // non-default values. + expect(result.perWriteCheckpoints).toBe(false) + expect(result.changeCardDetail).toBe("full") }) describe("clineMessagesSeq protection", () => { @@ -497,6 +523,7 @@ describe("mergeExtensionState", () => { shouldShowAnnouncement: false, enableCheckpoints: true, perWriteCheckpoints: true, + changeCardDetail: "summary", writeDelayMs: 1000, mode: "default", experiments: {} as Record, diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index c09bce835d..50177ed2a8 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -707,6 +707,10 @@ "perWrite": { "label": "Punt de control després de cada escriptura de fitxer", "description": "Registra una instantània de punt de control després de cada escriptura de fitxer reeixida de l’agent" + }, + "changeCardDetail": { + "label": "Mostra la diff completa a les targetes de canvis", + "description": "Inclou la diff unificada completa en línia per a cada fitxer a les targetes de canvis per pas. Desactivada, les targetes només mostren la llista de fitxers amb les línies afegides/eliminades." } }, "notifications": { diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index 261cfd9c1c..c7f242d468 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -707,6 +707,10 @@ "perWrite": { "label": "Kontrollpunkt nach jedem Dateischreibvorgang", "description": "Ein Kontrollpunkt-Snapshot wird nach jedem erfolgreichen Dateischreibvorgang des Agents erfasst" + }, + "changeCardDetail": { + "label": "Volle Diff in Änderungskarten anzeigen", + "description": "Enthält die vollständige Unified-Diff inline für jede Datei in den Änderungskarten pro Schritt. Deaktiviert zeigen die Karten nur die Dateiliste mit hinzugefügten/entfernten Zeilen." } }, "notifications": { diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index af4fc92393..42bb57bd00 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -787,6 +787,10 @@ "perWrite": { "label": "Checkpoint after each file write", "description": "Record a checkpoint snapshot after every successful file write by the agent" + }, + "changeCardDetail": { + "label": "Show full diff in change cards", + "description": "Include the full unified diff inline for every file in per-step change cards. When off, cards show only the file list with added/removed line counts." } }, "notifications": { diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index b4cfbfc980..64aa21b167 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -707,6 +707,10 @@ "perWrite": { "label": "Punto de control después de cada escritura de archivo", "description": "Registra una instantánea de punto de control después de cada escritura de archivo exitosa del agente" + }, + "changeCardDetail": { + "label": "Mostrar la diff completa en las tarjetas de cambios", + "description": "Incluye la diff unificada completa en línea para cada archivo en las tarjetas de cambios por paso. Al desactivarla, las tarjetas muestran solo la lista de archivos con las líneas añadidas/eliminadas." } }, "notifications": { diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index 5994d49fb6..a7cf663513 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -707,6 +707,10 @@ "perWrite": { "label": "Point de contrôle après chaque écriture de fichier", "description": "Enregistre un instantané de point de contrôle après chaque écriture de fichier réussie par l’agent" + }, + "changeCardDetail": { + "label": "Afficher la diff complète dans les cartes de modifications", + "description": "Inclut la diff unifiée complète en ligne pour chaque fichier dans les cartes de modifications par étape. Désactivée, les cartes n'affichent que la liste des fichiers avec les lignes ajoutées/retirées." } }, "notifications": { diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index 98972b5501..a6dd612ebf 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -707,6 +707,10 @@ "perWrite": { "label": "हर फ़ाइल लिखने के बाद चेकपॉइंट", "description": "एजेंट द्वारा हर सफल फ़ाइल लिखने के बाद एक चेकपॉइंट स्नैपशॉट दर्ज किया जाता है" + }, + "changeCardDetail": { + "label": "बदलाव कार्डों में पूर्ण diff दिखाएँ", + "description": "प्रति-चरण बदलाव कार्डों में हर फ़ाइल के लिए पूर्ण unified diff इनलाइन शामिल करता है। बंद होने पर कार्ड केवल जोड़ी/हटाई गई पंक्तियों के साथ फ़ाइल सूची दिखाते हैं।" } }, "notifications": { diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json index 7b94209e38..ebcdce7c50 100644 --- a/webview-ui/src/i18n/locales/id/settings.json +++ b/webview-ui/src/i18n/locales/id/settings.json @@ -707,6 +707,10 @@ "perWrite": { "label": "Checkpoint setelah setiap penulisan file", "description": "Merekam snapshot checkpoint setelah setiap penulisan file yang berhasil oleh agen" + }, + "changeCardDetail": { + "label": "Tampilkan diff lengkap di kartu perubahan", + "description": "Termasuk diff terpadu lengkap secara inline untuk setiap file di kartu perubahan per langkah. Saat dimatikan, kartu hanya menampilkan daftar file dengan baris yang ditambahkan/dihapus." } }, "notifications": { diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index c7e1d7a5d0..cff3dd7536 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -707,6 +707,10 @@ "perWrite": { "label": "Punto di controllo dopo ogni scrittura del file", "description": "Registra uno snapshot di punto di controllo dopo ogni scrittura del file riuscita dell’agente" + }, + "changeCardDetail": { + "label": "Mostra la diff completa nelle card dei cambiamenti", + "description": "Include la diff unificata completa in linea per ogni file nelle card dei cambiamenti per passo. Se disattivata, le card mostrano solo l'elenco dei file con le righe aggiunte/rimosse." } }, "notifications": { diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index f630f812a1..aadcd27087 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -707,6 +707,10 @@ "perWrite": { "label": "ファイルの書き込みごとにチェックポイント", "description": "エージェントによる各ファイルの書き込み成功後にチェックポイントのスナップショットを記録します" + }, + "changeCardDetail": { + "label": "変更カードに完全な diff を表示", + "description": "ステップごとの変更カードに各ファイルの完全な unified diff をインラインで含めます。オフにすると、カードは追加/削除行数付きのファイル一覧のみを表示します。" } }, "notifications": { diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index 4dff5e471e..a06707ac5f 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -707,6 +707,10 @@ "perWrite": { "label": "파일을 쓸 때마다 체크포인트", "description": "에이전트가 파일 쓰기에 성공할 때마다 체크포인트 스냅샷을 기록합니다" + }, + "changeCardDetail": { + "label": "변경 카드에 전체 diff 표시", + "description": "단계별 변경 카드에 각 파일의 전체 unified diff를 인라인으로 포함합니다. 끄면 카드는 추가/제거 줄 수만 있는 파일 목록만 표시합니다." } }, "notifications": { diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json index ed36d4e40f..368d7a17eb 100644 --- a/webview-ui/src/i18n/locales/nl/settings.json +++ b/webview-ui/src/i18n/locales/nl/settings.json @@ -707,6 +707,10 @@ "perWrite": { "label": "Checkpoint na elke bestandsschrijving", "description": "Neemt een checkpoint-snapshot op na elke succesvolle bestandsschrijving door de agent" + }, + "changeCardDetail": { + "label": "Volledige diff tonen in wijzigingskaarten", + "description": "Bevat de volledige unified diff inline voor elk bestand in wijzigingskaarten per stap. Wanneer deze optie is uitgeschakeld, tonen de kaarten alleen de bestandslijst met toegevoegde/verwijderde regels." } }, "notifications": { diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index e2e9840223..b57bd738a5 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -707,6 +707,10 @@ "perWrite": { "label": "Punkt kontrolny po każdym zapisaniu pliku", "description": "Rejestruje migawkę punktu kontrolnego po każdym udanym zapisaniu pliku przez agenta" + }, + "changeCardDetail": { + "label": "Pokaż pełny diff w kartach zmian", + "description": "Zawiera pełny spójny diff inline dla każdego pliku w kartach zmian per krok. Po wyłączeniu karty pokazują tylko listę plików z dodanymi/usuniętymi liniami." } }, "notifications": { diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index b600da9281..abc7b0062b 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -707,6 +707,10 @@ "perWrite": { "label": "Ponto de verificação após cada gravação de arquivo", "description": "Registra um snapshot de ponto de verificação após cada gravação de arquivo bem-sucedida pelo agente" + }, + "changeCardDetail": { + "label": "Mostrar diff completo nos cartões de alterações", + "description": "Inclui a diff unificada completa em linha para cada arquivo nos cartões de alterações por etapa. Quando desativado, os cartões mostram apenas a lista de arquivos com linhas adicionadas/removidas." } }, "notifications": { diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index c83e1f1f88..f171328b22 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -707,6 +707,10 @@ "perWrite": { "label": "Контрольная точка после каждой записи файла", "description": "Записывает снимок контрольной точки после каждой успешной записи файла агентом" + }, + "changeCardDetail": { + "label": "Показывать полный diff в карточках изменений", + "description": "Включает полную unified diff для каждого файла в карточках изменений по шагам. При выключенном показе карточки отображают только список файлов с количеством добавленных/удалённых строк." } }, "notifications": { diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index a1c3571ab7..c226c44214 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -707,6 +707,10 @@ "perWrite": { "label": "Her dosya yazımından sonra kontrol noktası", "description": "Ajanın her başarılı dosya yazımından sonra bir kontrol noktası görüntüsü kaydeder" + }, + "changeCardDetail": { + "label": "Değişiklik kartlarında tam diff'i göster", + "description": "Adım başına değişiklik kartlarında her dosya için tam birleşik diff'i satır içi olarak içerir. Kapalıyken kartlar yalnızca eklenen/çıkarılan satır sayıları dosya listesini gösterir." } }, "notifications": { diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index 711e01180d..c1b02a8948 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -707,6 +707,10 @@ "perWrite": { "label": "Điểm kiểm tra sau mỗi lần ghi file", "description": "Ghi lại ảnh chụp nhanh điểm kiểm tra sau mỗi lần ghi file thành công của agent" + }, + "changeCardDetail": { + "label": "Hiển thị diff đầy đủ trong thẻ thay đổi", + "description": "Bao gồm diff thống nhất đầy đủ nội tuyến cho từng tệp trong thẻ thay đổi theo bước. Khi tắt, thẻ chỉ hiển thị danh sách tệp với số dòng thêm/xóa." } }, "notifications": { diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index a02e36081f..f105237330 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -707,6 +707,10 @@ "perWrite": { "label": "每次文件写入后创建存档点", "description": "智能体每次成功写入文件后都会记录一个存档点快照" + }, + "changeCardDetail": { + "label": "在变更卡片中显示完整 diff", + "description": "在逐步变更卡片中为每个文件内嵌完整 unified diff。关闭时,卡片仅显示文件列表与新增/删除行数。" } }, "notifications": { diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index 179b0cdd3f..d03f431c91 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -734,6 +734,10 @@ "perWrite": { "label": "每次檔案寫入後建立檢查點", "description": "代理每次成功寫入檔案後都會記錄一個檢查點快照" + }, + "changeCardDetail": { + "label": "在變更卡片中顯示完整 diff", + "description": "在逐步變更卡片中為每個檔案內嵌完整 unified diff。關閉時,卡片僅顯示檔案清單與新增/刪除行數。" } }, "notifications": {