Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/clear-doom-loop-prompts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"kilo-code": patch
---

Clarify potential loop permission prompts and auto-approval rules with localized tool names.
25 changes: 24 additions & 1 deletion packages/kilo-vscode/tests/unit/permission-description.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { describe, test, expect } from "bun:test"
import {
describePatterns,
describeRule,
resolveLabel,
TOOL_LABEL_KEYS,
} from "../../webview-ui/src/components/chat/permission-dock-utils"
import { resolveTemplate } from "../../webview-ui/src/context/language-utils"

// Mock t() that returns the English label for known keys, or the key itself
const labels: Record<string, string> = {
Expand All @@ -24,8 +26,10 @@ const labels: Record<string, string> = {
"ui.permission.toolLabel.task": "Task",
"ui.permission.toolLabel.skill": "Skill",
"ui.permission.toolLabel.lsp": "LSP",
"ui.permission.doomLoop.prompt": "Potential loop detected for the {{tool}} tool. Continue running?",
"ui.permission.doomLoop.rule": "Continue {{tool}} calls",
}
const t = (key: string) => labels[key] ?? key
const t = (key: string, params?: Record<string, string>) => resolveTemplate(labels[key] ?? key, params)

describe("describePatterns", () => {
test("returns null when patterns is empty", () => {
Expand Down Expand Up @@ -95,6 +99,14 @@ describe("describePatterns", () => {
expect(result).toEqual({ kind: "single", text: "Web Search query" })
})

test("doom loop describes the repeated tool with its human-readable label", () => {
const result = describePatterns("doom_loop", ["read"], t)
expect(result).toEqual({
kind: "single",
text: "Potential loop detected for the Read tool. Continue running?",
})
})

test("TOOL_LABEL_KEYS maps all expected tools", () => {
const expected: Record<string, string> = {
read: "ui.permission.toolLabel.read",
Expand Down Expand Up @@ -162,6 +174,17 @@ describe("describePatterns", () => {
})
})

describe("describeRule", () => {
test("describes doom loop rules as the action being allowed or denied", () => {
expect(describeRule("doom_loop", "read", t)).toBe("Continue Read calls")
})

test("preserves existing permission rule labels", () => {
expect(describeRule("read", "*", t)).toBe("Read")
expect(describeRule("read", "src/app.ts", t)).toBe("Read src/app.ts")
})
})

describe("resolveLabel", () => {
test("returns translated label for known tool", () => {
expect(resolveLabel("read", t)).toBe("Read")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { Tooltip } from "@kilocode/kilo-ui/tooltip"
import { useSession } from "../../context/session"
import { useLanguage } from "../../context/language"
import { useConfig } from "../../context/config"
import { describePatterns, resolveLabel, savedRuleStates, type RuleDecision } from "./permission-dock-utils"
import { describePatterns, describeRule, savedRuleStates, type RuleDecision } from "./permission-dock-utils"
import { PermissionCommand } from "./PermissionCommand"
import { PermissionDiff } from "./PermissionDiff"
import { permissionDiffs } from "./permission-diff-utils"
Expand Down Expand Up @@ -249,11 +249,7 @@ export const PermissionDock: Component<{
</Tooltip>
</div>
<code data-slot="permission-rule">
{command()
? label(rule)
: rule === "*"
? resolveLabel(props.request.toolName, language.t)
: `${resolveLabel(props.request.toolName, language.t)} ${rule}`}
{command() ? label(rule) : describeRule(props.request.toolName, rule, language.t)}
</code>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,17 @@ export function resolveLabel(tool: string, t: (key: string) => string): string {
return key ? t(key) : tool
}

export function describeRule(
tool: string,
rule: string,
t: (key: string, params?: Record<string, string>) => string,
): string {
if (tool === "doom_loop") {
return t("ui.permission.doomLoop.rule", { tool: resolveLabel(rule, t) })
}
return rule === "*" ? resolveLabel(tool, t) : `${resolveLabel(tool, t)} ${rule}`
}

/**
* Build a human-readable description for a permission request's patterns.
*
Expand All @@ -62,13 +73,20 @@ export function resolveLabel(tool: string, t: (key: string) => string): string {
export function describePatterns(
tool: string,
patterns: string[],
t: (key: string) => string,
t: (key: string, params?: Record<string, string>) => string,
): PatternDescription | null {
const filtered = patterns.filter((p) => p !== "*")
if (filtered.length === 0) return null

const key = TOOL_LABEL_KEYS[tool]
const label = key ? t(key) : tool
// doom-loop requests always contain one repeated tool pattern.
if (tool === "doom_loop") {
return {
kind: "single",
text: t("ui.permission.doomLoop.prompt", { tool: resolveLabel(filtered[0], t) }),
}
}

const label = resolveLabel(tool, t)
if (filtered.length === 1) return { kind: "single", text: `${label} ${filtered[0]}` }
return { kind: "multi", title: `${label}:`, paths: filtered }
}
2 changes: 2 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/ar.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/br.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/bs.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/da.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/de.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,8 @@ export const dict = {
"notification.permission.titleSubagent": "Permission required (subagent)",
"notification.permission.description": "{{sessionTitle}} in {{projectName}} needs permission",
"ui.permission.manageAutoApprove": "Manage Auto-Approve Rules",
"ui.permission.doomLoop.prompt": "Potential loop detected for the {{tool}} tool. Continue running?",
"ui.permission.doomLoop.rule": "Continue {{tool}} calls",
"ui.permission.rule.addToAllowed": "Add to allowed list",
"ui.permission.rule.removeFromAllowed": "Remove from allowed list",
"ui.permission.rule.addToDenied": "Add to denied list",
Expand Down
2 changes: 2 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/es.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/fr.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/it.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/ja.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/ko.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/nl.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/no.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/pl.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/ru.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/th.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/tr.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/uk.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/zh.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/zht.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading