diff --git a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/settings/autoapprove/AutoApproveSettingsState.kt b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/settings/autoapprove/AutoApproveSettingsState.kt index fe54b0e7da..82a01edfca 100644 --- a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/settings/autoapprove/AutoApproveSettingsState.kt +++ b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/settings/autoapprove/AutoApproveSettingsState.kt @@ -92,13 +92,17 @@ internal fun setException(draft: PermissionDraft, tool: String, pattern: String, } /** Add a new exception pattern for [tool], defaulting its level to allow. */ -internal fun addException(draft: PermissionDraft, tool: String, pattern: String): PermissionDraft = - setException(draft, tool, pattern, "allow") +internal fun addException(draft: PermissionDraft, tool: String, pattern: String): PermissionDraft { + val rule = draft.rules[tool] as? PermissionRuleDto.Patterns + if (rule?.map?.get(pattern) != null) return draft + return setException(draft, tool, pattern, "allow") +} internal fun editException(draft: PermissionDraft, tool: String, from: String, to: String): PermissionDraft { if (from == to) return draft val rule = draft.rules[tool] as? PermissionRuleDto.Patterns ?: return draft val level = rule.map[from] ?: return draft + if (rule.map[to] != null) return draft val map = rule.map.filterKeys { it != from } + (to to level) return draft.copy(rules = draft.rules + (tool to PermissionRuleDto.Patterns(map))) } diff --git a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/settings/autoapprove/SettingsInlineList.kt b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/settings/autoapprove/SettingsInlineList.kt index 1fc2d03aec..b0f77468b1 100644 --- a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/settings/autoapprove/SettingsInlineList.kt +++ b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/settings/autoapprove/SettingsInlineList.kt @@ -80,6 +80,7 @@ internal class SettingsInlineList( selectionMode, showSearch = false, ) { + private var keys = emptySet() /** Overridable in tests, mirrors `PatternList.input` in ContextSettingsUi.kt. */ internal var input: () -> String? = { @@ -102,6 +103,7 @@ internal class SettingsInlineList( } fun syncRows(rows: List, enabled: Boolean) { + keys = rows.map { it.key }.toSet() setItems(rows.map(::PermissionItem), enabled) } @@ -147,6 +149,10 @@ internal class SettingsInlineList( val add = onAdd ?: return val value = input()?.trim().orEmpty() if (value.isBlank()) return + if (value in keys) { + selectKey(value, scroll = true) + return + } add(value) } @@ -154,6 +160,10 @@ internal class SettingsInlineList( val edit = onEdit ?: return val value = editInput(key)?.trim().orEmpty() if (value.isBlank() || value == key) return + if (value in keys) { + selectKey(value, scroll = true) + return + } edit(key, value) } diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ar.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ar.properties index e20e01fce5..0f2b9650fc 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ar.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ar.properties @@ -430,3 +430,6 @@ settings.context.watcher.remove=إزالة الأنماط المحددة settings.context.watcher.empty=لم يتم تكوين أنماط تجاهل. settings.context.watcher.input.title=إضافة نمط تجاهل settings.context.watcher.input.prompt=أدخل نمط glob لتجاهله: + +# Auto-Approve settings +settings.autoApprove.edit=تحرير diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_bs.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_bs.properties index 50718f6aa3..f061cb6747 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_bs.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_bs.properties @@ -430,3 +430,6 @@ settings.context.watcher.remove=Ukloni odabrane uzorke settings.context.watcher.empty=Nema konfigurisanih uzoraka za ignoriranje. settings.context.watcher.input.title=Dodaj uzorak za ignoriranje settings.context.watcher.input.prompt=Unesite glob uzorak za ignoriranje: + +# Auto-Approve settings +settings.autoApprove.edit=Uredi diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_da.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_da.properties index 97312d4554..8e38ac0e99 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_da.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_da.properties @@ -430,3 +430,6 @@ settings.context.watcher.remove=Fjern valgte mønstre settings.context.watcher.empty=Ingen ignormønstre konfigureret. settings.context.watcher.input.title=Tilføj ignormønster settings.context.watcher.input.prompt=Indtast et glob-mønster, der skal ignoreres: + +# Auto-Approve settings +settings.autoApprove.edit=Rediger diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_de.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_de.properties index 0b109cb5d1..5e7550c3c2 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_de.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_de.properties @@ -430,3 +430,6 @@ settings.context.watcher.remove=Ausgewählte Muster entfernen settings.context.watcher.empty=Keine Ignorierungsmuster konfiguriert. settings.context.watcher.input.title=Ignorierungsmuster hinzufügen settings.context.watcher.input.prompt=Glob-Muster zum Ignorieren eingeben: + +# Auto-Approve settings +settings.autoApprove.edit=Bearbeiten diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_es.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_es.properties index 0fb4bf6b32..4329c51145 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_es.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_es.properties @@ -430,3 +430,6 @@ settings.context.watcher.remove=Eliminar patrones seleccionados settings.context.watcher.empty=No hay patrones de ignorar configurados. settings.context.watcher.input.title=Agregar patrón de ignorar settings.context.watcher.input.prompt=Introduce un patrón glob para ignorar: + +# Auto-Approve settings +settings.autoApprove.edit=Editar diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_fr.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_fr.properties index 3a73251d2c..062dcabb20 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_fr.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_fr.properties @@ -430,3 +430,6 @@ settings.context.watcher.remove=Supprimer les motifs sélectionnés settings.context.watcher.empty=Aucun motif d’ignorance configuré. settings.context.watcher.input.title=Ajouter un motif d’ignorance settings.context.watcher.input.prompt=Saisissez un motif glob à ignorer : + +# Auto-Approve settings +settings.autoApprove.edit=Modifier diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ja.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ja.properties index 690c80ac6f..b16d3dcd87 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ja.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ja.properties @@ -430,3 +430,6 @@ settings.context.watcher.remove=選択したパターンを削除 settings.context.watcher.empty=無視パターンは設定されていません。 settings.context.watcher.input.title=無視パターンを追加 settings.context.watcher.input.prompt=無視するglobパターンを入力してください: + +# Auto-Approve settings +settings.autoApprove.edit=編集 diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ko.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ko.properties index fbb207e99a..d1d77fadf1 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ko.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ko.properties @@ -430,3 +430,6 @@ settings.context.watcher.remove=선택한 패턴 제거 settings.context.watcher.empty=구성된 무시 패턴이 없습니다. settings.context.watcher.input.title=무시 패턴 추가 settings.context.watcher.input.prompt=무시할 glob 패턴을 입력하세요: + +# Auto-Approve settings +settings.autoApprove.edit=편집 diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_nl.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_nl.properties index 48a5012988..ca24376502 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_nl.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_nl.properties @@ -430,3 +430,6 @@ settings.context.watcher.remove=Geselecteerde patronen verwijderen settings.context.watcher.empty=Geen negeerpatronen geconfigureerd. settings.context.watcher.input.title=Negeerpatroon toevoegen settings.context.watcher.input.prompt=Voer een glob-patroon in om te negeren: + +# Auto-Approve settings +settings.autoApprove.edit=Bewerken diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_no.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_no.properties index f496ba6895..e4753e67a7 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_no.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_no.properties @@ -430,3 +430,6 @@ settings.context.watcher.remove=Fjern valgte mønstre settings.context.watcher.empty=Ingen ignormønstre konfigurert. settings.context.watcher.input.title=Legg til ignormønster settings.context.watcher.input.prompt=Skriv inn et glob-mønster som skal ignoreres: + +# Auto-Approve settings +settings.autoApprove.edit=Rediger diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_pl.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_pl.properties index 1b11ce706c..01a220418e 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_pl.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_pl.properties @@ -430,3 +430,6 @@ settings.context.watcher.remove=Usuń wybrane wzorce settings.context.watcher.empty=Nie skonfigurowano wzorców ignorowania. settings.context.watcher.input.title=Dodaj wzorzec ignorowania settings.context.watcher.input.prompt=Wpisz wzorzec glob do ignorowania: + +# Auto-Approve settings +settings.autoApprove.edit=Edytuj diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_pt_BR.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_pt_BR.properties index 310300af16..7a2f489b0a 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_pt_BR.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_pt_BR.properties @@ -430,3 +430,6 @@ settings.context.watcher.remove=Remover padrões selecionados settings.context.watcher.empty=Nenhum padrão de ignorar configurado. settings.context.watcher.input.title=Adicionar padrão de ignorar settings.context.watcher.input.prompt=Digite um padrão glob para ignorar: + +# Auto-Approve settings +settings.autoApprove.edit=Editar diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ru.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ru.properties index a99de42be5..4beb8bc385 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ru.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ru.properties @@ -430,3 +430,6 @@ settings.context.watcher.remove=Удалить выбранные шаблоны settings.context.watcher.empty=Шаблоны игнорирования не настроены. settings.context.watcher.input.title=Добавить шаблон игнорирования settings.context.watcher.input.prompt=Введите glob-шаблон для игнорирования: + +# Auto-Approve settings +settings.autoApprove.edit=Изменить diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_th.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_th.properties index dacf14d429..ad185648d8 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_th.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_th.properties @@ -430,3 +430,6 @@ settings.context.watcher.remove=ลบรูปแบบที่เลือก settings.context.watcher.empty=ยังไม่ได้กำหนดค่ารูปแบบการละเว้น settings.context.watcher.input.title=เพิ่มรูปแบบการละเว้น settings.context.watcher.input.prompt=ป้อนรูปแบบ glob ที่จะละเว้น: + +# Auto-Approve settings +settings.autoApprove.edit=แก้ไข diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_tr.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_tr.properties index d018cdd240..8ea019b233 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_tr.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_tr.properties @@ -430,3 +430,6 @@ settings.context.watcher.remove=Seçili kalıpları kaldır settings.context.watcher.empty=Yok sayma kalıbı yapılandırılmadı. settings.context.watcher.input.title=Yok sayma kalıbı ekle settings.context.watcher.input.prompt=Yok sayılacak bir glob kalıbı girin: + +# Auto-Approve settings +settings.autoApprove.edit=Düzenle diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_uk.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_uk.properties index e981786fc5..5b220bad1b 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_uk.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_uk.properties @@ -430,3 +430,6 @@ settings.context.watcher.remove=Видалити вибрані шаблони settings.context.watcher.empty=Шаблони ігнорування не налаштовано. settings.context.watcher.input.title=Додати шаблон ігнорування settings.context.watcher.input.prompt=Введіть glob-шаблон для ігнорування: + +# Auto-Approve settings +settings.autoApprove.edit=Редагувати diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_zh_CN.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_zh_CN.properties index 9c6e2d76b0..649a5faa59 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_zh_CN.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_zh_CN.properties @@ -430,3 +430,6 @@ settings.context.watcher.remove=移除所选模式 settings.context.watcher.empty=未配置忽略模式。 settings.context.watcher.input.title=添加忽略模式 settings.context.watcher.input.prompt=输入要忽略的 glob 模式: + +# Auto-Approve settings +settings.autoApprove.edit=编辑 diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_zh_TW.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_zh_TW.properties index 401ca4ed8e..9f0e38414a 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_zh_TW.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_zh_TW.properties @@ -430,3 +430,6 @@ settings.context.watcher.remove=移除所選模式 settings.context.watcher.empty=尚未設定忽略模式。 settings.context.watcher.input.title=新增忽略模式 settings.context.watcher.input.prompt=輸入要忽略的 glob 模式: + +# Auto-Approve settings +settings.autoApprove.edit=編輯 diff --git a/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/settings/autoapprove/AutoApproveSettingsStateTest.kt b/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/settings/autoapprove/AutoApproveSettingsStateTest.kt index 1f5490c0eb..63ba407135 100644 --- a/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/settings/autoapprove/AutoApproveSettingsStateTest.kt +++ b/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/settings/autoapprove/AutoApproveSettingsStateTest.kt @@ -107,6 +107,26 @@ class AutoApproveSettingsStateTest { ) } + @Test + fun `addException ignores an existing pattern`() { + val draft = PermissionDraft( + rules = mapOf("bash" to PermissionRuleDto.Patterns(mapOf("*" to "ask", "git *" to "deny"))), + ) + + assertEquals(draft, addException(draft, "bash", "git *")) + } + + @Test + fun `editException ignores an existing target pattern`() { + val draft = PermissionDraft( + rules = mapOf( + "bash" to PermissionRuleDto.Patterns(mapOf("git *" to "deny", "git status" to "ask")), + ), + ) + + assertEquals(draft, editException(draft, "bash", "git *", "git status")) + } + @Test fun `setException changes an existing exception level`() { val from = PermissionDraft( diff --git a/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/settings/autoapprove/SettingsInlineListTest.kt b/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/settings/autoapprove/SettingsInlineListTest.kt index fc3245eb07..e1de6aa07e 100644 --- a/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/settings/autoapprove/SettingsInlineListTest.kt +++ b/packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/settings/autoapprove/SettingsInlineListTest.kt @@ -69,6 +69,20 @@ class SettingsInlineListTest : BasePlatformTestCase() { } } + fun `test toolbar add ignores duplicate input`() { + edt { + val added = mutableListOf() + val list = list(onAdd = { added += it }) + list.syncItems(listOf("git *" to "ask"), true) + list.input = { "git *" } + layout(list) + + click(button(list, 0)) + + assertTrue(added.isEmpty()) + } + } + fun `test row level action changes through picker selection`() { edt { val changed = mutableListOf() @@ -122,6 +136,22 @@ class SettingsInlineListTest : BasePlatformTestCase() { } } + fun `test exception edit ignores duplicate target`() { + edt { + val edits = mutableListOf>() + val list = list(onEdit = { from, to -> edits += from to to }) + list.editInput = { "git status" } + list.syncItems(listOf("git *" to "allow", "git status" to "ask"), true) + val jList = jbList(list) + jList.setSize(400, jList.preferredSize.height.coerceAtLeast(50)) + jList.doLayout() + + doubleClickRow(jList, 0) + + assertTrue(edits.isEmpty()) + } + } + fun `test syncItems retains the same list view instance across updates`() { edt { val list = list()