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
31 changes: 31 additions & 0 deletions packages/kilo-vscode/src/KiloProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -1127,6 +1132,32 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
}
}

/**
* Remove a skill via the CLI backend (deletes from disk + clears cache), then refresh.
* The webview optimistically removes the skill from its list before this runs.
* On failure, re-fetches skills so the webview reverts to the authoritative state.
*/
private async handleRemoveSkill(location: string): Promise<void> {
if (!this.client) return
try {
const dir = this.getWorkspaceDirectory()
const result = await this.client.kilocode.removeSkill({ location, directory: dir })
if (result.error) {
console.error("[Kilo New] KiloProvider: removeSkill returned error:", result.error)
this.cachedSkillsMessage = null
await this.fetchAndSendSkills()
return
}
} catch (error) {
console.error("[Kilo New] KiloProvider: Failed to remove skill:", error)
this.cachedSkillsMessage = null
await this.fetchAndSendSkills()
return
}
// Invalidate cache so next requestSkills fetches fresh data
Comment thread
markijbema marked this conversation as resolved.
this.cachedSkillsMessage = null
}

/**
* Fetch backend config and send to webview.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { Component, createSignal, createMemo, createEffect, For, Show, onCleanup } from "solid-js"
import { Component, createSignal, createMemo, createEffect, For, Show } from "solid-js"
import { Select } from "@kilocode/kilo-ui/select"
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"
import { useLanguage } from "../../context/language"
import { useVSCode } from "../../context/vscode"
import type { AgentConfig, SkillInfo, ExtensionMessage } from "../../types/messages"
import type { AgentConfig, SkillInfo } from "../../types/messages"

type SubtabId = "agents" | "mcpServers" | "rules" | "workflows" | "skills"

Expand Down Expand Up @@ -52,30 +53,20 @@ const AgentBehaviourTab: Component = () => {
const language = useLanguage()
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("")
const [newSkillUrl, setNewSkillUrl] = createSignal("")
const [newInstruction, setNewInstruction] = createSignal("")
const [discoveredSkills, setDiscoveredSkills] = createSignal<SkillInfo[]>([])

// Subscribe to skillsLoaded messages from the extension
const unsub = vscode.onMessage((message: ExtensionMessage) => {
if (message.type === "skillsLoaded") {
setDiscoveredSkills(message.skills)
}
})

// Fetch skills whenever the skills subtab becomes active
createEffect(() => {
if (activeSubtab() === "skills") {
vscode.postMessage({ type: "requestSkills" })
session.refreshSkills()
}
})

onCleanup(() => unsub())

const agentNames = createMemo(() => {
const names = session.agents().map((a) => a.name)
// Also include any agents from config that might not be in the agent list
Expand Down Expand Up @@ -179,6 +170,31 @@ const AgentBehaviourTab: Component = () => {
updateConfig({ skills: { ...config().skills, urls: current } })
}

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={() => {
session.removeSkill(skill.location)
dialog.close()
}}
>
{language.t("settings.agentBehaviour.removeSkill.button")}
</Button>
</div>
</div>
</Dialog>
))
}

const renderAgentsSubtab = () => (
<div>
{/* Default agent */}
Expand Down Expand Up @@ -398,36 +414,41 @@ const AgentBehaviourTab: Component = () => {
{language.t("settings.agentBehaviour.discoveredSkills")}
</h4>
<Show
when={discoveredSkills().length > 0}
when={session.skills().length > 0}
fallback={
<Card style={{ "margin-bottom": "16px" }}>
<div data-slot="settings-row-label-subtitle">{language.t("settings.agentBehaviour.noSkillsFound")}</div>
</Card>
}
>
<Card style={{ "margin-bottom": "16px" }}>
<For each={discoveredSkills()}>
<For each={session.skills()}>
{(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",
"border-bottom": index() < session.skills().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>
Expand Down
29 changes: 29 additions & 0 deletions packages/kilo-vscode/webview-ui/src/context/session.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import type {
ModelSelection,
ContextUsage,
AgentInfo,
SkillInfo,
ExtensionMessage,
FileAttachment,
SendMessageFailedMessage,
Expand Down Expand Up @@ -114,6 +115,11 @@ interface SessionContextValue {
totalCost: Accessor<number>
contextUsage: Accessor<ContextUsage | undefined>

// Skills loaded from the CLI backend
skills: Accessor<SkillInfo[]>
refreshSkills: () => void
removeSkill: (location: string) => void

// Agent/mode selection (per-session)
agents: Accessor<AgentInfo[]>
selectedAgent: Accessor<string>
Expand Down Expand Up @@ -204,6 +210,9 @@ export const SessionProvider: ParentComponent = (props) => {
const [agents, setAgents] = createSignal<AgentInfo[]>([])
const [defaultAgent, setDefaultAgent] = createSignal("code")

// Skills loaded from the CLI backend
const [skills, setSkills] = createSignal<SkillInfo[]>([])

// Pending agent selection for before a session exists
const [pendingAgentSelection, setPendingAgentSelection] = createSignal<string | null>(null)

Expand Down Expand Up @@ -341,8 +350,25 @@ export const SessionProvider: ParentComponent = (props) => {
vscode.postMessage({ type: "requestAgents" })
}, agentRetryMs)

// Skills loaded from the CLI backend
const unsubSkills = vscode.onMessage((message: ExtensionMessage) => {
if (message.type === "skillsLoaded") {
setSkills(message.skills)
}
})

const refreshSkills = () => {
vscode.postMessage({ type: "requestSkills" })
}

const removeSkill = (location: string) => {
setSkills((prev) => prev.filter((s) => s.location !== location))
vscode.postMessage({ type: "removeSkill", location })
}

onCleanup(() => {
unsubAgents()
unsubSkills()
clearInterval(agentRetryTimer)
})

Expand Down Expand Up @@ -1285,6 +1311,9 @@ export const SessionProvider: ParentComponent = (props) => {
totalCost,
contextUsage,
agents,
skills,
refreshSkills,
removeSkill,
selectedAgent: selectedAgentName,
selectAgent,
getSessionAgent: (sessionID: string) => store.agentSelections[sessionID] ?? defaultAgent(),
Expand Down
4 changes: 4 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/ar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,10 @@ export const dict = {
"لم يتم العثور على مهارات. أضف مسارات مجلدات أو عناوين URL أدناه لإتاحة المهارات.",
"settings.agentBehaviour.skillPaths": "مسارات مجلدات المهارات",
"settings.agentBehaviour.skillUrls": "عناوين URL للمهارات",
"settings.agentBehaviour.removeSkill.title": "إزالة المهارة",
"settings.agentBehaviour.removeSkill.confirm":
'هل تريد إزالة المهارة "{{name}}"؟ سيؤدي هذا إلى حذف ملفات المهارة من القرص.',
"settings.agentBehaviour.removeSkill.button": "إزالة",
"settings.agentBehaviour.instructionFiles": "ملفات تعليمات إضافية",
"settings.agentBehaviour.instructionFiles.description": "مسارات ملفات التعليمات الإضافية في موجه النظام",
"settings.agentBehaviour.mcpEmpty": "لم يتم تهيئة خوادم MCP. قم بتحرير ملف تهيئة opencode لإضافة خوادم MCP.",
Expand Down
4 changes: 4 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/br.ts
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,10 @@ export const dict = {
"Nenhuma habilidade encontrada. Adicione caminhos de pastas ou URLs abaixo para disponibilizar habilidades.",
"settings.agentBehaviour.skillPaths": "Caminhos de pastas de habilidades",
"settings.agentBehaviour.skillUrls": "URLs de habilidades",
"settings.agentBehaviour.removeSkill.title": "Remover habilidade",
"settings.agentBehaviour.removeSkill.confirm":
'Remover a habilidade "{{name}}"? Isso excluirá os arquivos da habilidade do disco.',
"settings.agentBehaviour.removeSkill.button": "Remover",
"settings.agentBehaviour.instructionFiles": "Arquivos de instruções adicionais",
"settings.agentBehaviour.instructionFiles.description":
"Caminhos para arquivos de instruções adicionais no prompt do sistema",
Expand Down
4 changes: 4 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/bs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,10 @@ export const dict = {
"Nisu pronađene vještine. Dodajte putanje mapa ili URL-ove ispod kako biste učinili vještine dostupnim.",
"settings.agentBehaviour.skillPaths": "Putanje mapa vještina",
"settings.agentBehaviour.skillUrls": "URL-ovi vještina",
"settings.agentBehaviour.removeSkill.title": "Ukloni vještinu",
"settings.agentBehaviour.removeSkill.confirm":
'Ukloniti vještinu "{{name}}"? Ovo će obrisati datoteke vještine sa diska.',
"settings.agentBehaviour.removeSkill.button": "Ukloni",
"settings.agentBehaviour.instructionFiles": "Dodatne datoteke uputa",
"settings.agentBehaviour.instructionFiles.description": "Putanje do dodatnih datoteka uputa u sistemskom promptu",
"settings.agentBehaviour.mcpEmpty":
Expand Down
4 changes: 4 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/da.ts
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,10 @@ export const dict = {
"Ingen skills fundet. Tilføj skill-mappestier eller URL'er nedenfor for at gøre skills tilgængelige.",
"settings.agentBehaviour.skillPaths": "Skill-mappestier",
"settings.agentBehaviour.skillUrls": "Skill-URL'er",
"settings.agentBehaviour.removeSkill.title": "Fjern færdighed",
"settings.agentBehaviour.removeSkill.confirm":
'Vil du fjerne færdigheden "{{name}}"? Dette vil slette færdighedsfilerne fra disken.',
"settings.agentBehaviour.removeSkill.button": "Fjern",
"settings.agentBehaviour.instructionFiles": "Yderligere instruktionsfiler",
"settings.agentBehaviour.instructionFiles.description": "Stier til yderligere instruktionsfiler i systemprompten",
"settings.agentBehaviour.mcpEmpty":
Expand Down
4 changes: 4 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,10 @@ export const dict = {
"Keine Skills gefunden. Fügen Sie unten Skill-Ordnerpfade oder URLs hinzu, um Skills verfügbar zu machen.",
"settings.agentBehaviour.skillPaths": "Skill-Ordnerpfade",
"settings.agentBehaviour.skillUrls": "Skill-URLs",
"settings.agentBehaviour.removeSkill.title": "Skill entfernen",
"settings.agentBehaviour.removeSkill.confirm":
'Skill "{{name}}" entfernen? Dadurch werden die Skill-Dateien vom Datenträger gelöscht.',
"settings.agentBehaviour.removeSkill.button": "Entfernen",
"settings.agentBehaviour.instructionFiles": "Zusätzliche Anweisungsdateien",
"settings.agentBehaviour.instructionFiles.description": "Pfade zu zusätzlichen Anweisungsdateien im System-Prompt",
"settings.agentBehaviour.mcpEmpty":
Expand Down
3 changes: 3 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
4 changes: 4 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,10 @@ export const dict = {
"No se encontraron habilidades. Agregue rutas de carpetas o URLs abajo para hacer disponibles las habilidades.",
"settings.agentBehaviour.skillPaths": "Rutas de carpetas de habilidades",
"settings.agentBehaviour.skillUrls": "URLs de habilidades",
"settings.agentBehaviour.removeSkill.title": "Eliminar habilidad",
"settings.agentBehaviour.removeSkill.confirm":
'¿Eliminar la habilidad "{{name}}"? Esto borrará los archivos de la habilidad del disco.',
"settings.agentBehaviour.removeSkill.button": "Eliminar",
"settings.agentBehaviour.instructionFiles": "Archivos de instrucciones adicionales",
"settings.agentBehaviour.instructionFiles.description":
"Rutas a archivos de instrucciones adicionales incluidos en el prompt del sistema",
Expand Down
4 changes: 4 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,10 @@ export const dict = {
"Aucune compétence découverte. Ajoutez des chemins de dossiers ou des URLs ci-dessous pour rendre les compétences disponibles.",
"settings.agentBehaviour.skillPaths": "Chemins des dossiers de compétences",
"settings.agentBehaviour.skillUrls": "URLs de compétences",
"settings.agentBehaviour.removeSkill.title": "Supprimer la compétence",
"settings.agentBehaviour.removeSkill.confirm":
'Supprimer la compétence "{{name}}" ? Cela supprimera les fichiers de la compétence du disque.',
"settings.agentBehaviour.removeSkill.button": "Supprimer",
"settings.agentBehaviour.instructionFiles": "Fichiers d'instructions supplémentaires",
"settings.agentBehaviour.instructionFiles.description": "Chemins vers des fichiers d'instructions supplémentaires",
"settings.agentBehaviour.mcpEmpty":
Expand Down
4 changes: 4 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,10 @@ export const dict = {
"スキルが見つかりません。スキルを利用可能にするには、以下にスキルフォルダパスまたはURLを追加してください。",
"settings.agentBehaviour.skillPaths": "スキルフォルダパス",
"settings.agentBehaviour.skillUrls": "スキルURL",
"settings.agentBehaviour.removeSkill.title": "スキルを削除",
"settings.agentBehaviour.removeSkill.confirm":
'スキル "{{name}}" を削除しますか?これにより、ディスクからスキルファイルが削除されます。',
"settings.agentBehaviour.removeSkill.button": "削除",
"settings.agentBehaviour.instructionFiles": "追加の指示ファイル",
"settings.agentBehaviour.instructionFiles.description": "システムプロンプトに含まれる追加の指示ファイルへのパス",
"settings.agentBehaviour.mcpEmpty":
Expand Down
4 changes: 4 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/ko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -956,6 +956,10 @@ export const dict = {
"스킬을 찾을 수 없습니다. 스킬을 사용하려면 아래에 스킬 폴더 경로 또는 URL을 추가하세요.",
"settings.agentBehaviour.skillPaths": "스킬 폴더 경로",
"settings.agentBehaviour.skillUrls": "스킬 URL",
"settings.agentBehaviour.removeSkill.title": "스킬 제거",
"settings.agentBehaviour.removeSkill.confirm":
'스킬 "{{name}}"을(를) 제거하시겠습니까? 디스크에서 스킬 파일이 삭제됩니다.',
"settings.agentBehaviour.removeSkill.button": "제거",
"settings.agentBehaviour.instructionFiles": "추가 지시 파일",
"settings.agentBehaviour.instructionFiles.description": "시스템 프롬프트에 포함되는 추가 지시 파일 경로",
"settings.agentBehaviour.mcpEmpty":
Expand Down
4 changes: 4 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/no.ts
Original file line number Diff line number Diff line change
Expand Up @@ -961,6 +961,10 @@ export const dict = {
"Ingen ferdigheter funnet. Legg til ferdighetsmappestier eller URLer nedenfor for å gjøre ferdigheter tilgjengelige.",
"settings.agentBehaviour.skillPaths": "Ferdighetsmappe-stier",
"settings.agentBehaviour.skillUrls": "Ferdighets-URLer",
"settings.agentBehaviour.removeSkill.title": "Fjern ferdighet",
"settings.agentBehaviour.removeSkill.confirm":
'Vil du fjerne ferdigheten "{{name}}"? Dette vil slette ferdighetsfilene fra disken.',
"settings.agentBehaviour.removeSkill.button": "Fjern",
"settings.agentBehaviour.instructionFiles": "Ekstra instruksjonsfiler",
"settings.agentBehaviour.instructionFiles.description": "Stier til ekstra instruksjonsfiler i systemprompten",
"settings.agentBehaviour.mcpEmpty":
Expand Down
4 changes: 4 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/pl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -961,6 +961,10 @@ export const dict = {
"Nie znaleziono umiejętności. Dodaj ścieżki folderów lub adresy URL poniżej, aby udostępnić umiejętności.",
"settings.agentBehaviour.skillPaths": "Ścieżki folderów umiejętności",
"settings.agentBehaviour.skillUrls": "Adresy URL umiejętności",
"settings.agentBehaviour.removeSkill.title": "Usuń umiejętność",
"settings.agentBehaviour.removeSkill.confirm":
'Usunąć umiejętność "{{name}}"? Spowoduje to usunięcie plików umiejętności z dysku.',
"settings.agentBehaviour.removeSkill.button": "Usuń",
"settings.agentBehaviour.instructionFiles": "Dodatkowe pliki instrukcji",
"settings.agentBehaviour.instructionFiles.description":
"Ścieżki do dodatkowych plików instrukcji w prompcie systemowym",
Expand Down
Loading
Loading