feat: add ability to remove discovered skills - #7070
Conversation
| .route("/telemetry", TelemetryRoutes()) // kilocode_change | ||
| .route("/commit-message", CommitMessageRoutes()) // kilocode_change | ||
| .route("/enhance-prompt", EnhancePromptRoutes()) // kilocode_change | ||
| .route("/kilocode", KilocodeRoutes()) // kilocode_change |
There was a problem hiding this comment.
I'd prefer kilo, but that is taken by the gateway, and I didn't feel like renaming everything for this change
| export async function remove(location: string) { | ||
| const resolved = path.resolve(location) | ||
| const dir = path.dirname(resolved) | ||
| await rm(dir, { recursive: true, force: true }) |
There was a problem hiding this comment.
CRITICAL: Unvalidated path can delete arbitrary directories
location comes straight from the client and this deletes path.dirname(location) recursively. Any caller can point it at an arbitrary file and remove its parent directory, not just a discovered skill folder. Please resolve the skill from the loaded registry (or otherwise validate the path) before deleting anything on disk.
Code Review SummaryStatus: 3 Issues Found | Recommendation: Address before merge Overview
Fix these issues in Kilo Cloud Issue Details (click to expand)CRITICAL
WARNING
Other Observations (not in diff)No additional issues found outside the diff. Files Reviewed (7 files)
Reviewed by gpt-5.4-20260305 · 726,534 tokens |
…ttings 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.
…oveSkill Move discoveredSkills signal from AgentBehaviourTab into the session context so any component can access session.skills(), session.refreshSkills(), and session.removeSkill(location). removeSkill optimistically removes the skill from the UI signal before sending the message to the extension, so the screen updates immediately.
Add Skill.remove() that deletes the skill directory from disk and mutates the cached Instance.state in-place so subsequent GET /skill calls return the updated list. Add DELETE /skill?location=... server endpoint, regenerate the SDK, and update KiloProvider to call the SDK method instead of deleting files directly from the extension.
Extract the inline DELETE /skill endpoint from server.ts into a dedicated packages/opencode/src/server/routes/skill.ts file, reducing kilo-specific changes in the shared server.ts and minimizing future merge conflicts with upstream. The route is mounted at /skill and uses the same lazy() pattern as other kilo-specific route files (telemetry, enhance-prompt, etc.).
Rename routes/skill.ts to routes/kilocode.ts with KilocodeRoutes export, mounted at /kilocode. This is the single home for all future kilo-specific CLI endpoints, avoiding conflicts with the existing /kilo gateway routes and keeping all kilo changes out of server.ts. SDK: client.kilocode.removeSkill()
The DELETE /kilocode/skill endpoint now returns the updated skills list (Skill.Info[]) instead of a boolean. The extension uses this response directly to update the webview, eliminating the need for a separate GET /skill round-trip that could return stale cached data. Also normalize paths in Skill.remove() with path.resolve() to ensure location strings match regardless of path format differences.
The DELETE endpoint was returning data that somehow rendered as empty rows in the webview. Simplify the approach: - Webview optimistically removes the skill from its signal immediately - Extension fires DELETE to the backend (deletes from disk + cache) - Extension invalidates cachedSkillsMessage so next tab visit fetches fresh data - No second skillsLoaded message is sent after removal, avoiding the stale data overwrite that caused the UI corruption
…th query params File paths as query parameters can fail due to URL encoding issues. Switch to POST /kilocode/skill/remove with the location in the JSON request body, which avoids encoding problems entirely. Also log the SDK error response to aid debugging.
3874de6 to
cfe4e8c
Compare
…sync webview on failure
feat: add ability to remove discovered skills
feat: add ability to remove discovered skills
Summary
vscode.workspace.fs.deleteand refreshes the skills listChanges
messages.ts: NewRemoveSkillMessagetype added toWebviewMessageunionen.ts: i18n strings for the removal confirmation dialogAgentBehaviourTab.tsx: Remove button + confirmation dialog on each discovered skill rowKiloProvider.ts:handleRemoveSkillhandler that deletes the skill directory and re-fetches skills