diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index fe9143a3f09..79d29ac0ea2 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -1133,15 +1133,15 @@ 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. + * Remove a skill via the CLI backend (deletes from disk + clears cache), then refresh. */ private async handleRemoveSkill(location: string): Promise { - const dir = path.dirname(location) + if (!this.client) return try { - await vscode.workspace.fs.delete(vscode.Uri.file(dir), { recursive: true }) + const dir = this.getWorkspaceDirectory() + await this.client.app.removeSkill({ location, directory: dir }, { throwOnError: true }) } catch (error) { - console.error("[Kilo New] KiloProvider: Failed to delete skill directory:", dir, error) + console.error("[Kilo New] KiloProvider: Failed to remove skill:", error) } this.cachedSkillsMessage = null await this.fetchAndSendSkills() diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index d37112823a1..1169642058f 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -500,6 +500,38 @@ export namespace Server { return c.json(skills) }, ) + // kilocode_change start + .delete( + "/skill", + describeRoute({ + summary: "Remove a skill", + description: "Remove a skill by deleting its directory from disk and clearing it from cache.", + operationId: "app.removeSkill", + responses: { + 200: { + description: "Skill removed", + content: { + "application/json": { + schema: resolver(z.boolean()), + }, + }, + }, + ...errors(400), + }, + }), + validator( + "query", + z.object({ + location: z.string(), + }), + ), + async (c) => { + const { location } = c.req.valid("query") + await Skill.remove(location) + return c.json(true) + }, + ) + // kilocode_change end .get( "/lsp", describeRoute({ diff --git a/packages/opencode/src/skill/skill.ts b/packages/opencode/src/skill/skill.ts index d0b4eddeb87..aebac03faf4 100644 --- a/packages/opencode/src/skill/skill.ts +++ b/packages/opencode/src/skill/skill.ts @@ -1,6 +1,7 @@ import z from "zod" import path from "path" import os from "os" +import { rm } from "fs/promises" import { Config } from "../config/config" import { Instance } from "../project/instance" import { NamedError } from "@opencode-ai/util/error" @@ -213,4 +214,17 @@ export namespace Skill { export async function dirs() { return state().then((x) => x.dirs) } + + // kilocode_change start + export async function remove(location: string) { + const dir = path.dirname(location) + await rm(dir, { recursive: true, force: true }) + const s = await state() + const name = Object.keys(s.skills).find((k) => s.skills[k].location === location) + if (name) { + delete s.skills[name] + s.dirs = s.dirs.filter((d) => d !== dir) + } + } + // kilocode_change end } diff --git a/packages/sdk/js/src/v2/gen/sdk.gen.ts b/packages/sdk/js/src/v2/gen/sdk.gen.ts index 9104c813c2e..b7ff65c3cf7 100644 --- a/packages/sdk/js/src/v2/gen/sdk.gen.ts +++ b/packages/sdk/js/src/v2/gen/sdk.gen.ts @@ -7,6 +7,8 @@ import type { AppAgentsResponses, AppLogErrors, AppLogResponses, + AppRemoveSkillErrors, + AppRemoveSkillResponses, AppSkillsResponses, Auth as Auth3, AuthRemoveErrors, @@ -4330,6 +4332,38 @@ export class App extends HeyApiClient { }) } + /** + * Remove a skill + * + * Remove a skill by deleting its directory from disk and clearing it from cache. + */ + public removeSkill( + parameters: { + directory?: string + workspace?: string + location: string + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "query", key: "workspace" }, + { in: "query", key: "location" }, + ], + }, + ], + ) + return (options?.client ?? this.client).delete({ + url: "/skill", + ...options, + ...params, + }) + } + /** * List skills * diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index 5c724d3621f..83dbdbf153b 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -5483,6 +5483,35 @@ export type AppAgentsResponses = { export type AppAgentsResponse = AppAgentsResponses[keyof AppAgentsResponses] +export type AppRemoveSkillData = { + body?: never + path?: never + query: { + directory?: string + workspace?: string + location: string + } + url: "/skill" +} + +export type AppRemoveSkillErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type AppRemoveSkillError = AppRemoveSkillErrors[keyof AppRemoveSkillErrors] + +export type AppRemoveSkillResponses = { + /** + * Skill removed + */ + 200: boolean +} + +export type AppRemoveSkillResponse = AppRemoveSkillResponses[keyof AppRemoveSkillResponses] + export type AppSkillsData = { body?: never path?: never diff --git a/packages/sdk/openapi.json b/packages/sdk/openapi.json index 45dd0752210..66adf212510 100644 --- a/packages/sdk/openapi.json +++ b/packages/sdk/openapi.json @@ -7935,6 +7935,63 @@ "source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.app.skills({\n ...\n})" } ] + }, + "delete": { + "operationId": "app.removeSkill", + "parameters": [ + { + "in": "query", + "name": "directory", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "workspace", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "location", + "schema": { + "type": "string" + }, + "required": true + } + ], + "summary": "Remove a skill", + "description": "Remove a skill by deleting its directory from disk and clearing it from cache.", + "responses": { + "200": { + "description": "Skill removed", + "content": { + "application/json": { + "schema": { + "type": "boolean" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestError" + } + } + } + } + }, + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.app.removeSkill({\n ...\n})" + } + ] } }, "/lsp": {