mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-09-24 16:02:55 +08:00
feat: add ability to remove discovered skills from Agent Behaviour settings
Add a remove button (X icon) to each discovered skill in the skills subtab with a confirmation dialog. On confirm, the skill's directory is deleted from disk and the skills list is refreshed.
This commit is contained in:
@@ -429,6 +429,11 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
|
||||
case "requestSkills":
|
||||
this.fetchAndSendSkills().catch((e) => console.error("[Kilo New] fetchAndSendSkills failed:", e))
|
||||
break
|
||||
case "removeSkill":
|
||||
this.handleRemoveSkill(message.location).catch((e) =>
|
||||
console.error("[Kilo New] handleRemoveSkill failed:", e),
|
||||
)
|
||||
break
|
||||
case "questionReply":
|
||||
await this.handleQuestionReply(message.requestID, message.answers)
|
||||
break
|
||||
@@ -1127,6 +1132,21 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a skill by deleting its directory from disk, then refresh the skills list.
|
||||
* The location is the path to the SKILL.md file; the skill directory is its parent.
|
||||
*/
|
||||
private async handleRemoveSkill(location: string): Promise<void> {
|
||||
const dir = path.dirname(location)
|
||||
try {
|
||||
await vscode.workspace.fs.delete(vscode.Uri.file(dir), { recursive: true })
|
||||
} catch (error) {
|
||||
console.error("[Kilo New] KiloProvider: Failed to delete skill directory:", dir, error)
|
||||
}
|
||||
this.cachedSkillsMessage = null
|
||||
await this.fetchAndSendSkills()
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch backend config and send to webview.
|
||||
*/
|
||||
|
||||
@@ -4,6 +4,8 @@ import { TextField } from "@kilocode/kilo-ui/text-field"
|
||||
import { Card } from "@kilocode/kilo-ui/card"
|
||||
import { Button } from "@kilocode/kilo-ui/button"
|
||||
import { IconButton } from "@kilocode/kilo-ui/icon-button"
|
||||
import { Dialog } from "@kilocode/kilo-ui/dialog"
|
||||
import { useDialog } from "@kilocode/kilo-ui/context/dialog"
|
||||
|
||||
import { useConfig } from "../../context/config"
|
||||
import { useSession } from "../../context/session"
|
||||
@@ -53,6 +55,7 @@ const AgentBehaviourTab: Component = () => {
|
||||
const { config, updateConfig } = useConfig()
|
||||
const session = useSession()
|
||||
const vscode = useVSCode()
|
||||
const dialog = useDialog()
|
||||
const [activeSubtab, setActiveSubtab] = createSignal<SubtabId>("agents")
|
||||
const [selectedAgent, setSelectedAgent] = createSignal<string>("")
|
||||
const [newSkillPath, setNewSkillPath] = createSignal("")
|
||||
@@ -179,6 +182,35 @@ const AgentBehaviourTab: Component = () => {
|
||||
updateConfig({ skills: { ...config().skills, urls: current } })
|
||||
}
|
||||
|
||||
const removeSkill = (skill: SkillInfo) => {
|
||||
vscode.postMessage({ type: "removeSkill", location: skill.location })
|
||||
}
|
||||
|
||||
const confirmRemoveSkill = (skill: SkillInfo) => {
|
||||
dialog.show(() => (
|
||||
<Dialog title={language.t("settings.agentBehaviour.removeSkill.title")} fit>
|
||||
<div class="dialog-confirm-body">
|
||||
<span>{language.t("settings.agentBehaviour.removeSkill.confirm", { name: skill.name })}</span>
|
||||
<div class="dialog-confirm-actions">
|
||||
<Button variant="ghost" size="large" onClick={() => dialog.close()}>
|
||||
{language.t("common.cancel")}
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
size="large"
|
||||
onClick={() => {
|
||||
removeSkill(skill)
|
||||
dialog.close()
|
||||
}}
|
||||
>
|
||||
{language.t("settings.agentBehaviour.removeSkill.button")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
))
|
||||
}
|
||||
|
||||
const renderAgentsSubtab = () => (
|
||||
<div>
|
||||
{/* Default agent */}
|
||||
@@ -410,24 +442,30 @@ const AgentBehaviourTab: Component = () => {
|
||||
{(skill, index) => (
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
"align-items": "center",
|
||||
"justify-content": "space-between",
|
||||
padding: "8px 0",
|
||||
"border-bottom":
|
||||
index() < discoveredSkills().length - 1 ? "1px solid var(--border-weak-base)" : "none",
|
||||
}}
|
||||
>
|
||||
<div data-slot="settings-row-label-title" style={{ "margin-bottom": "0" }}>
|
||||
{skill.name}
|
||||
</div>
|
||||
<div
|
||||
data-slot="settings-row-label-subtitle"
|
||||
style={{
|
||||
"margin-top": "4px",
|
||||
"font-family": "var(--vscode-editor-font-family, monospace)",
|
||||
}}
|
||||
>
|
||||
<div>{skill.description}</div>
|
||||
<div>{skill.location}</div>
|
||||
<div style={{ flex: 1, "min-width": 0 }}>
|
||||
<div data-slot="settings-row-label-title" style={{ "margin-bottom": "0" }}>
|
||||
{skill.name}
|
||||
</div>
|
||||
<div
|
||||
data-slot="settings-row-label-subtitle"
|
||||
style={{
|
||||
"margin-top": "4px",
|
||||
"font-family": "var(--vscode-editor-font-family, monospace)",
|
||||
}}
|
||||
>
|
||||
<div>{skill.description}</div>
|
||||
<div>{skill.location}</div>
|
||||
</div>
|
||||
</div>
|
||||
<IconButton size="small" variant="ghost" icon="close" onClick={() => confirmRemoveSkill(skill)} />
|
||||
</div>
|
||||
)}
|
||||
</For>
|
||||
|
||||
@@ -971,6 +971,9 @@ export const dict = {
|
||||
"No skills discovered. Add skill folder paths or URLs below to make skills available.",
|
||||
"settings.agentBehaviour.skillPaths": "Skill Folder Paths",
|
||||
"settings.agentBehaviour.skillUrls": "Skill URLs",
|
||||
"settings.agentBehaviour.removeSkill.title": "Remove skill",
|
||||
"settings.agentBehaviour.removeSkill.confirm": 'Remove skill "{{name}}"? This will delete the skill files from disk.',
|
||||
"settings.agentBehaviour.removeSkill.button": "Remove",
|
||||
"settings.agentBehaviour.instructionFiles": "Additional Instruction Files",
|
||||
"settings.agentBehaviour.instructionFiles.description":
|
||||
"Paths to additional instruction files that are included in the system prompt",
|
||||
|
||||
@@ -1248,6 +1248,11 @@ export interface RequestSkillsMessage {
|
||||
type: "requestSkills"
|
||||
}
|
||||
|
||||
export interface RemoveSkillMessage {
|
||||
type: "removeSkill"
|
||||
location: string
|
||||
}
|
||||
|
||||
export interface SetLanguageRequest {
|
||||
type: "setLanguage"
|
||||
locale: string
|
||||
@@ -1628,6 +1633,7 @@ export type WebviewMessage =
|
||||
| CompactRequest
|
||||
| RequestAgentsMessage
|
||||
| RequestSkillsMessage
|
||||
| RemoveSkillMessage
|
||||
| SetLanguageRequest
|
||||
| QuestionReplyRequest
|
||||
| QuestionRejectRequest
|
||||
|
||||
Reference in New Issue
Block a user