From 3c96a7c8d3cb5975df331f87d726749d82389006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Catriel=20M=C3=BCller?= Date: Thu, 28 May 2026 14:20:13 -0300 Subject: [PATCH] refactor: fix merge main --- .../projects/terminal/GhosttyTerminal.tsx | 47 +- packages/opencode/src/cli/cmd/tui/thread.ts | 9 +- packages/opencode/src/config/mcp.ts | 10 +- .../server/httpapi/groups/agent-builder.ts | 77 ++ .../server/httpapi/groups/config-console.ts | 188 +++ .../server/httpapi/handlers/agent-builder.ts | 43 + .../server/httpapi/handlers/config-console.ts | 153 +++ .../src/kilocode/server/httpapi/instance.ts | 12 + .../src/kilocode/server/httpapi/public.ts | 27 +- .../src/kilocode/server/httpapi/server.ts | 4 + .../kilocode/server/routes/agent-builder.ts | 3 +- packages/opencode/src/pty/index.ts | 2 +- .../src/server/routes/instance/httpapi/api.ts | 4 + packages/opencode/test/cli/tui/thread.test.ts | 2 + .../kilocode/server/config-overlay.test.ts | 4 +- packages/sdk/js/src/v2/gen/sdk.gen.ts | 465 ++++++- packages/sdk/js/src/v2/gen/types.gen.ts | 407 +++++- packages/sdk/openapi.json | 1220 ++++++++++++++++- 18 files changed, 2640 insertions(+), 37 deletions(-) create mode 100644 packages/opencode/src/kilocode/server/httpapi/groups/agent-builder.ts create mode 100644 packages/opencode/src/kilocode/server/httpapi/groups/config-console.ts create mode 100644 packages/opencode/src/kilocode/server/httpapi/handlers/agent-builder.ts create mode 100644 packages/opencode/src/kilocode/server/httpapi/handlers/config-console.ts diff --git a/packages/kilo-console/src/routes/projects/terminal/GhosttyTerminal.tsx b/packages/kilo-console/src/routes/projects/terminal/GhosttyTerminal.tsx index c1df440817..187c21c0f1 100644 --- a/packages/kilo-console/src/routes/projects/terminal/GhosttyTerminal.tsx +++ b/packages/kilo-console/src/routes/projects/terminal/GhosttyTerminal.tsx @@ -70,12 +70,44 @@ function rect(view: View, x: number, y: number, w: number, h: number) { view.ctx.fillRect(left, top, right - left, bottom - top) } +function sextant(view: View, mask: number, x: number, y: number, w: number, h: number) { + const sw = w / 2 + const sh = h / 3 + + for (const n of [1, 2, 3, 4, 5, 6]) { + if (!(mask & (1 << (n - 1)))) continue + const dx = n % 2 === 1 ? 0 : sw + const dy = Math.floor((n - 1) / 2) * sh + rect(view, x + dx, y + dy, sw, sh) + } +} + function fill(view: View, cp: number, x: number, y: number, w: number, h: number) { const ew = w / 8 const eh = h / 8 const hw = w / 2 const hh = h / 2 + if (cp === 0x1fb01) { + sextant(view, 0b000010, x, y, w, h) + return true + } + + if (cp === 0x1fb0f) { + sextant(view, 0b010000, x, y, w, h) + return true + } + + if (cp === 0x1fb2c) { + sextant(view, 0b101111, x, y, w, h) + return true + } + + if (cp === 0x1fb3a) { + sextant(view, 0b111101, x, y, w, h) + return true + } + if (cp >= 0x2581 && cp <= 0x2587) { const n = cp - 0x2580 rect(view, x, y + h - eh * n, w, eh * n) @@ -187,9 +219,11 @@ function patch(renderer: Terminal["renderer"]) { view.renderCellText = (cell, x, y, over) => { if ( !(cell.flags & CellFlags.INVISIBLE) && - cell.grapheme_len === 0 && - cell.codepoint >= 0x2580 && - cell.codepoint <= 0x259f + ((cell.codepoint >= 0x2580 && cell.codepoint <= 0x259f) || + cell.codepoint === 0x1fb01 || + cell.codepoint === 0x1fb0f || + cell.codepoint === 0x1fb2c || + cell.codepoint === 0x1fb3a) ) { const w = view.metrics.width * cell.width const h = view.metrics.height @@ -244,7 +278,8 @@ export function GhosttyTerminal(props: { query: Query; pty: string; active?: boo cols: 100, rows: 30, cursorBlink: true, - fontFamily: "'FiraCode Nerd Font', 'FiraCode Nerd Font Mono', 'Fira Code', Menlo, Monaco, 'Courier New', monospace", + fontFamily: + "'FiraCode Nerd Font', 'FiraCode Nerd Font Mono', 'Fira Code', Menlo, Monaco, 'Courier New', monospace", fontSize: Math.max(14, px(host, "--font-size-base", 14)), scrollback: 5000, theme: theme(host), @@ -323,9 +358,7 @@ export function GhosttyTerminal(props: { query: Query; pty: string; active?: boo return (
- - {(msg) =>
{msg()}
} -
+ {(msg) =>
{msg()}
}
) } diff --git a/packages/opencode/src/cli/cmd/tui/thread.ts b/packages/opencode/src/cli/cmd/tui/thread.ts index 5d45570b4a..996ac084e9 100644 --- a/packages/opencode/src/cli/cmd/tui/thread.ts +++ b/packages/opencode/src/cli/cmd/tui/thread.ts @@ -89,7 +89,7 @@ export function resolveThreadDirectory(project?: string, envPWD = process.env.PW const root = envPWD && Filesystem.resolve(envPWD) === real ? Filesystem.resolve(envPWD) : real // kilocode_change end if (project) return Filesystem.resolve(path.isAbsolute(project) ? project : path.join(root, project)) - return real + return real // kilocode_change } export const TuiThreadCommand = cmd({ @@ -363,7 +363,7 @@ export const TuiThreadCommand = cmd({ try { await validateSession({ - url: transport.url, + url: transport.url, // kilocode_change sessionID: args.session, directory: cwd, fetch: transport.fetch, @@ -398,9 +398,8 @@ export const TuiThreadCommand = cmd({ } // kilocode_change end - await start({ - // kilocode_change - url: transport.url, + await start({ // kilocode_change + url: transport.url, // kilocode_change async onSnapshot() { const tui = writeHeapSnapshot("tui.heapsnapshot") const server = await client.call("snapshot", undefined) diff --git a/packages/opencode/src/config/mcp.ts b/packages/opencode/src/config/mcp.ts index f72b7c0ab4..3f7d2f4657 100644 --- a/packages/opencode/src/config/mcp.ts +++ b/packages/opencode/src/config/mcp.ts @@ -31,8 +31,14 @@ const LocalInput = Schema.Struct({ }) const normalizeLocal = (input: Schema.Schema.Type): Schema.Schema.Type => { - const { env, environment, ...rest } = input - return { ...rest, environment: environment ?? env } + const env = input.environment ?? input.env + return { + type: input.type, + command: input.command, + ...(env === undefined ? {} : { environment: env }), + ...("enabled" in input ? { enabled: input.enabled } : {}), + ...("timeout" in input ? { timeout: input.timeout } : {}), + } } export const Local = LocalInput.pipe( diff --git a/packages/opencode/src/kilocode/server/httpapi/groups/agent-builder.ts b/packages/opencode/src/kilocode/server/httpapi/groups/agent-builder.ts new file mode 100644 index 0000000000..bc2c9ad258 --- /dev/null +++ b/packages/opencode/src/kilocode/server/httpapi/groups/agent-builder.ts @@ -0,0 +1,77 @@ +import { Authorization } from "@/server/routes/instance/httpapi/middleware/authorization" +import { InstanceContextMiddleware } from "@/server/routes/instance/httpapi/middleware/instance-context" +import { WorkspaceRoutingMiddleware } from "@/server/routes/instance/httpapi/middleware/workspace-routing" +import { described } from "@/server/routes/instance/httpapi/groups/metadata" +import { Schema } from "effect" +import { HttpApi, HttpApiEndpoint, HttpApiError, HttpApiGroup, OpenApi } from "effect/unstable/httpapi" + +const Scope = Schema.Literals(["global", "project"]) +const Mode = Schema.Literals(["primary", "subagent", "all"]) +export const AgentBuilderID = Schema.String +const Body = { + scope: Schema.optional(Scope), + description: Schema.optional(Schema.String), + mode: Schema.optional(Mode), + model: Schema.optional(Schema.String), + color: Schema.optional(Schema.String), + steps: Schema.optional(Schema.Number), + tools: Schema.optional(Schema.Array(Schema.String)), + permission: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)), + prompt: Schema.String, +} + +export const AgentBuilderInput = Schema.Struct({ id: AgentBuilderID, ...Body }) +export const AgentBuilderSaveInput = Schema.Struct({ id: Schema.optional(AgentBuilderID), ...Body }) +export const AgentBuilderOutput = Schema.Struct({ + id: AgentBuilderID, + scope: Scope, + path: Schema.String, + markdown: Schema.String, +}) + +export const AgentBuilderPaths = { + preview: "/agent-builder/preview", + save: "/agent-builder/:id", +} as const + +export const AgentBuilderApi = HttpApi.make("agent-builder") + .add( + HttpApiGroup.make("agent-builder") + .add( + HttpApiEndpoint.post("preview", AgentBuilderPaths.preview, { + payload: AgentBuilderInput, + success: described(AgentBuilderOutput, "Agent markdown preview"), + error: HttpApiError.BadRequest, + }).annotateMerge( + OpenApi.annotations({ + identifier: "agentBuilder.preview", + summary: "Preview agent markdown", + description: + "Validate an agent builder payload and return the canonical agent markdown without writing it.", + }), + ), + HttpApiEndpoint.put("save", AgentBuilderPaths.save, { + params: { id: AgentBuilderID }, + payload: AgentBuilderSaveInput, + success: described(AgentBuilderOutput, "Saved agent markdown"), + error: HttpApiError.BadRequest, + }).annotateMerge( + OpenApi.annotations({ + identifier: "agentBuilder.save", + summary: "Save agent markdown", + description: "Save an agent builder payload as a canonical agent markdown file.", + }), + ), + ) + .annotateMerge(OpenApi.annotations({ title: "agent-builder", description: "Kilo agent builder routes." })) + .middleware(InstanceContextMiddleware) + .middleware(WorkspaceRoutingMiddleware) + .middleware(Authorization), + ) + .annotateMerge( + OpenApi.annotations({ + title: "kilo HttpApi", + version: "0.0.1", + description: "Kilo HttpApi surface.", + }), + ) diff --git a/packages/opencode/src/kilocode/server/httpapi/groups/config-console.ts b/packages/opencode/src/kilocode/server/httpapi/groups/config-console.ts new file mode 100644 index 0000000000..0aa0d759c2 --- /dev/null +++ b/packages/opencode/src/kilocode/server/httpapi/groups/config-console.ts @@ -0,0 +1,188 @@ +import { Config } from "@/config/config" +import { ConfigPlugin } from "@/config/plugin" +import { Authorization } from "@/server/routes/instance/httpapi/middleware/authorization" +import { InstanceContextMiddleware } from "@/server/routes/instance/httpapi/middleware/instance-context" +import { WorkspaceRoutingMiddleware } from "@/server/routes/instance/httpapi/middleware/workspace-routing" +import { described } from "@/server/routes/instance/httpapi/groups/metadata" +import { Schema } from "effect" +import { HttpApi, HttpApiEndpoint, HttpApiError, HttpApiGroup, OpenApi } from "effect/unstable/httpapi" + +const Scope = Schema.Literals(["global", "project"]) +const Origin = Schema.Literals(["project", "global", "system", "default"]) +const UnknownRecord = Schema.Record(Schema.String, Schema.Unknown) +const ModelRef = Schema.Struct({ providerID: Schema.String, modelID: Schema.String }) +const Resolved = Schema.Struct({ + key: Schema.String, + path: Schema.Array(Schema.String), + value: Schema.optional(Schema.Unknown), + global: Schema.optional(Schema.Unknown), + local: Schema.optional(Schema.Unknown), + source: Origin, + inherited: Schema.Boolean, + overridden: Schema.Boolean, + editable: Schema.Boolean, + reason: Schema.optional(Schema.String), +}) +const Source = Schema.Struct({ + order: Schema.Number, + kind: Schema.String, + scope: Schema.String, + label: Schema.String, + source: Schema.String, + path: Schema.optional(Schema.String), + exists: Schema.Boolean, + editable: Schema.Boolean, + reason: Schema.optional(Schema.String), +}) + +export const ConfigOverlayQuery = Schema.Struct({ scope: Schema.optional(Scope) }) +export const ConfigOverlayPatch = Schema.Struct({ + scope: Schema.optional(Scope), + set: Schema.optional(UnknownRecord), + unset: Schema.optional(Schema.Array(Schema.Array(Schema.String))), +}) +export const ConfigOverlayResponse = Schema.Struct({ + scope: Scope, + effective: Config.Info, + global: Config.Info, + project: Config.Info, + sources: Schema.Array(Source), + targets: Schema.Struct({ + global: Schema.optional(Schema.String), + project: Schema.optional(Schema.String), + active: Schema.optional(Schema.String), + }), + fields: Schema.Record(Schema.String, Resolved), + collections: Schema.Record(Schema.String, Schema.Array(Resolved)), +}).annotate({ identifier: "ConfigOverlayResponse" }) +export const ConfigSourcesResponse = Schema.Struct({ sources: Schema.Array(Source) }).annotate({ + identifier: "ConfigSourcesResponse", +}) +export const ConfigModelStatePatch = Schema.Struct({ favorite: Schema.optional(Schema.Array(ModelRef)) }) +export const ConfigModelStateResponse = Schema.Struct({ + model: Schema.Record(Schema.String, ModelRef), + recent: Schema.Array(ModelRef), + favorite: Schema.Array(ModelRef), + variant: Schema.Record(Schema.String, Schema.String), +}).annotate({ identifier: "ConfigModelStateResponse" }) + +export const TuiConfigQuery = Schema.Struct({ scope: Schema.optional(Scope) }) +const TuiConfigShape = { + $schema: Schema.optional(Schema.String), + theme: Schema.optional(Schema.String), + keybinds: Schema.optional(Schema.Record(Schema.String, Schema.UndefinedOr(Schema.String))), + plugin: Schema.optional(Schema.Array(ConfigPlugin.Spec)), + plugin_enabled: Schema.optional(Schema.Record(Schema.String, Schema.Boolean)), + scroll_speed: Schema.optional(Schema.Number), + scroll_acceleration: Schema.optional(Schema.Struct({ enabled: Schema.Boolean })), + diff_style: Schema.optional(Schema.Literals(["auto", "stacked"])), + mouse: Schema.optional(Schema.Boolean), +} +export const TuiConfigResponse = Schema.Struct(TuiConfigShape).annotate({ identifier: "TuiConfigGetResponse" }) +export const TuiConfigPatch = Schema.Struct(TuiConfigShape) + +export const ConfigConsolePaths = { + sources: "/config/sources", + effective: "/config/effective", + overlay: "/config/overlay", + modelState: "/config/model-state", + tuiConfig: "/tui/config", +} as const + +export const ConfigConsoleApi = HttpApi.make("config-console") + .add( + HttpApiGroup.make("config-console") + .add( + HttpApiEndpoint.get("overlay", ConfigConsolePaths.overlay, { + query: ConfigOverlayQuery, + success: described(ConfigOverlayResponse, "Resolved config overlay"), + }).annotateMerge( + OpenApi.annotations({ + identifier: "config.overlay", + summary: "Get config overlay", + description: + "Resolve global, project, and effective config values with source metadata for inheritance-aware settings UI.", + }), + ), + HttpApiEndpoint.get("sources", ConfigConsolePaths.sources, { + success: described(ConfigSourcesResponse, "Config source inventory"), + }).annotateMerge( + OpenApi.annotations({ + identifier: "config.sources", + summary: "List config sources", + description: "List config source metadata in load order without exposing config contents or secrets.", + }), + ), + HttpApiEndpoint.get("effective", ConfigConsolePaths.effective, { + success: described(Config.Info, "Effective config info"), + }).annotateMerge( + OpenApi.annotations({ + identifier: "config.effective", + summary: "Get effective configuration", + description: "Retrieve effective config for the current instance directory.", + }), + ), + HttpApiEndpoint.patch("overlayUpdate", ConfigConsolePaths.overlay, { + payload: ConfigOverlayPatch, + success: described(Config.Info, "Effective configuration after patch"), + }).annotateMerge( + OpenApi.annotations({ + identifier: "config.overlayUpdate", + summary: "Patch config overlay", + description: + "Apply a minimal global or project config patch, including unset paths for reverting local overrides.", + }), + ), + HttpApiEndpoint.get("modelState", ConfigConsolePaths.modelState, { + success: described(ConfigModelStateResponse, "Model state"), + }).annotateMerge( + OpenApi.annotations({ + identifier: "config.modelState", + summary: "Get model state", + description: "Retrieve TUI-compatible recent and favorite model selections.", + }), + ), + HttpApiEndpoint.patch("modelStateUpdate", ConfigConsolePaths.modelState, { + payload: ConfigModelStatePatch, + success: described(ConfigModelStateResponse, "Updated model state"), + }).annotateMerge( + OpenApi.annotations({ + identifier: "config.modelStateUpdate", + summary: "Update model state", + description: "Patch TUI-compatible model selections shared with Kilo Console.", + }), + ), + HttpApiEndpoint.get("tuiConfigGet", ConfigConsolePaths.tuiConfig, { + success: described(TuiConfigResponse, "Effective TUI configuration"), + }).annotateMerge( + OpenApi.annotations({ + identifier: "tui.config.get", + summary: "Get TUI configuration", + description: "Retrieve the effective TUI configuration for the current instance directory.", + }), + ), + HttpApiEndpoint.patch("tuiConfigUpdate", ConfigConsolePaths.tuiConfig, { + query: TuiConfigQuery, + payload: TuiConfigPatch, + success: described(TuiConfigResponse, "Effective TUI configuration after the update"), + error: HttpApiError.BadRequest, + }).annotateMerge( + OpenApi.annotations({ + identifier: "tui.config.update", + summary: "Update TUI configuration", + description: "Patch global or project TUI configuration and return the effective TUI configuration.", + }), + ), + ) + .annotateMerge(OpenApi.annotations({ title: "config-console", description: "Kilo Console config routes." })) + .middleware(InstanceContextMiddleware) + .middleware(WorkspaceRoutingMiddleware) + .middleware(Authorization), + ) + .annotateMerge( + OpenApi.annotations({ + title: "kilo HttpApi", + version: "0.0.1", + description: "Kilo HttpApi surface.", + }), + ) diff --git a/packages/opencode/src/kilocode/server/httpapi/handlers/agent-builder.ts b/packages/opencode/src/kilocode/server/httpapi/handlers/agent-builder.ts new file mode 100644 index 0000000000..71a062bba3 --- /dev/null +++ b/packages/opencode/src/kilocode/server/httpapi/handlers/agent-builder.ts @@ -0,0 +1,43 @@ +import * as InstanceState from "@/effect/instance-state" +import { AgentBuilder } from "@/kilocode/agent/builder" +import { InstanceStore } from "@/project/instance-store" +import { InstanceHttpApi } from "@/server/routes/instance/httpapi/api" +import { Effect } from "effect" +import { HttpApiBuilder } from "effect/unstable/httpapi" +import { AgentBuilderID, AgentBuilderInput, AgentBuilderSaveInput } from "../groups/agent-builder" + +export const agentBuilderHandlers = HttpApiBuilder.group(InstanceHttpApi, "agent-builder", (handlers) => + Effect.gen(function* () { + const store = yield* InstanceStore.Service + + const preview = Effect.fn("AgentBuilderHttpApi.preview")(function* (ctx: { + payload: typeof AgentBuilderInput.Type + }) { + const instance = yield* InstanceState.context + return yield* Effect.promise(() => AgentBuilder.preview(instance, normalize(ctx.payload))) + }) + + const save = Effect.fn("AgentBuilderHttpApi.save")(function* (ctx: { + params: { id: typeof AgentBuilderID.Type } + payload: typeof AgentBuilderSaveInput.Type + }) { + const instance = yield* InstanceState.context + const input = normalize({ ...ctx.payload, id: ctx.params.id }) + const output = yield* Effect.promise(() => AgentBuilder.save(instance, input)) + yield* store.dispose(instance) + return output + }) + + return handlers.handle("preview", preview).handle("save", save) + }), +) + +function normalize(input: typeof AgentBuilderInput.Type): AgentBuilder.Input { + return { + ...input, + scope: input.scope ?? "project", + mode: input.mode ?? "primary", + prompt: input.prompt.trim(), + tools: input.tools ? [...input.tools] : undefined, + } +} diff --git a/packages/opencode/src/kilocode/server/httpapi/handlers/config-console.ts b/packages/opencode/src/kilocode/server/httpapi/handlers/config-console.ts new file mode 100644 index 0000000000..2fe2b20c24 --- /dev/null +++ b/packages/opencode/src/kilocode/server/httpapi/handlers/config-console.ts @@ -0,0 +1,153 @@ +import { Account } from "@/account/account" +import { Auth } from "@/auth" +import { Config } from "@/config/config" +import * as InstanceState from "@/effect/instance-state" +import { KilocodeConfigOverlay } from "@/kilocode/config/overlay" +import { KilocodeConfigSources } from "@/kilocode/config/sources" +import { KilocodeModelState } from "@/kilocode/config/model-state" +import { KilocodeTuiConfig } from "@/kilocode/tui/config" +import { InstanceHttpApi } from "@/server/routes/instance/httpapi/api" +import { Effect, Option } from "effect" +import { HttpApiBuilder } from "effect/unstable/httpapi" +import { + ConfigModelStatePatch, + ConfigOverlayPatch, + ConfigOverlayQuery, + TuiConfigPatch, + TuiConfigQuery, +} from "../groups/config-console" + +export const configConsoleHandlers = HttpApiBuilder.group(InstanceHttpApi, "config-console", (handlers) => + Effect.gen(function* () { + const config = yield* Config.Service + const auth = yield* Auth.Service + const account = yield* Account.Service + + const overlay = Effect.fn("ConfigConsoleHttpApi.overlay")(function* (ctx: { + query: typeof ConfigOverlayQuery.Type + }) { + const instance = yield* InstanceState.context + const all = yield* auth.all().pipe(Effect.orElseSucceed(() => ({}))) + const active = yield* account.active().pipe( + Effect.map(Option.getOrUndefined), + Effect.orElseSucceed(() => undefined), + ) + const [base, global, sources] = yield* Effect.all( + [ + config.get(), + config.getGlobal(), + Effect.promise(() => + KilocodeConfigSources.list({ + directory: instance.directory, + worktree: instance.worktree, + auth: all, + account: active, + }), + ), + ], + { concurrency: 3 }, + ) + return yield* Effect.promise(() => + KilocodeConfigOverlay.resolve({ + directory: instance.directory, + worktree: instance.worktree, + scope: ctx.query.scope ?? "project", + effective: base, + global, + sources: sources.sources, + }), + ) + }) + + const overlayUpdate = Effect.fn("ConfigConsoleHttpApi.overlayUpdate")(function* (ctx: { + payload: typeof ConfigOverlayPatch.Type + }) { + const body = { + ...ctx.payload, + scope: ctx.payload.scope ?? "project", + set: ctx.payload.set ? { ...ctx.payload.set } : undefined, + unset: ctx.payload.unset?.map((item) => [...item]), + } + const patch = KilocodeConfigOverlay.patch(body) + if (Object.keys(patch).length === 0) { + if (body.scope === "global") return yield* config.getGlobal() + return yield* config.get() + } + if (body.scope === "global") return (yield* config.updateGlobal(patch)).info + yield* config.update(patch) + return yield* config.get() + }) + + const sources = Effect.fn("ConfigConsoleHttpApi.sources")(function* () { + const instance = yield* InstanceState.context + const all = yield* auth.all().pipe(Effect.orElseSucceed(() => ({}))) + const active = yield* account.active().pipe( + Effect.map(Option.getOrUndefined), + Effect.orElseSucceed(() => undefined), + ) + return yield* Effect.promise(() => + KilocodeConfigSources.list({ + directory: instance.directory, + worktree: instance.worktree, + auth: all, + account: active, + }), + ) + }) + + const effective = Effect.fn("ConfigConsoleHttpApi.effective")(function* () { + return yield* config.get() + }) + + const modelState = Effect.fn("ConfigConsoleHttpApi.modelState")(function* () { + return yield* Effect.promise(() => KilocodeModelState.get()) + }) + + const modelStateUpdate = Effect.fn("ConfigConsoleHttpApi.modelStateUpdate")(function* (ctx: { + payload: typeof ConfigModelStatePatch.Type + }) { + return yield* Effect.promise(() => + KilocodeModelState.update({ favorite: ctx.payload.favorite?.map((item) => ({ ...item })) }), + ) + }) + + const tuiConfigGet = Effect.fn("ConfigConsoleHttpApi.tuiConfigGet")(function* () { + const instance = yield* InstanceState.context + return yield* Effect.promise(() => KilocodeTuiConfig.get({ directory: instance.directory })) + }) + + const tuiConfigUpdate = Effect.fn("ConfigConsoleHttpApi.tuiConfigUpdate")(function* (ctx: { + query: typeof TuiConfigQuery.Type + payload: typeof TuiConfigPatch.Type + }) { + const instance = yield* InstanceState.context + const patch = { + ...ctx.payload, + keybinds: ctx.payload.keybinds ? { ...ctx.payload.keybinds } : undefined, + plugin: ctx.payload.plugin?.map((item) => { + if (!Array.isArray(item)) return item + return [item[0], { ...item[1] }] as [string, { readonly [x: string]: unknown }] + }), + plugin_enabled: ctx.payload.plugin_enabled ? { ...ctx.payload.plugin_enabled } : undefined, + } + return yield* Effect.promise(() => + KilocodeTuiConfig.update({ + directory: instance.directory, + worktree: instance.worktree, + scope: ctx.query.scope ?? "project", + patch, + }), + ) + }) + + return handlers + .handle("overlay", overlay) + .handle("overlayUpdate", overlayUpdate) + .handle("sources", sources) + .handle("effective", effective) + .handle("modelState", modelState) + .handle("modelStateUpdate", modelStateUpdate) + .handle("tuiConfigGet", tuiConfigGet) + .handle("tuiConfigUpdate", tuiConfigUpdate) + }), +) diff --git a/packages/opencode/src/kilocode/server/httpapi/instance.ts b/packages/opencode/src/kilocode/server/httpapi/instance.ts index 2e823ed1e4..5d9f3eddfe 100644 --- a/packages/opencode/src/kilocode/server/httpapi/instance.ts +++ b/packages/opencode/src/kilocode/server/httpapi/instance.ts @@ -1,6 +1,8 @@ import type { Context } from "effect" import type { Hono } from "hono" +import { AgentBuilderPaths } from "./groups/agent-builder" import { BackgroundProcessPaths } from "./groups/background-process" +import { ConfigConsolePaths } from "./groups/config-console" import { IndexingPaths } from "./groups/indexing" import { KiloGatewayPaths } from "./groups/kilo-gateway" import { KilocodePaths } from "./groups/kilocode" @@ -13,12 +15,22 @@ import { TelemetryPaths } from "./groups/telemetry" type Handler = (request: Request, context: Context.Context) => Promise export function register(app: Hono, handler: Handler, context: Context.Context) { + app.post(AgentBuilderPaths.preview, (c) => handler(c.req.raw, context)) + app.put(AgentBuilderPaths.save, (c) => handler(c.req.raw, context)) app.get(BackgroundProcessPaths.list, (c) => handler(c.req.raw, context)) app.get(BackgroundProcessPaths.get, (c) => handler(c.req.raw, context)) app.get(BackgroundProcessPaths.logs, (c) => handler(c.req.raw, context)) app.post(BackgroundProcessPaths.stop, (c) => handler(c.req.raw, context)) app.post(BackgroundProcessPaths.restart, (c) => handler(c.req.raw, context)) app.post(BackgroundProcessPaths.stopSession, (c) => handler(c.req.raw, context)) + app.get(ConfigConsolePaths.sources, (c) => handler(c.req.raw, context)) + app.get(ConfigConsolePaths.effective, (c) => handler(c.req.raw, context)) + app.get(ConfigConsolePaths.overlay, (c) => handler(c.req.raw, context)) + app.patch(ConfigConsolePaths.overlay, (c) => handler(c.req.raw, context)) + app.get(ConfigConsolePaths.modelState, (c) => handler(c.req.raw, context)) + app.patch(ConfigConsolePaths.modelState, (c) => handler(c.req.raw, context)) + app.get(ConfigConsolePaths.tuiConfig, (c) => handler(c.req.raw, context)) + app.patch(ConfigConsolePaths.tuiConfig, (c) => handler(c.req.raw, context)) app.post("/permission/allow-everything", (c) => handler(c.req.raw, context)) app.post("/enhance-prompt", (c) => handler(c.req.raw, context)) app.post("/commit-message", (c) => handler(c.req.raw, context)) diff --git a/packages/opencode/src/kilocode/server/httpapi/public.ts b/packages/opencode/src/kilocode/server/httpapi/public.ts index bd3fdd7f6d..739e23f9c3 100644 --- a/packages/opencode/src/kilocode/server/httpapi/public.ts +++ b/packages/opencode/src/kilocode/server/httpapi/public.ts @@ -12,21 +12,18 @@ type Response = { description?: string } +type Operation = { + requestBody?: { + content?: Record + } + responses?: Record +} + type Spec = { components?: { schemas?: Record } - paths?: Record< - string, - { - post?: { - requestBody?: { - content?: Record - } - responses?: Record - } - } - > + paths?: Record>> } export function matchLegacyKiloOpenApi(input: Record) { @@ -40,6 +37,14 @@ export function matchLegacyKiloOpenApi(input: Record) { if (provider?.additionalProperties && typeof provider.additionalProperties === "object") provider.additionalProperties = nullable(provider.additionalProperties) + const pty = spec.components?.schemas?.Pty?.properties + if (pty?.sessionID) pty.sessionID = nullable(pty.sessionID) + + const update = spec.paths?.["/pty/{ptyID}"]?.put?.requestBody?.content?.["application/json"]?.schema + const name = update?.$ref?.replace("#/components/schemas/", "") + const fields = name ? spec.components?.schemas?.[name]?.properties : update?.properties + if (fields?.sessionID) fields.sessionID = nullable(fields.sessionID) + const fim = spec.paths?.["/kilo/fim"]?.post?.responses if (!fim) return fim["200"] = { diff --git a/packages/opencode/src/kilocode/server/httpapi/server.ts b/packages/opencode/src/kilocode/server/httpapi/server.ts index f82f17fe98..e8e1e97879 100644 --- a/packages/opencode/src/kilocode/server/httpapi/server.ts +++ b/packages/opencode/src/kilocode/server/httpapi/server.ts @@ -1,7 +1,9 @@ import { Layer } from "effect" +import { agentBuilderHandlers } from "./handlers/agent-builder" import { backgroundProcessHandlers } from "./handlers/background-process" import { commitMessageHandlers } from "./handlers/commit-message" +import { configConsoleHandlers } from "./handlers/config-console" import { enhancePromptHandlers } from "./handlers/enhance-prompt" import { indexingHandlers } from "./handlers/indexing" import { kiloGatewayHandlers } from "./handlers/kilo-gateway" @@ -13,8 +15,10 @@ import { suggestionHandlers } from "./handlers/suggestion" import { telemetryHandlers } from "./handlers/telemetry" export const provide = Layer.provide([ + agentBuilderHandlers, backgroundProcessHandlers, commitMessageHandlers, + configConsoleHandlers, enhancePromptHandlers, indexingHandlers, kiloGatewayHandlers, diff --git a/packages/opencode/src/kilocode/server/routes/agent-builder.ts b/packages/opencode/src/kilocode/server/routes/agent-builder.ts index 6d08a14947..8d30155309 100644 --- a/packages/opencode/src/kilocode/server/routes/agent-builder.ts +++ b/packages/opencode/src/kilocode/server/routes/agent-builder.ts @@ -1,6 +1,7 @@ import { Hono } from "hono" import { describeRoute, resolver, validator } from "hono-openapi" import { AgentBuilder } from "@/kilocode/agent/builder" +import { AppRuntime } from "@/effect/app-runtime" import { Instance } from "@/project/instance" import { InstanceStore } from "@/project/instance-store" import { errors } from "@/server/error" @@ -53,7 +54,7 @@ export const AgentBuilderRoutes = lazy(() => const body = c.req.valid("json") const input = AgentBuilder.Input.parse({ ...body, id: c.req.valid("param").id }) const output = await AgentBuilder.save(context(), input) - await InstanceStore.disposeInstance(Instance.current) + await AppRuntime.runPromise(InstanceStore.Service.use((svc) => svc.dispose(Instance.current))) return c.json(output) }, ), diff --git a/packages/opencode/src/pty/index.ts b/packages/opencode/src/pty/index.ts index f8b57d898e..7bc2588a2e 100644 --- a/packages/opencode/src/pty/index.ts +++ b/packages/opencode/src/pty/index.ts @@ -185,7 +185,7 @@ export const layer = Layer.effect( const id = PtyID.ascending() // kilocode_change end const resolved = KiloPtySelfCommand.resolve(input) // kilocode_change - const command = resolved.command || Shell.preferred(cfg.shell) + const command = resolved.command || Shell.preferred(cfg.shell) // kilocode_change const args = resolved.args || [] // kilocode_change if (Shell.login(command)) { args.push("-l") // kilocode_change diff --git a/packages/opencode/src/server/routes/instance/httpapi/api.ts b/packages/opencode/src/server/routes/instance/httpapi/api.ts index 1121970da6..19c03eb052 100644 --- a/packages/opencode/src/server/routes/instance/httpapi/api.ts +++ b/packages/opencode/src/server/routes/instance/httpapi/api.ts @@ -21,8 +21,10 @@ import { TuiApi } from "./groups/tui" import { WorkspaceApi } from "./groups/workspace" import { V2Api } from "./groups/v2" // kilocode_change start - Kilo HttpApi groups +import { AgentBuilderApi } from "@/kilocode/server/httpapi/groups/agent-builder" import { CommitMessageApi } from "@/kilocode/server/httpapi/groups/commit-message" import { BackgroundProcessApi } from "@/kilocode/server/httpapi/groups/background-process" +import { ConfigConsoleApi } from "@/kilocode/server/httpapi/groups/config-console" import { EnhancePromptApi } from "@/kilocode/server/httpapi/groups/enhance-prompt" import { IndexingApi } from "@/kilocode/server/httpapi/groups/indexing" import { KiloGatewayApi } from "@/kilocode/server/httpapi/groups/kilo-gateway" @@ -58,8 +60,10 @@ export const InstanceHttpApi = HttpApi.make("opencode-instance") .addHttpApi(TuiApi) .addHttpApi(WorkspaceApi) // kilocode_change start - Kilo HttpApi groups + .addHttpApi(AgentBuilderApi) .addHttpApi(BackgroundProcessApi) .addHttpApi(CommitMessageApi) + .addHttpApi(ConfigConsoleApi) .addHttpApi(EnhancePromptApi) .addHttpApi(IndexingApi) .addHttpApi(KiloGatewayApi) diff --git a/packages/opencode/test/cli/tui/thread.test.ts b/packages/opencode/test/cli/tui/thread.test.ts index a03f73ef0b..e951c3f603 100644 --- a/packages/opencode/test/cli/tui/thread.test.ts +++ b/packages/opencode/test/cli/tui/thread.test.ts @@ -26,6 +26,7 @@ describe("tui thread", () => { await check(".") }) + // kilocode_change start test("ignores stale PWD after cwd is changed by a process wrapper", async () => { await using root = await tmpdir() const pkg = path.join(root.path, "packages", "opencode") @@ -33,4 +34,5 @@ describe("tui thread", () => { expect(resolveThreadDirectory(".", root.path, pkg)).toBe(pkg) }) + // kilocode_change end }) diff --git a/packages/opencode/test/kilocode/server/config-overlay.test.ts b/packages/opencode/test/kilocode/server/config-overlay.test.ts index 65e9f1d941..7e739e29e5 100644 --- a/packages/opencode/test/kilocode/server/config-overlay.test.ts +++ b/packages/opencode/test/kilocode/server/config-overlay.test.ts @@ -20,7 +20,7 @@ type Overlay = { afterEach(async () => { ;(Global.Path as { config: string }).config = original - await AppRuntime.runPromise(Config.Service.use((svc) => svc.invalidate(true))) + await AppRuntime.runPromise(Config.Service.use((svc) => svc.invalidate())) await disposeAllInstances() await resetDatabase() }) @@ -45,7 +45,7 @@ async function config(dir: string, value: unknown) { } async function invalidate() { - await AppRuntime.runPromise(Config.Service.use((svc) => svc.invalidate(true))) + await AppRuntime.runPromise(Config.Service.use((svc) => svc.invalidate())) } describe("config overlay routes", () => { diff --git a/packages/sdk/js/src/v2/gen/sdk.gen.ts b/packages/sdk/js/src/v2/gen/sdk.gen.ts index b6495fd866..e7df7015c6 100644 --- a/packages/sdk/js/src/v2/gen/sdk.gen.ts +++ b/packages/sdk/js/src/v2/gen/sdk.gen.ts @@ -3,6 +3,10 @@ import { client } from "./client.gen.js" import { buildClientParams, type Client, type Options as Options2, type TDataShape } from "./client/index.js" import type { + AgentBuilderPreviewErrors, + AgentBuilderPreviewResponses, + AgentBuilderSaveErrors, + AgentBuilderSaveResponses, AgentPartInput, AppAgentsResponses, AppLogErrors, @@ -26,9 +30,15 @@ import type { CommandListResponses, CommitMessageGenerateErrors, CommitMessageGenerateResponses, - Config as Config3, + Config as Config4, + ConfigEffectiveResponses, ConfigGetResponses, + ConfigModelStateResponses, + ConfigModelStateUpdateResponses, + ConfigOverlayResponses, + ConfigOverlayUpdateResponses, ConfigProvidersResponses, + ConfigSourcesResponses, ConfigUpdateErrors, ConfigUpdateResponses, ConfigWarningsResponses, @@ -254,6 +264,9 @@ import type { TuiAppendPromptErrors, TuiAppendPromptResponses, TuiClearPromptResponses, + TuiConfigGetResponses, + TuiConfigUpdateErrors, + TuiConfigUpdateResponses, TuiControlNextResponses, TuiControlResponseResponses, TuiExecuteCommandErrors, @@ -526,7 +539,7 @@ export class Config extends HeyApiClient { */ public update( parameters?: { - config?: Config3 + config?: Config4 }, options?: Options, ) { @@ -683,7 +696,7 @@ export class Config2 extends HeyApiClient { parameters?: { directory?: string workspace?: string - config?: Config3 + config?: Config4 }, options?: Options, ) { @@ -770,6 +783,211 @@ export class Config2 extends HeyApiClient { ...params, }) } + + /** + * Get config overlay + * + * Resolve global, project, and effective config values with source metadata for inheritance-aware settings UI. + */ + public overlay( + parameters?: { + directory?: string + workspace?: string + scope?: "global" | "project" + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "query", key: "workspace" }, + { in: "query", key: "scope" }, + ], + }, + ], + ) + return (options?.client ?? this.client).get({ + url: "/config/overlay", + ...options, + ...params, + }) + } + + /** + * Patch config overlay + * + * Apply a minimal global or project config patch, including unset paths for reverting local overrides. + */ + public overlayUpdate( + parameters?: { + directory?: string + workspace?: string + scope?: "global" | "project" + set?: { + [key: string]: unknown + } + unset?: Array> + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "query", key: "workspace" }, + { in: "body", key: "scope" }, + { in: "body", key: "set" }, + { in: "body", key: "unset" }, + ], + }, + ], + ) + return (options?.client ?? this.client).patch({ + url: "/config/overlay", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * List config sources + * + * List config source metadata in load order without exposing config contents or secrets. + */ + public sources( + 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: "/config/sources", + ...options, + ...params, + }) + } + + /** + * Get effective configuration + * + * Retrieve effective config for the current instance directory. + */ + public effective( + 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: "/config/effective", + ...options, + ...params, + }) + } + + /** + * Get model state + * + * Retrieve TUI-compatible recent and favorite model selections. + */ + public modelState( + 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: "/config/model-state", + ...options, + ...params, + }) + } + + /** + * Update model state + * + * Patch TUI-compatible model selections shared with Kilo Console. + */ + public modelStateUpdate( + parameters?: { + directory?: string + workspace?: string + favorite?: Array<{ + providerID: string + modelID: string + }> + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "query", key: "workspace" }, + { in: "body", key: "favorite" }, + ], + }, + ], + ) + return (options?.client ?? this.client).patch({ + url: "/config/model-state", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } } export class Console extends HeyApiClient { @@ -2639,7 +2857,7 @@ export class Pty extends HeyApiClient { directory?: string workspace?: string title?: string - sessionID?: string + sessionID?: string | null size?: { rows: number cols: number @@ -4748,6 +4966,107 @@ export class Control extends HeyApiClient { } } +export class Config3 extends HeyApiClient { + /** + * Get TUI configuration + * + * Retrieve the effective TUI configuration for the current instance directory. + */ + public get( + 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: "/tui/config", + ...options, + ...params, + }) + } + + /** + * Update TUI configuration + * + * Patch global or project TUI configuration and return the effective TUI configuration. + */ + public update( + parameters?: { + directory?: string + workspace?: string + scope?: "global" | "project" + $schema?: string + theme?: string + keybinds?: { + [key: string]: string + } + plugin?: Array< + | string + | [ + string, + { + [key: string]: unknown + }, + ] + > + plugin_enabled?: { + [key: string]: boolean + } + scroll_speed?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + scroll_acceleration?: { + enabled: boolean + } + diff_style?: "auto" | "stacked" + mouse?: boolean + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "query", key: "workspace" }, + { in: "query", key: "scope" }, + { in: "body", key: "$schema" }, + { in: "body", key: "theme" }, + { in: "body", key: "keybinds" }, + { in: "body", key: "plugin" }, + { in: "body", key: "plugin_enabled" }, + { in: "body", key: "scroll_speed" }, + { in: "body", key: "scroll_acceleration" }, + { in: "body", key: "diff_style" }, + { in: "body", key: "mouse" }, + ], + }, + ], + ) + return (options?.client ?? this.client).patch({ + url: "/tui/config", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } +} + export class Tui extends HeyApiClient { /** * Append TUI prompt @@ -5124,6 +5443,139 @@ export class Tui extends HeyApiClient { get control(): Control { return (this._control ??= new Control({ client: this.client })) } + + private _config?: Config3 + get config(): Config3 { + return (this._config ??= new Config3({ client: this.client })) + } +} + +export class AgentBuilder extends HeyApiClient { + /** + * Preview agent markdown + * + * Validate an agent builder payload and return the canonical agent markdown without writing it. + */ + public preview( + parameters?: { + directory?: string + workspace?: string + id?: string + scope?: "global" | "project" + description?: string + mode?: "primary" | "subagent" | "all" + model?: string + color?: string + steps?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + tools?: Array + permission?: { + [key: string]: unknown + } + prompt?: string + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "query", key: "workspace" }, + { in: "body", key: "id" }, + { in: "body", key: "scope" }, + { in: "body", key: "description" }, + { in: "body", key: "mode" }, + { in: "body", key: "model" }, + { in: "body", key: "color" }, + { in: "body", key: "steps" }, + { in: "body", key: "tools" }, + { in: "body", key: "permission" }, + { in: "body", key: "prompt" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post( + { + url: "/agent-builder/preview", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }, + ) + } + + /** + * Save agent markdown + * + * Save an agent builder payload as a canonical agent markdown file. + */ + public save( + parameters: { + path_id: string + directory?: string + workspace?: string + body_id?: string + scope?: "global" | "project" + description?: string + mode?: "primary" | "subagent" | "all" + model?: string + color?: string + steps?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + tools?: Array + permission?: { + [key: string]: unknown + } + prompt?: string + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { + in: "path", + key: "path_id", + map: "id", + }, + { in: "query", key: "directory" }, + { in: "query", key: "workspace" }, + { + in: "body", + key: "body_id", + map: "id", + }, + { in: "body", key: "scope" }, + { in: "body", key: "description" }, + { in: "body", key: "mode" }, + { in: "body", key: "model" }, + { in: "body", key: "color" }, + { in: "body", key: "steps" }, + { in: "body", key: "tools" }, + { in: "body", key: "permission" }, + { in: "body", key: "prompt" }, + ], + }, + ], + ) + return (options?.client ?? this.client).put({ + url: "/agent-builder/{id}", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } } export class BackgroundProcess extends HeyApiClient { @@ -6974,6 +7426,11 @@ export class KiloClient extends HeyApiClient { return (this._tui ??= new Tui({ client: this.client })) } + private _agentBuilder?: AgentBuilder + get agentBuilder(): AgentBuilder { + return (this._agentBuilder ??= new AgentBuilder({ client: this.client })) + } + private _backgroundProcess?: BackgroundProcess get backgroundProcess(): BackgroundProcess { return (this._backgroundProcess ??= new BackgroundProcess({ 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 c06af10487..6e67012518 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -438,7 +438,7 @@ export type Pty = { cwd: string status: "running" | "exited" pid: number - sessionID?: string + sessionID?: string | null } export type OutputFormatText = { @@ -1985,6 +1985,117 @@ export type BackgroundProcessLogs = { output: string } +export type ConfigOverlayResponse = { + scope: "global" | "project" + effective: Config + global: Config + project: Config + sources: Array<{ + order: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + kind: string + scope: string + label: string + source: string + path?: string + exists: boolean + editable: boolean + reason?: string + }> + targets: { + global?: string + project?: string + active?: string + } + fields: { + [key: string]: { + key: string + path: Array + value?: unknown + global?: unknown + local?: unknown + source: "project" | "global" | "system" | "default" + inherited: boolean + overridden: boolean + editable: boolean + reason?: string + } + } + collections: { + [key: string]: Array<{ + key: string + path: Array + value?: unknown + global?: unknown + local?: unknown + source: "project" | "global" | "system" | "default" + inherited: boolean + overridden: boolean + editable: boolean + reason?: string + }> + } +} + +export type ConfigSourcesResponse = { + sources: Array<{ + order: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + kind: string + scope: string + label: string + source: string + path?: string + exists: boolean + editable: boolean + reason?: string + }> +} + +export type ConfigModelStateResponse = { + model: { + [key: string]: { + providerID: string + modelID: string + } + } + recent: Array<{ + providerID: string + modelID: string + }> + favorite: Array<{ + providerID: string + modelID: string + }> + variant: { + [key: string]: string + } +} + +export type TuiConfigGetResponse = { + $schema?: string + theme?: string + keybinds?: { + [key: string]: string + } + plugin?: Array< + | string + | [ + string, + { + [key: string]: unknown + }, + ] + > + plugin_enabled?: { + [key: string]: boolean + } + scroll_speed?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + scroll_acceleration?: { + enabled: boolean + } + diff_style?: "auto" | "stacked" + mouse?: boolean +} + export type EffectHttpApiErrorUnauthorized = { _tag: "Unauthorized" } @@ -5211,7 +5322,7 @@ export type PtyGetResponse = PtyGetResponses[keyof PtyGetResponses] export type PtyUpdateData = { body?: { title?: string - sessionID?: string + sessionID?: string | null size?: { rows: number cols: number @@ -7395,6 +7506,100 @@ export type ExperimentalWorkspaceWarpResponses = { export type ExperimentalWorkspaceWarpResponse = ExperimentalWorkspaceWarpResponses[keyof ExperimentalWorkspaceWarpResponses] +export type AgentBuilderPreviewData = { + body?: { + id: string + scope?: "global" | "project" + description?: string + mode?: "primary" | "subagent" | "all" + model?: string + color?: string + steps?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + tools?: Array + permission?: { + [key: string]: unknown + } + prompt: string + } + path?: never + query?: { + directory?: string + workspace?: string + } + url: "/agent-builder/preview" +} + +export type AgentBuilderPreviewErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type AgentBuilderPreviewError = AgentBuilderPreviewErrors[keyof AgentBuilderPreviewErrors] + +export type AgentBuilderPreviewResponses = { + /** + * Agent markdown preview + */ + 200: { + id: string + scope: "global" | "project" + path: string + markdown: string + } +} + +export type AgentBuilderPreviewResponse = AgentBuilderPreviewResponses[keyof AgentBuilderPreviewResponses] + +export type AgentBuilderSaveData = { + body?: { + id?: string + scope?: "global" | "project" + description?: string + mode?: "primary" | "subagent" | "all" + model?: string + color?: string + steps?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + tools?: Array + permission?: { + [key: string]: unknown + } + prompt: string + } + path: { + id: string + } + query?: { + directory?: string + workspace?: string + } + url: "/agent-builder/{id}" +} + +export type AgentBuilderSaveErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type AgentBuilderSaveError = AgentBuilderSaveErrors[keyof AgentBuilderSaveErrors] + +export type AgentBuilderSaveResponses = { + /** + * Saved agent markdown + */ + 200: { + id: string + scope: "global" | "project" + path: string + markdown: string + } +} + +export type AgentBuilderSaveResponse = AgentBuilderSaveResponses[keyof AgentBuilderSaveResponses] + export type BackgroundProcessListData = { body?: never path?: never @@ -7594,6 +7799,204 @@ export type CommitMessageGenerateResponses = { export type CommitMessageGenerateResponse = CommitMessageGenerateResponses[keyof CommitMessageGenerateResponses] +export type ConfigOverlayData = { + body?: never + path?: never + query?: { + directory?: string + workspace?: string + scope?: "global" | "project" + } + url: "/config/overlay" +} + +export type ConfigOverlayResponses = { + /** + * Resolved config overlay + */ + 200: ConfigOverlayResponse +} + +export type ConfigOverlayResponse2 = ConfigOverlayResponses[keyof ConfigOverlayResponses] + +export type ConfigOverlayUpdateData = { + body?: { + scope?: "global" | "project" + set?: { + [key: string]: unknown + } + unset?: Array> + } + path?: never + query?: { + directory?: string + workspace?: string + } + url: "/config/overlay" +} + +export type ConfigOverlayUpdateResponses = { + /** + * Effective configuration after patch + */ + 200: Config +} + +export type ConfigOverlayUpdateResponse = ConfigOverlayUpdateResponses[keyof ConfigOverlayUpdateResponses] + +export type ConfigSourcesData = { + body?: never + path?: never + query?: { + directory?: string + workspace?: string + } + url: "/config/sources" +} + +export type ConfigSourcesResponses = { + /** + * Config source inventory + */ + 200: ConfigSourcesResponse +} + +export type ConfigSourcesResponse2 = ConfigSourcesResponses[keyof ConfigSourcesResponses] + +export type ConfigEffectiveData = { + body?: never + path?: never + query?: { + directory?: string + workspace?: string + } + url: "/config/effective" +} + +export type ConfigEffectiveResponses = { + /** + * Effective config info + */ + 200: Config +} + +export type ConfigEffectiveResponse = ConfigEffectiveResponses[keyof ConfigEffectiveResponses] + +export type ConfigModelStateData = { + body?: never + path?: never + query?: { + directory?: string + workspace?: string + } + url: "/config/model-state" +} + +export type ConfigModelStateResponses = { + /** + * Model state + */ + 200: ConfigModelStateResponse +} + +export type ConfigModelStateResponse2 = ConfigModelStateResponses[keyof ConfigModelStateResponses] + +export type ConfigModelStateUpdateData = { + body?: { + favorite?: Array<{ + providerID: string + modelID: string + }> + } + path?: never + query?: { + directory?: string + workspace?: string + } + url: "/config/model-state" +} + +export type ConfigModelStateUpdateResponses = { + /** + * Updated model state + */ + 200: ConfigModelStateResponse +} + +export type ConfigModelStateUpdateResponse = ConfigModelStateUpdateResponses[keyof ConfigModelStateUpdateResponses] + +export type TuiConfigGetData = { + body?: never + path?: never + query?: { + directory?: string + workspace?: string + } + url: "/tui/config" +} + +export type TuiConfigGetResponses = { + /** + * Effective TUI configuration + */ + 200: TuiConfigGetResponse +} + +export type TuiConfigGetResponse2 = TuiConfigGetResponses[keyof TuiConfigGetResponses] + +export type TuiConfigUpdateData = { + body?: { + $schema?: string + theme?: string + keybinds?: { + [key: string]: string + } + plugin?: Array< + | string + | [ + string, + { + [key: string]: unknown + }, + ] + > + plugin_enabled?: { + [key: string]: boolean + } + scroll_speed?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + scroll_acceleration?: { + enabled: boolean + } + diff_style?: "auto" | "stacked" + mouse?: boolean + } + path?: never + query?: { + directory?: string + workspace?: string + scope?: "global" | "project" + } + url: "/tui/config" +} + +export type TuiConfigUpdateErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type TuiConfigUpdateError = TuiConfigUpdateErrors[keyof TuiConfigUpdateErrors] + +export type TuiConfigUpdateResponses = { + /** + * Effective TUI configuration after the update + */ + 200: TuiConfigGetResponse +} + +export type TuiConfigUpdateResponse = TuiConfigUpdateResponses[keyof TuiConfigUpdateResponses] + export type EnhancePromptEnhanceData = { body?: { /** diff --git a/packages/sdk/openapi.json b/packages/sdk/openapi.json index e3b359d979..1e51549ed4 100644 --- a/packages/sdk/openapi.json +++ b/packages/sdk/openapi.json @@ -3773,7 +3773,14 @@ "type": "string" }, "sessionID": { - "type": "string" + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] }, "size": { "type": "object", @@ -9205,6 +9212,294 @@ ] } }, + "/agent-builder/preview": { + "post": { + "tags": ["agent-builder"], + "operationId": "agentBuilder.preview", + "parameters": [ + { + "name": "directory", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "workspace", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Agent markdown preview", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "scope": { + "type": "string", + "enum": ["global", "project"] + }, + "path": { + "type": "string" + }, + "markdown": { + "type": "string" + } + }, + "required": ["id", "scope", "path", "markdown"], + "additionalProperties": false, + "description": "Agent markdown preview" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestError" + } + } + } + } + }, + "description": "Validate an agent builder payload and return the canonical agent markdown without writing it.", + "summary": "Preview agent markdown", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "scope": { + "type": "string", + "enum": ["global", "project"] + }, + "description": { + "type": "string" + }, + "mode": { + "type": "string", + "enum": ["primary", "subagent", "all"] + }, + "model": { + "type": "string" + }, + "color": { + "type": "string" + }, + "steps": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string", + "enum": ["NaN"] + }, + { + "type": "string", + "enum": ["Infinity"] + }, + { + "type": "string", + "enum": ["-Infinity"] + }, + { + "type": "string", + "enum": ["Infinity", "-Infinity", "NaN"] + } + ] + }, + "tools": { + "type": "array", + "items": { + "type": "string" + } + }, + "permission": { + "type": "object" + }, + "prompt": { + "type": "string" + } + }, + "required": ["id", "prompt"], + "additionalProperties": false + } + } + } + }, + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.agentBuilder.preview({\n ...\n})" + } + ] + } + }, + "/agent-builder/{id}": { + "put": { + "tags": ["agent-builder"], + "operationId": "agentBuilder.save", + "parameters": [ + { + "name": "directory", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "workspace", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "Saved agent markdown", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "scope": { + "type": "string", + "enum": ["global", "project"] + }, + "path": { + "type": "string" + }, + "markdown": { + "type": "string" + } + }, + "required": ["id", "scope", "path", "markdown"], + "additionalProperties": false, + "description": "Saved agent markdown" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestError" + } + } + } + } + }, + "description": "Save an agent builder payload as a canonical agent markdown file.", + "summary": "Save agent markdown", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "scope": { + "type": "string", + "enum": ["global", "project"] + }, + "description": { + "type": "string" + }, + "mode": { + "type": "string", + "enum": ["primary", "subagent", "all"] + }, + "model": { + "type": "string" + }, + "color": { + "type": "string" + }, + "steps": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string", + "enum": ["NaN"] + }, + { + "type": "string", + "enum": ["Infinity"] + }, + { + "type": "string", + "enum": ["-Infinity"] + }, + { + "type": "string", + "enum": ["Infinity", "-Infinity", "NaN"] + } + ] + }, + "tools": { + "type": "array", + "items": { + "type": "string" + } + }, + "permission": { + "type": "object" + }, + "prompt": { + "type": "string" + } + }, + "required": ["prompt"], + "additionalProperties": false + } + } + } + }, + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.agentBuilder.save({\n ...\n})" + } + ] + } + }, "/background-process": { "get": { "tags": ["background-process"], @@ -9647,6 +9942,529 @@ ] } }, + "/config/overlay": { + "get": { + "tags": ["config-console"], + "operationId": "config.overlay", + "parameters": [ + { + "name": "directory", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "workspace", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "scope", + "in": "query", + "schema": { + "type": "string", + "enum": ["global", "project"] + }, + "required": false + } + ], + "responses": { + "200": { + "description": "Resolved config overlay", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConfigOverlayResponse" + } + } + } + } + }, + "description": "Resolve global, project, and effective config values with source metadata for inheritance-aware settings UI.", + "summary": "Get config overlay", + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.config.overlay({\n ...\n})" + } + ] + }, + "patch": { + "tags": ["config-console"], + "operationId": "config.overlayUpdate", + "parameters": [ + { + "name": "directory", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "workspace", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Effective configuration after patch", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Config" + } + } + } + } + }, + "description": "Apply a minimal global or project config patch, including unset paths for reverting local overrides.", + "summary": "Patch config overlay", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "scope": { + "type": "string", + "enum": ["global", "project"] + }, + "set": { + "type": "object" + }, + "unset": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "additionalProperties": false + } + } + } + }, + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.config.overlayUpdate({\n ...\n})" + } + ] + } + }, + "/config/sources": { + "get": { + "tags": ["config-console"], + "operationId": "config.sources", + "parameters": [ + { + "name": "directory", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "workspace", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Config source inventory", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConfigSourcesResponse" + } + } + } + } + }, + "description": "List config source metadata in load order without exposing config contents or secrets.", + "summary": "List config sources", + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.config.sources({\n ...\n})" + } + ] + } + }, + "/config/effective": { + "get": { + "tags": ["config-console"], + "operationId": "config.effective", + "parameters": [ + { + "name": "directory", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "workspace", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Effective config info", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Config" + } + } + } + } + }, + "description": "Retrieve effective config for the current instance directory.", + "summary": "Get effective configuration", + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.config.effective({\n ...\n})" + } + ] + } + }, + "/config/model-state": { + "get": { + "tags": ["config-console"], + "operationId": "config.modelState", + "parameters": [ + { + "name": "directory", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "workspace", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Model state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConfigModelStateResponse" + } + } + } + } + }, + "description": "Retrieve TUI-compatible recent and favorite model selections.", + "summary": "Get model state", + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.config.modelState({\n ...\n})" + } + ] + }, + "patch": { + "tags": ["config-console"], + "operationId": "config.modelStateUpdate", + "parameters": [ + { + "name": "directory", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "workspace", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Updated model state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConfigModelStateResponse" + } + } + } + } + }, + "description": "Patch TUI-compatible model selections shared with Kilo Console.", + "summary": "Update model state", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "favorite": { + "type": "array", + "items": { + "type": "object", + "properties": { + "providerID": { + "type": "string" + }, + "modelID": { + "type": "string" + } + }, + "required": ["providerID", "modelID"], + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + } + } + }, + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.config.modelStateUpdate({\n ...\n})" + } + ] + } + }, + "/tui/config": { + "get": { + "tags": ["config-console"], + "operationId": "tui.config.get", + "parameters": [ + { + "name": "directory", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "workspace", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Effective TUI configuration", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TuiConfigGetResponse" + } + } + } + } + }, + "description": "Retrieve the effective TUI configuration for the current instance directory.", + "summary": "Get TUI configuration", + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.tui.config.get({\n ...\n})" + } + ] + }, + "patch": { + "tags": ["config-console"], + "operationId": "tui.config.update", + "parameters": [ + { + "name": "directory", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "workspace", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "scope", + "in": "query", + "schema": { + "type": "string", + "enum": ["global", "project"] + }, + "required": false + } + ], + "responses": { + "200": { + "description": "Effective TUI configuration after the update", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TuiConfigGetResponse" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestError" + } + } + } + } + }, + "description": "Patch global or project TUI configuration and return the effective TUI configuration.", + "summary": "Update TUI configuration", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "$schema": { + "type": "string" + }, + "theme": { + "type": "string" + }, + "keybinds": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "plugin": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "prefixItems": [ + { + "type": "string" + }, + { + "type": "object" + } + ], + "maxItems": 2, + "minItems": 2 + } + ] + } + }, + "plugin_enabled": { + "type": "object", + "additionalProperties": { + "type": "boolean" + } + }, + "scroll_speed": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string", + "enum": ["NaN"] + }, + { + "type": "string", + "enum": ["Infinity"] + }, + { + "type": "string", + "enum": ["-Infinity"] + }, + { + "type": "string", + "enum": ["Infinity", "-Infinity", "NaN"] + } + ] + }, + "scroll_acceleration": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + }, + "required": ["enabled"], + "additionalProperties": false + }, + "diff_style": { + "type": "string", + "enum": ["auto", "stacked"] + }, + "mouse": { + "type": "boolean" + } + }, + "additionalProperties": false + } + } + } + }, + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.tui.config.update({\n ...\n})" + } + ] + } + }, "/enhance-prompt": { "post": { "tags": ["enhance-prompt"], @@ -14074,7 +14892,14 @@ "exclusiveMinimum": 0 }, "sessionID": { - "type": "string" + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] } }, "required": ["id", "title", "command", "args", "cwd", "status", "pid"], @@ -18604,6 +19429,389 @@ "required": ["id", "sessionID", "output"], "additionalProperties": false }, + "ConfigOverlayResponse": { + "type": "object", + "properties": { + "scope": { + "type": "string", + "enum": ["global", "project"] + }, + "effective": { + "$ref": "#/components/schemas/Config" + }, + "global": { + "$ref": "#/components/schemas/Config" + }, + "project": { + "$ref": "#/components/schemas/Config" + }, + "sources": { + "type": "array", + "items": { + "type": "object", + "properties": { + "order": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string", + "enum": ["NaN"] + }, + { + "type": "string", + "enum": ["Infinity"] + }, + { + "type": "string", + "enum": ["-Infinity"] + }, + { + "type": "string", + "enum": ["Infinity", "-Infinity", "NaN"] + } + ] + }, + "kind": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "label": { + "type": "string" + }, + "source": { + "type": "string" + }, + "path": { + "type": "string" + }, + "exists": { + "type": "boolean" + }, + "editable": { + "type": "boolean" + }, + "reason": { + "type": "string" + } + }, + "required": ["order", "kind", "scope", "label", "source", "exists", "editable"], + "additionalProperties": false + } + }, + "targets": { + "type": "object", + "properties": { + "global": { + "type": "string" + }, + "project": { + "type": "string" + }, + "active": { + "type": "string" + } + }, + "additionalProperties": false + }, + "fields": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "path": { + "type": "array", + "items": { + "type": "string" + } + }, + "value": {}, + "global": {}, + "local": {}, + "source": { + "type": "string", + "enum": ["project", "global", "system", "default"] + }, + "inherited": { + "type": "boolean" + }, + "overridden": { + "type": "boolean" + }, + "editable": { + "type": "boolean" + }, + "reason": { + "type": "string" + } + }, + "required": ["key", "path", "source", "inherited", "overridden", "editable"], + "additionalProperties": false + } + }, + "collections": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "path": { + "type": "array", + "items": { + "type": "string" + } + }, + "value": {}, + "global": {}, + "local": {}, + "source": { + "type": "string", + "enum": ["project", "global", "system", "default"] + }, + "inherited": { + "type": "boolean" + }, + "overridden": { + "type": "boolean" + }, + "editable": { + "type": "boolean" + }, + "reason": { + "type": "string" + } + }, + "required": ["key", "path", "source", "inherited", "overridden", "editable"], + "additionalProperties": false + } + } + } + }, + "required": ["scope", "effective", "global", "project", "sources", "targets", "fields", "collections"], + "additionalProperties": false + }, + "ConfigSourcesResponse": { + "type": "object", + "properties": { + "sources": { + "type": "array", + "items": { + "type": "object", + "properties": { + "order": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string", + "enum": ["NaN"] + }, + { + "type": "string", + "enum": ["Infinity"] + }, + { + "type": "string", + "enum": ["-Infinity"] + }, + { + "type": "string", + "enum": ["Infinity", "-Infinity", "NaN"] + } + ] + }, + "kind": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "label": { + "type": "string" + }, + "source": { + "type": "string" + }, + "path": { + "type": "string" + }, + "exists": { + "type": "boolean" + }, + "editable": { + "type": "boolean" + }, + "reason": { + "type": "string" + } + }, + "required": ["order", "kind", "scope", "label", "source", "exists", "editable"], + "additionalProperties": false + } + } + }, + "required": ["sources"], + "additionalProperties": false + }, + "ConfigModelStateResponse": { + "type": "object", + "properties": { + "model": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "providerID": { + "type": "string" + }, + "modelID": { + "type": "string" + } + }, + "required": ["providerID", "modelID"], + "additionalProperties": false + } + }, + "recent": { + "type": "array", + "items": { + "type": "object", + "properties": { + "providerID": { + "type": "string" + }, + "modelID": { + "type": "string" + } + }, + "required": ["providerID", "modelID"], + "additionalProperties": false + } + }, + "favorite": { + "type": "array", + "items": { + "type": "object", + "properties": { + "providerID": { + "type": "string" + }, + "modelID": { + "type": "string" + } + }, + "required": ["providerID", "modelID"], + "additionalProperties": false + } + }, + "variant": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "required": ["model", "recent", "favorite", "variant"], + "additionalProperties": false + }, + "TuiConfigGetResponse": { + "type": "object", + "properties": { + "$schema": { + "type": "string" + }, + "theme": { + "type": "string" + }, + "keybinds": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "plugin": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "prefixItems": [ + { + "type": "string" + }, + { + "type": "object" + } + ], + "maxItems": 2, + "minItems": 2 + } + ] + } + }, + "plugin_enabled": { + "type": "object", + "additionalProperties": { + "type": "boolean" + } + }, + "scroll_speed": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string", + "enum": ["NaN"] + }, + { + "type": "string", + "enum": ["Infinity"] + }, + { + "type": "string", + "enum": ["-Infinity"] + }, + { + "type": "string", + "enum": ["Infinity", "-Infinity", "NaN"] + } + ] + }, + "scroll_acceleration": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + }, + "required": ["enabled"], + "additionalProperties": false + }, + "diff_style": { + "type": "string", + "enum": ["auto", "stacked"] + }, + "mouse": { + "type": "boolean" + } + }, + "additionalProperties": false + }, "effect_HttpApiError_Unauthorized": { "type": "object", "properties": { @@ -23767,6 +24975,10 @@ "name": "workspace", "description": "Experimental HttpApi workspace routes." }, + { + "name": "agent-builder", + "description": "Kilo agent builder routes." + }, { "name": "background-process", "description": "Kilo background process routes." @@ -23775,6 +24987,10 @@ "name": "commit-message", "description": "Kilo commit message routes." }, + { + "name": "config-console", + "description": "Kilo Console config routes." + }, { "name": "enhance-prompt", "description": "Kilo enhance prompt routes."