fix(vscode): show full external permission paths

This commit is contained in:
Josh Lambert
2026-06-23 17:36:35 -04:00
parent c9d7016ea2
commit d2dff8844d
7 changed files with 69 additions and 10 deletions
@@ -0,0 +1,5 @@
---
"kilo-code": patch
---
Show full external directory paths in permission auto-approve rules.
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:af33f5d026513422db6efc37848eec76d9da511432e5933606ae0be73da684f8
size 16675
oid sha256:6ee59e48c176043eee3b22441ce1c50e8d17dbafe58e969cfc8e97f404f2608d
size 17429
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:61b1d0bc725e3b33a40d1d777d71b70afcec1b6cdcfae15e2023667bc4574f23
size 17201
oid sha256:5c4f1492f44da109debc1fc09195eac2a02a20cb211ee45b6651f81478d66b1a
size 71547
@@ -211,6 +211,21 @@ test.describe("Permission Dock Dropdown — external directory", () => {
await page.waitForSelector("#storybook-root *", { state: "attached" })
await openDropdown(page)
const text = "Read External Directory /Users/developer/projects/kilo-bench/dashboard/app/routes/*"
const hint = page.locator('[data-slot="permission-hint"]')
await expect(hint).toHaveText(text)
await expect(hint).toHaveAttribute("title", text)
expect(
await hint.evaluate((node) => node.scrollWidth > node.clientWidth || node.scrollHeight > node.clientHeight),
).toBe(false)
const rule = page.locator('[data-slot="permission-rule"]')
await expect(rule).toHaveText(text)
await expect(rule).toHaveAttribute("title", text)
expect(
await rule.evaluate((node) => node.scrollWidth > node.clientWidth || node.scrollHeight > node.clientHeight),
).toBe(false)
const root = page.locator("#storybook-root")
await expect(root).toHaveScreenshot(["permission-dock-dropdown", "external-dir-expanded-pending.png"])
})
@@ -48,6 +48,8 @@ export const PermissionDock: Component<{
// Normalize IDN/Unicode hostnames to punycode ASCII to prevent homograph attacks.
return normalizeUrls(cmd)
}
const text = (rule: string) => (command() ? label(rule) : describeRule(props.request.toolName, rule, language.t))
const external = () => props.request.toolName === "external_directory"
const cmdDescription = () => {
const val = props.request.args?.description
return typeof val === "string" && val.length > 0 ? val : undefined
@@ -248,8 +250,13 @@ export const PermissionDock: Component<{
</button>
</Tooltip>
</div>
<code data-slot="permission-rule">
{command() ? label(rule) : describeRule(props.request.toolName, rule, language.t)}
<code data-slot="permission-rule" data-wrap={external() ? "" : undefined} title={text(rule)}>
<Show when={external()} fallback={text(rule)}>
<span data-slot="permission-rule-label">
{language.t("ui.permission.toolLabel.externalDirectory")}{" "}
</span>
<span data-slot="permission-rule-path">{rule}</span>
</Show>
</code>
</div>
)}
@@ -268,7 +275,16 @@ export const PermissionDock: Component<{
const desc = description()
if (!desc)
return !command() && toolDescription() ? <div data-slot="permission-hint">{toolDescription()}</div> : null
if (desc.kind === "single") return <div data-slot="permission-hint">{desc.text}</div>
if (desc.kind === "single")
return (
<div
data-slot="permission-hint"
data-wrap={external() ? "" : undefined}
title={external() ? desc.text : undefined}
>
{desc.text}
</div>
)
return (
<div data-slot="permission-patterns">
<span data-slot="permission-patterns-title">{desc.title}</span>
@@ -958,9 +958,9 @@ const externalDirPermission: PermissionRequest = {
id: "perm-extdir-001",
sessionID: SESSION_ID,
toolName: "external_directory",
patterns: ["/home/user/other-project/*"],
always: ["/home/user/other-project/*"],
args: { filepath: "/home/user/other-project/config.json" },
patterns: ["/Users/developer/projects/kilo-bench/dashboard/app/routes/*"],
always: ["/Users/developer/projects/kilo-bench/dashboard/app/routes/*"],
args: { filepath: "/Users/developer/projects/kilo-bench/dashboard/app/routes/index.tsx" },
tool: { messageID: ASST_MSG_ID, callID: "call-extdir-001" },
}
@@ -109,6 +109,11 @@
[data-slot="permission-hint"] {
font-size: var(--kilo-font-size-12);
&[data-wrap] {
overflow-wrap: anywhere;
word-break: normal;
}
}
[data-slot="permission-patterns"] {
@@ -316,6 +321,24 @@
white-space: nowrap;
min-width: 0;
flex: 1;
&[data-wrap] {
display: flex;
flex-direction: column;
align-items: flex-start;
overflow: visible;
text-overflow: clip;
white-space: normal;
word-break: normal;
}
}
[data-slot="permission-rule-label"] {
color: var(--text-base, var(--vscode-foreground));
}
[data-slot="permission-rule-path"] {
overflow-wrap: anywhere;
}
[data-slot="permission-rule-actions"] {