From 07d16dff237b6c4097521214f60da4a149e97433 Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Mon, 16 Mar 2026 11:38:39 +0100 Subject: [PATCH] refactor: move DELETE /skill to dedicated route file 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.). --- packages/kilo-vscode/src/KiloProvider.ts | 2 +- packages/opencode/src/server/routes/skill.ts | 40 +++ packages/opencode/src/server/server.ts | 34 +-- packages/sdk/js/src/v2/gen/sdk.gen.ts | 299 ++++++++++--------- packages/sdk/js/src/v2/gen/types.gen.ts | 106 +++---- packages/sdk/openapi.json | 232 +++++++------- 6 files changed, 365 insertions(+), 348 deletions(-) create mode 100644 packages/opencode/src/server/routes/skill.ts diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index 79d29ac0ea2..34a1a3dbdf5 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -1139,7 +1139,7 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper if (!this.client) return try { const dir = this.getWorkspaceDirectory() - await this.client.app.removeSkill({ location, directory: dir }, { throwOnError: true }) + await this.client.skill.remove({ location, directory: dir }, { throwOnError: true }) } catch (error) { console.error("[Kilo New] KiloProvider: Failed to remove skill:", error) } diff --git a/packages/opencode/src/server/routes/skill.ts b/packages/opencode/src/server/routes/skill.ts new file mode 100644 index 00000000000..fbf49607166 --- /dev/null +++ b/packages/opencode/src/server/routes/skill.ts @@ -0,0 +1,40 @@ +// kilocode_change - new file +import { Hono } from "hono" +import { describeRoute, validator, resolver } from "hono-openapi" +import z from "zod" +import { Skill } from "../../skill/skill" +import { lazy } from "../../util/lazy" +import { errors } from "../error" + +export const SkillRoutes = lazy(() => + new Hono().delete( + "/", + describeRoute({ + summary: "Remove a skill", + description: "Remove a skill by deleting its directory from disk and clearing it from cache.", + operationId: "skill.remove", + 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) + }, + ), +) diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index 1169642058f..80ce513cb09 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -47,6 +47,7 @@ import { HTTPException } from "hono/http-exception" import { errors } from "./error" import { CommitMessageRoutes } from "./routes/commit-message" import { EnhancePromptRoutes } from "./routes/enhance-prompt" // kilocode_change +import { SkillRoutes } from "./routes/skill" // kilocode_change import { QuestionRoutes } from "./routes/question" import { PermissionRoutes } from "./routes/permission" import { GlobalRoutes } from "./routes/global" @@ -268,6 +269,7 @@ export namespace Server { .route("/telemetry", TelemetryRoutes()) // kilocode_change .route("/commit-message", CommitMessageRoutes()) // kilocode_change .route("/enhance-prompt", EnhancePromptRoutes()) // kilocode_change + .route("/skill", SkillRoutes()) // kilocode_change // kilocode_change start - Kilo Gateway routes .route( "/kilo", @@ -500,38 +502,6 @@ 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/sdk/js/src/v2/gen/sdk.gen.ts b/packages/sdk/js/src/v2/gen/sdk.gen.ts index b7ff65c3cf7..60c3805c7ab 100644 --- a/packages/sdk/js/src/v2/gen/sdk.gen.ts +++ b/packages/sdk/js/src/v2/gen/sdk.gen.ts @@ -7,8 +7,6 @@ import type { AppAgentsResponses, AppLogErrors, AppLogResponses, - AppRemoveSkillErrors, - AppRemoveSkillResponses, AppSkillsResponses, Auth as Auth3, AuthRemoveErrors, @@ -170,6 +168,8 @@ import type { SessionUnshareResponses, SessionUpdateErrors, SessionUpdateResponses, + SkillRemoveErrors, + SkillRemoveResponses, SubtaskPartInput, TelemetryCaptureErrors, TelemetryCaptureResponses, @@ -2930,6 +2930,147 @@ export class EnhancePrompt extends HeyApiClient { } } +export class Skill extends HeyApiClient { + /** + * Remove a skill + * + * Remove a skill by deleting its directory from disk and clearing it from cache. + */ + public remove( + 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, + }) + } +} + +export class App extends HeyApiClient { + /** + * List skills + * + * Get a list of all available skills in the OpenCode system. + */ + public skills( + parameters?: { + directory?: string + workspace?: string + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "query", key: "workspace" }, + ], + }, + ], + ) + return (options?.client ?? this.client).get({ + url: "/skill", + ...options, + ...params, + }) + } + + /** + * Write log + * + * Write a log entry to the server logs with specified level and metadata. + */ + public log( + parameters?: { + directory?: string + workspace?: string + service?: string + level?: "debug" | "info" | "error" | "warn" + message?: string + extra?: { + [key: string]: unknown + } + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "query", key: "workspace" }, + { in: "body", key: "service" }, + { in: "body", key: "level" }, + { in: "body", key: "message" }, + { in: "body", key: "extra" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post({ + url: "/log", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * List agents + * + * Get a list of all available AI agents in the OpenCode system. + */ + public agents( + parameters?: { + directory?: string + workspace?: string + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "query", key: "workspace" }, + ], + }, + ], + ) + return (options?.client ?? this.client).get({ + url: "/agent", + ...options, + ...params, + }) + } +} + export class Organization extends HeyApiClient { /** * Update Kilo Gateway organization @@ -4256,145 +4397,6 @@ export class Command extends HeyApiClient { } } -export class App extends HeyApiClient { - /** - * Write log - * - * Write a log entry to the server logs with specified level and metadata. - */ - public log( - parameters?: { - directory?: string - workspace?: string - service?: string - level?: "debug" | "info" | "error" | "warn" - message?: string - extra?: { - [key: string]: unknown - } - }, - options?: Options, - ) { - const params = buildClientParams( - [parameters], - [ - { - args: [ - { in: "query", key: "directory" }, - { in: "query", key: "workspace" }, - { in: "body", key: "service" }, - { in: "body", key: "level" }, - { in: "body", key: "message" }, - { in: "body", key: "extra" }, - ], - }, - ], - ) - return (options?.client ?? this.client).post({ - url: "/log", - ...options, - ...params, - headers: { - "Content-Type": "application/json", - ...options?.headers, - ...params.headers, - }, - }) - } - - /** - * List agents - * - * Get a list of all available AI agents in the OpenCode system. - */ - public agents( - parameters?: { - directory?: string - workspace?: string - }, - options?: Options, - ) { - const params = buildClientParams( - [parameters], - [ - { - args: [ - { in: "query", key: "directory" }, - { in: "query", key: "workspace" }, - ], - }, - ], - ) - return (options?.client ?? this.client).get({ - url: "/agent", - ...options, - ...params, - }) - } - - /** - * 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 - * - * Get a list of all available skills in the OpenCode system. - */ - public skills( - parameters?: { - directory?: string - workspace?: string - }, - options?: Options, - ) { - const params = buildClientParams( - [parameters], - [ - { - args: [ - { in: "query", key: "directory" }, - { in: "query", key: "workspace" }, - ], - }, - ], - ) - return (options?.client ?? this.client).get({ - url: "/skill", - ...options, - ...params, - }) - } -} - export class Lsp extends HeyApiClient { /** * Get LSP status @@ -4579,6 +4581,16 @@ export class KiloClient extends HeyApiClient { return (this._enhancePrompt ??= new EnhancePrompt({ client: this.client })) } + private _skill?: Skill + get skill(): Skill { + return (this._skill ??= new Skill({ client: this.client })) + } + + private _app?: App + get app(): App { + return (this._app ??= new App({ client: this.client })) + } + private _kilo?: Kilo get kilo(): Kilo { return (this._kilo ??= new Kilo({ client: this.client })) @@ -4624,11 +4636,6 @@ export class KiloClient extends HeyApiClient { return (this._command ??= new Command({ client: this.client })) } - private _app?: App - get app(): App { - return (this._app ??= new App({ client: this.client })) - } - private _lsp?: Lsp get lsp(): Lsp { return (this._lsp ??= new Lsp({ client: this.client })) diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index 83dbdbf153b..cc00335cfd2 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -4402,6 +4402,59 @@ export type EnhancePromptEnhanceResponses = { export type EnhancePromptEnhanceResponse = EnhancePromptEnhanceResponses[keyof EnhancePromptEnhanceResponses] +export type SkillRemoveData = { + body?: never + path?: never + query: { + directory?: string + workspace?: string + location: string + } + url: "/skill" +} + +export type SkillRemoveErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type SkillRemoveError = SkillRemoveErrors[keyof SkillRemoveErrors] + +export type SkillRemoveResponses = { + /** + * Skill removed + */ + 200: boolean +} + +export type SkillRemoveResponse = SkillRemoveResponses[keyof SkillRemoveResponses] + +export type AppSkillsData = { + body?: never + path?: never + query?: { + directory?: string + workspace?: string + } + url: "/skill" +} + +export type AppSkillsResponses = { + /** + * List of skills + */ + 200: Array<{ + name: string + description: string + location: string + content: string + }> +} + +export type AppSkillsResponse = AppSkillsResponses[keyof AppSkillsResponses] + export type KiloProfileData = { body?: never path?: never @@ -5483,59 +5536,6 @@ 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 - query?: { - directory?: string - workspace?: string - } - url: "/skill" -} - -export type AppSkillsResponses = { - /** - * List of skills - */ - 200: Array<{ - name: string - description: string - location: string - content: string - }> -} - -export type AppSkillsResponse = AppSkillsResponses[keyof AppSkillsResponses] - export type LspStatusData = { body?: never path?: never diff --git a/packages/sdk/openapi.json b/packages/sdk/openapi.json index 66adf212510..bed3949ac4b 100644 --- a/packages/sdk/openapi.json +++ b/packages/sdk/openapi.json @@ -5372,6 +5372,122 @@ ] } }, + "/skill": { + "delete": { + "operationId": "skill.remove", + "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.skill.remove({\n ...\n})" + } + ] + }, + "get": { + "operationId": "app.skills", + "parameters": [ + { + "in": "query", + "name": "directory", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "workspace", + "schema": { + "type": "string" + } + } + ], + "summary": "List skills", + "description": "Get a list of all available skills in the OpenCode system.", + "responses": { + "200": { + "description": "List of skills", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "location": { + "type": "string" + }, + "content": { + "type": "string" + } + }, + "required": ["name", "description", "location", "content"] + } + } + } + } + } + }, + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.app.skills({\n ...\n})" + } + ] + } + }, "/kilo/profile": { "get": { "operationId": "kilo.profile", @@ -7878,122 +7994,6 @@ ] } }, - "/skill": { - "get": { - "operationId": "app.skills", - "parameters": [ - { - "in": "query", - "name": "directory", - "schema": { - "type": "string" - } - }, - { - "in": "query", - "name": "workspace", - "schema": { - "type": "string" - } - } - ], - "summary": "List skills", - "description": "Get a list of all available skills in the OpenCode system.", - "responses": { - "200": { - "description": "List of skills", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "location": { - "type": "string" - }, - "content": { - "type": "string" - } - }, - "required": ["name", "description", "location", "content"] - } - } - } - } - } - }, - "x-codeSamples": [ - { - "lang": "js", - "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": { "get": { "operationId": "lsp.status",