feat(kilocode): add worktree diff, FIM proxy, audio transcription, and session viewed endpoints

Introduce several new Effect HttpApi endpoints across the kilo-gateway
and experimental API groups to support agent manager workflows and
enhanced gateway proxying.

- Add worktree diff endpoints (diff, diff/summary, diff/file) for
  comparing worktree changes against a base branch
- Add FIM completion proxy endpoint with streaming SSE response and
  timeout handling
- Add audio transcriptions proxy endpoint forwarding to Kilo Gateway
- Add organization modes endpoint to fetch custom modes config
- Add session/viewed endpoint to track which sessions the user has open
- Extend session list query with projectID and worktrees parameters
- Register all new routes in Hono instance router
- Regenerate SDK types and OpenAPI spec
This commit is contained in:
Imanol Maiztegui
2026-05-18 15:41:42 +02:00
parent f560e5bd7a
commit a1a1936416
11 changed files with 1604 additions and 17 deletions
@@ -1,5 +1,5 @@
import { Schema } from "effect"
import { HttpApi, HttpApiEndpoint, HttpApiError, HttpApiGroup, OpenApi } from "effect/unstable/httpapi"
import { HttpApi, HttpApiEndpoint, HttpApiError, HttpApiGroup, HttpApiSchema, OpenApi } from "effect/unstable/httpapi"
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"
@@ -103,6 +103,61 @@ export const CloudSessionImportBody = Schema.Struct({
sessionId: Schema.String,
})
const GroupEntry = Schema.Union([
Schema.String,
Schema.Tuple([
Schema.String,
Schema.Struct({
fileRegex: Schema.optional(Schema.String),
description: Schema.optional(Schema.String),
}),
]),
])
export const OrganizationMode = Schema.Struct({
id: Schema.String,
organization_id: Schema.String,
name: Schema.String,
slug: Schema.String,
created_by: Schema.String,
created_at: Schema.String,
updated_at: Schema.String,
config: Schema.Struct({
roleDefinition: Schema.optional(Schema.String),
whenToUse: Schema.optional(Schema.String),
description: Schema.optional(Schema.String),
customInstructions: Schema.optional(Schema.String),
groups: Schema.optional(Schema.Array(GroupEntry)),
}),
})
export const OrganizationModes = Schema.Struct({
modes: Schema.Array(OrganizationMode),
})
export const FimBody = Schema.Struct({
prefix: Schema.String,
suffix: Schema.String,
model: Schema.optional(Schema.String),
maxTokens: Schema.optional(Schema.Finite),
temperature: Schema.optional(Schema.Finite),
})
export const AudioTranscriptionsBody = Schema.Struct({
model: Schema.String,
input_audio: Schema.Struct({
data: Schema.String,
format: Schema.String,
}),
language: Schema.optional(Schema.String),
temperature: Schema.optional(Schema.Finite),
})
export const TranscriptionResponse = Schema.Struct({
text: Schema.String,
usage: Schema.optional(Schema.Unknown),
})
export const CloudMessage = Schema.Struct({
info: Schema.Struct({
id: Schema.String,
@@ -136,7 +191,10 @@ export const CloudSessionData = Schema.Struct({
})
export const KiloGatewayPaths = {
modes: `${root}/modes`,
profile: `${root}/profile`,
fim: `${root}/fim`,
audioTranscriptions: `${root}/audio/transcriptions`,
notifications: `${root}/notifications`,
organization: `${root}/organization`,
clawStatus: `${root}/claw/status`,
@@ -160,6 +218,37 @@ export const KiloGatewayApi = HttpApi.make("kilo")
description: "Fetch user profile and organizations from Kilo Gateway",
}),
),
HttpApiEndpoint.get("modes", KiloGatewayPaths.modes, {
success: described(OrganizationModes, "Organization modes list"),
}).annotateMerge(
OpenApi.annotations({
identifier: "kilo.modes",
summary: "Get organization custom modes",
description: "Fetch custom modes defined for the current organization",
}),
),
HttpApiEndpoint.post("fim", KiloGatewayPaths.fim, {
payload: FimBody,
success: Schema.String.pipe(HttpApiSchema.asText({ contentType: "text/event-stream" })),
error: [HttpApiError.BadRequest, HttpApiError.Unauthorized],
}).annotateMerge(
OpenApi.annotations({
identifier: "kilo.fim",
summary: "FIM completion",
description: "Proxy a Fill-in-the-Middle completion request to the Kilo Gateway",
}),
),
HttpApiEndpoint.post("audioTranscriptions", KiloGatewayPaths.audioTranscriptions, {
payload: AudioTranscriptionsBody,
success: described(TranscriptionResponse, "Transcription response"),
error: [HttpApiError.BadRequest, HttpApiError.Unauthorized],
}).annotateMerge(
OpenApi.annotations({
identifier: "kilo.audio.transcriptions",
summary: "Speech to text transcription",
description: "Proxy an audio transcription request to the Kilo Gateway",
}),
),
HttpApiEndpoint.get("notifications", KiloGatewayPaths.notifications, {
success: described(Schema.Array(Notification), "Notifications list"),
error: [HttpApiError.BadRequest, HttpApiError.Unauthorized],
@@ -8,6 +8,7 @@ import {
importSessionToDb,
} from "@kilocode/kilo-gateway"
import {
HEADER_FEATURE,
HEADER_ORGANIZATIONID,
KILO_API_BASE,
KILO_CHAT_URL,
@@ -15,9 +16,13 @@ import {
clearModesCache,
fetchBalance,
fetchKilocodeNotifications,
fetchOrganizationModes,
fetchProfile,
} from "@kilocode/kilo-gateway"
import { buildKiloHeaders } from "@kilocode/kilo-gateway"
import { Effect } from "effect"
import * as Stream from "effect/Stream"
import { HttpServerRequest, HttpServerResponse } from "effect/unstable/http"
import { HttpApiBuilder, HttpApiError } from "effect/unstable/httpapi"
import { Auth } from "@/auth"
import { Bus } from "@/bus"
@@ -29,6 +34,9 @@ import { InstanceHttpApi } from "@/server/routes/instance/httpapi/api"
import { MessageTable, PartTable, SessionTable } from "@/session/session.sql"
import { Session } from "@/session/session"
import { Database } from "@/storage/db"
import { AudioTranscriptionsBody, FimBody } from "../groups/kilo-gateway"
const FIM_TIMEOUT_MS = 30_000
export const kiloGatewayHandlers = HttpApiBuilder.group(InstanceHttpApi, "kilo", (handlers) =>
Effect.gen(function* () {
@@ -47,6 +55,117 @@ export const kiloGatewayHandlers = HttpApiBuilder.group(InstanceHttpApi, "kilo",
return { profile, balance, currentOrgId }
})
const proxy = Effect.fn("KiloGatewayHttpApi.proxyAuth")(function* () {
const info = yield* auth.get("kilo").pipe(Effect.mapError(() => new HttpApiError.Unauthorized({})))
return {
auth: info,
token: getToken(info),
organizationId: getOrganizationId(info),
}
})
const modes = Effect.fn("KiloGatewayHttpApi.modes")(function* () {
const info = yield* auth.get("kilo").pipe(Effect.mapError(() => new HttpApiError.BadRequest({})))
if (!info || info.type !== "oauth" || !info.access || !info.accountId) return { modes: [] }
return yield* Effect.promise(() => fetchOrganizationModes(info.access, info.accountId)).pipe(
Effect.map((modes) => ({ modes })),
Effect.catch(() => Effect.succeed({ modes: [] })),
)
})
const fim = Effect.fn("KiloGatewayHttpApi.fim")(function* (ctx: { payload: typeof FimBody.Type }) {
const info = yield* proxy()
if (!info.auth) return yield* Effect.fail(new HttpApiError.Unauthorized({}))
if (!info.token) return yield* Effect.fail(new HttpApiError.Unauthorized({}))
const request = yield* HttpServerRequest.HttpServerRequest
const endpoint = new URL("fim/completions", `${KILO_API_BASE}/api/`)
const signal = AbortSignal.any([request.source.signal, AbortSignal.timeout(FIM_TIMEOUT_MS)])
const response = yield* Effect.promise(async () => {
try {
return await fetch(endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${info.token}`,
...buildKiloHeaders(undefined, { kilocodeOrganizationId: info.organizationId }),
[HEADER_FEATURE]: "autocomplete",
},
signal,
body: JSON.stringify({
model: ctx.payload.model ?? "mistralai/codestral-2501",
prompt: ctx.payload.prefix,
suffix: ctx.payload.suffix,
max_tokens: ctx.payload.maxTokens ?? 256,
temperature: ctx.payload.temperature ?? 0.2,
stream: true,
}),
})
} catch (err) {
if (err instanceof DOMException && err.name === "TimeoutError")
return Response.json({ error: "FIM request timed out" }, { status: 504 })
if (signal.aborted) return Response.json({ error: "FIM request canceled" }, { status: 499 })
throw err
}
})
if (!response.ok) {
const text = yield* Effect.promise(() => response.text())
return HttpServerResponse.jsonUnsafe(
{ error: `FIM request failed: ${response.status} ${text}` },
{ status: response.status },
)
}
if (!response.body) return HttpServerResponse.raw(null, { status: response.status })
return HttpServerResponse.stream(
Stream.fromReadableStream({
evaluate: () => response.body!,
onError: (err) => err,
}),
{
contentType: "text/event-stream",
headers: {
"Cache-Control": "no-cache",
Connection: "keep-alive",
},
},
)
})
const audioTranscriptions = Effect.fn("KiloGatewayHttpApi.audioTranscriptions")(function* (ctx: {
payload: typeof AudioTranscriptionsBody.Type
}) {
const info = yield* proxy()
if (!info.auth) return yield* Effect.fail(new HttpApiError.Unauthorized({}))
if (!info.token) return yield* Effect.fail(new HttpApiError.Unauthorized({}))
const request = yield* HttpServerRequest.HttpServerRequest
const response = yield* Effect.tryPromise({
try: () =>
fetch(`${KILO_API_BASE}/api/gateway/v1/audio/transcriptions`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${info.token}`,
...buildKiloHeaders(undefined, { kilocodeOrganizationId: info.organizationId }),
[HEADER_FEATURE]: "vscode-extension",
},
signal: request.source.signal,
body: JSON.stringify(ctx.payload),
}),
catch: () => new HttpApiError.BadRequest({}),
})
const text = yield* Effect.promise(() => response.text())
return HttpServerResponse.raw(text, {
status: response.status,
contentType: response.headers.get("Content-Type") ?? "application/json",
headers: {
"Content-Type": response.headers.get("Content-Type") ?? "application/json",
},
})
})
const notifications = Effect.fn("KiloGatewayHttpApi.notifications")(function* () {
const info = yield* auth.get("kilo").pipe(Effect.mapError(() => new HttpApiError.BadRequest({})))
const token = getToken(info)
@@ -178,6 +297,9 @@ export const kiloGatewayHandlers = HttpApiBuilder.group(InstanceHttpApi, "kilo",
return handlers
.handle("profile", profile)
.handle("modes", modes)
.handle("fim", fim)
.handle("audioTranscriptions", audioTranscriptions)
.handle("notifications", notifications)
.handle("organization", organization)
.handle("clawStatus", clawStatus)
@@ -35,6 +35,9 @@ export function register(app: Hono, handler: Handler, context: Context.Context<u
app.post(SessionImportPaths.part, (c) => handler(c.req.raw, context))
app.get(IndexingPaths.status, (c) => handler(c.req.raw, context))
app.get(KiloGatewayPaths.profile, (c) => handler(c.req.raw, context))
app.get(KiloGatewayPaths.modes, (c) => handler(c.req.raw, context))
app.post(KiloGatewayPaths.fim, (c) => handler(c.req.raw, context))
app.post(KiloGatewayPaths.audioTranscriptions, (c) => handler(c.req.raw, context))
app.get(KiloGatewayPaths.notifications, (c) => handler(c.req.raw, context))
app.post(KiloGatewayPaths.organization, (c) => handler(c.req.raw, context))
app.get(KiloGatewayPaths.clawStatus, (c) => handler(c.req.raw, context))
@@ -1,7 +1,9 @@
import { AccountID, OrgID } from "@/account/schema"
import { Snapshot } from "@/snapshot" // kilocode_change
import { MCP } from "@/mcp"
import { ProviderID, ModelID } from "@/provider/schema"
import { Session } from "@/session/session"
import { WorktreeDiff } from "@/kilocode/review/worktree-diff" // kilocode_change
import { Worktree } from "@/worktree"
import { NonNegativeInt } from "@/util/schema"
import { Schema, SchemaGetter } from "effect"
@@ -55,7 +57,11 @@ const QueryBoolean = Schema.Literals(["true", "false"]).pipe(
)
const WorktreeList = Schema.Array(Schema.String)
export const SessionListQuery = Schema.Struct({
// kilocode_change start
projectID: Schema.optional(Schema.String),
directory: Schema.optional(Schema.String),
worktrees: Schema.optional(QueryBoolean),
// kilocode_change end
roots: Schema.optional(QueryBoolean),
start: Schema.optional(Schema.NumberFromString),
cursor: Schema.optional(Schema.NumberFromString),
@@ -63,6 +69,15 @@ export const SessionListQuery = Schema.Struct({
limit: Schema.optional(Schema.NumberFromString),
archived: Schema.optional(QueryBoolean),
})
// kilocode_change start
export const WorktreeDiffQuery = Schema.Struct({
base: Schema.optional(Schema.String),
})
export const WorktreeDiffFileQuery = Schema.Struct({
base: Schema.optional(Schema.String),
file: Schema.String,
})
// kilocode_change end
export const ExperimentalPaths = {
console: "/experimental/console",
@@ -71,6 +86,9 @@ export const ExperimentalPaths = {
tool: "/experimental/tool",
toolIDs: "/experimental/tool/ids",
worktree: "/experimental/worktree",
worktreeDiff: "/experimental/worktree/diff", // kilocode_change
worktreeDiffFile: "/experimental/worktree/diff/file", // kilocode_change
worktreeDiffSummary: "/experimental/worktree/diff/summary", // kilocode_change
worktreeReset: "/experimental/worktree/reset",
session: "/experimental/session",
resource: "/experimental/resource",
@@ -174,6 +192,41 @@ export const ExperimentalApi = HttpApi.make("experimental")
description: "Reset a worktree branch to the primary default branch.",
}),
),
// kilocode_change start - worktree diff endpoints for agent manager
HttpApiEndpoint.get("worktreeDiff", ExperimentalPaths.worktreeDiff, {
query: WorktreeDiffQuery,
success: described(Schema.Array(Snapshot.FileDiff), "File diffs"),
error: HttpApiError.BadRequest,
}).annotateMerge(
OpenApi.annotations({
identifier: "worktree.diff",
summary: "Get worktree diff",
description: "Get file diffs for a worktree compared to its base branch. Includes uncommitted changes.",
}),
),
HttpApiEndpoint.get("worktreeDiffSummary", ExperimentalPaths.worktreeDiffSummary, {
query: WorktreeDiffQuery,
success: described(Schema.Array(WorktreeDiff.Item), "Diff summary items"),
error: HttpApiError.BadRequest,
}).annotateMerge(
OpenApi.annotations({
identifier: "worktree.diffSummary",
summary: "Get worktree diff summary",
description: "Get lightweight file diff metadata for a worktree compared to its base branch.",
}),
),
HttpApiEndpoint.get("worktreeDiffFile", ExperimentalPaths.worktreeDiffFile, {
query: WorktreeDiffFileQuery,
success: described(Schema.NullOr(WorktreeDiff.Item), "Diff detail item"),
error: HttpApiError.BadRequest,
}).annotateMerge(
OpenApi.annotations({
identifier: "worktree.diffFile",
summary: "Get worktree diff detail",
description: "Get full diff contents for one worktree file compared to its base branch.",
}),
),
// kilocode_change end
HttpApiEndpoint.get("session", ExperimentalPaths.session, {
query: SessionListQuery,
success: described(Schema.Array(Session.GlobalInfo), "List of sessions"),
@@ -66,6 +66,12 @@ export const RevertPayload = Schema.Struct(Struct.omit(SessionRevert.RevertInput
export const PermissionResponsePayload = Schema.Struct({
response: Permission.Reply,
})
// kilocode_change start
export const ViewedPayload = Schema.Struct({
focused: Schema.optional(Schema.Array(Schema.String)),
open: Schema.optional(Schema.Array(Schema.String)),
})
// kilocode_change end
export const SessionPaths = {
list: root,
@@ -94,6 +100,7 @@ export const SessionPaths = {
deleteMessage: `${root}/:sessionID/message/:messageID`,
deletePart: `${root}/:sessionID/message/:messageID/part/:partID`,
updatePart: `${root}/:sessionID/message/:messageID/part/:partID`,
viewed: `${root}/viewed`, // kilocode_change
} as const
export const SessionApi = HttpApi.make("session")
@@ -409,6 +416,18 @@ export const SessionApi = HttpApi.make("session")
description: "Update a part in a message.",
}),
),
// kilocode_change start
HttpApiEndpoint.post("viewed", SessionPaths.viewed, {
payload: ViewedPayload,
success: described(Schema.Boolean, "Viewed sessions updated"),
}).annotateMerge(
OpenApi.annotations({
identifier: "session.viewed",
summary: "Set viewed sessions",
description: "Notify the server which sessions the user is currently viewing, or clear all.",
}),
),
// kilocode_change end
)
.annotateMerge(
OpenApi.annotations({
@@ -7,12 +7,24 @@ import { Project } from "@/project/project"
import { Session } from "@/session/session"
import { ToolRegistry } from "@/tool/registry"
import * as EffectZod from "@/util/effect-zod"
import { Filesystem } from "@/util/filesystem" // kilocode_change
import { Review } from "@/kilocode/review/review" // kilocode_change
import { WorktreeDiff } from "@/kilocode/review/worktree-diff" // kilocode_change
import { WorktreeFamily } from "@/kilocode/worktree-family" // kilocode_change
import { Worktree } from "@/worktree"
import { Effect, Option } from "effect"
import * as HttpServerResponse from "effect/unstable/http/HttpServerResponse"
import { HttpApiBuilder, HttpApiError } from "effect/unstable/httpapi"
import * as Log from "@opencode-ai/core/util/log" // kilocode_change
import path from "path" // kilocode_change
import { InstanceHttpApi } from "../api"
import { ConsoleSwitchPayload, SessionListQuery, ToolListQuery } from "../groups/experimental"
import {
ConsoleSwitchPayload,
SessionListQuery,
ToolListQuery,
WorktreeDiffFileQuery,
WorktreeDiffQuery,
} from "../groups/experimental"
export const experimentalHandlers = HttpApiBuilder.group(InstanceHttpApi, "experimental", (handlers) =>
Effect.gen(function* () {
@@ -113,11 +125,67 @@ export const experimentalHandlers = HttpApiBuilder.group(InstanceHttpApi, "exper
return true
})
// kilocode_change start - worktree diff endpoints for agent manager
const base = Effect.fn("ExperimentalHttpApi.worktreeDiffBase")(function* (input: { base?: string }) {
if (input.base) return input.base
return yield* Effect.promise(() => Review.getBaseBranch())
})
const worktreeDiff = Effect.fn("ExperimentalHttpApi.worktreeDiff")(function* (ctx: {
query: typeof WorktreeDiffQuery.Type
}) {
const log = Log.create({ service: "worktree-diff" })
const ref = yield* base(ctx.query)
const dir = yield* InstanceState.directory
log.info("computing diff", { dir, base: ref })
const diffs = yield* Effect.promise(() => WorktreeDiff.full({ dir, base: ref, log }))
return diffs.map((diff) => ({
file: diff.file,
before: diff.before,
after: diff.after,
patch: diff.patch,
additions: diff.additions,
deletions: diff.deletions,
status: diff.status,
}))
})
const worktreeDiffSummary = Effect.fn("ExperimentalHttpApi.worktreeDiffSummary")(function* (ctx: {
query: typeof WorktreeDiffQuery.Type
}) {
const log = Log.create({ service: "worktree-diff" })
const ref = yield* base(ctx.query)
const dir = yield* InstanceState.directory
log.info("computing diff summary", { dir, base: ref })
return yield* Effect.promise(() => WorktreeDiff.summary({ dir, base: ref, log }))
})
const worktreeDiffFile = Effect.fn("ExperimentalHttpApi.worktreeDiffFile")(function* (ctx: {
query: typeof WorktreeDiffFileQuery.Type
}) {
const log = Log.create({ service: "worktree-diff" })
const ref = yield* base(ctx.query)
const dir = yield* InstanceState.directory
log.info("computing diff detail", { dir, base: ref, file: ctx.query.file })
return yield* Effect.promise(() => WorktreeDiff.detail({ dir, base: ref, file: ctx.query.file, log })).pipe(
Effect.map((item) => item ?? null),
)
})
// kilocode_change end
const session = Effect.fn("ExperimentalHttpApi.session")(function* (ctx: { query: typeof SessionListQuery.Type }) {
const limit = ctx.query.limit ?? 100
// kilocode_change start
const state = yield* InstanceState.context
const projectID = ctx.query.worktrees && !ctx.query.projectID ? state.project.id : ctx.query.projectID
const directories = ctx.query.worktrees ? yield* Effect.promise(() => WorktreeFamily.list()) : undefined
const sorted = directories ? [...directories].sort((a, b) => b.length - a.length) : undefined
// kilocode_change end
const sessions = Array.from(
Session.listGlobal({
directory: ctx.query.directory,
projectID, // kilocode_change
directory: ctx.query.worktrees ? undefined : ctx.query.directory, // kilocode_change
directories, // kilocode_change
roots: ctx.query.roots,
start: ctx.query.start,
cursor: ctx.query.cursor,
@@ -126,10 +194,18 @@ export const experimentalHandlers = HttpApiBuilder.group(InstanceHttpApi, "exper
archived: ctx.query.archived,
}),
)
const list = sessions.length > limit ? sessions.slice(0, limit) : sessions
// kilocode_change start - resolve worktree folder name for each session
const result = sorted
? sessions.map((session) => {
const root = sorted.find((dir) => Filesystem.contains(dir, session.directory))
return { ...session, worktreeName: path.basename(root ?? session.directory) }
})
: sessions
const list = result.length > limit ? result.slice(0, limit) : result
// kilocode_change end
return HttpServerResponse.jsonUnsafe(list, {
headers:
sessions.length > limit && list.length > 0
result.length > limit && list.length > 0 // kilocode_change
? { "x-next-cursor": String(list[list.length - 1].time.updated) }
: undefined,
})
@@ -139,17 +215,24 @@ export const experimentalHandlers = HttpApiBuilder.group(InstanceHttpApi, "exper
return yield* mcp.resources()
})
return handlers
.handle("console", getConsole)
.handle("consoleOrgs", listConsoleOrgs)
.handle("consoleSwitch", switchConsole)
.handle("tool", tool)
.handle("toolIDs", toolIDs)
.handle("worktree", worktree)
.handle("worktreeCreate", worktreeCreate)
.handle("worktreeRemove", worktreeRemove)
.handle("worktreeReset", worktreeReset)
.handle("session", session)
.handle("resource", resource)
return (
handlers
.handle("console", getConsole)
.handle("consoleOrgs", listConsoleOrgs)
.handle("consoleSwitch", switchConsole)
.handle("tool", tool)
.handle("toolIDs", toolIDs)
.handle("worktree", worktree)
.handle("worktreeCreate", worktreeCreate)
.handle("worktreeRemove", worktreeRemove)
.handle("worktreeReset", worktreeReset)
// kilocode_change start
.handle("worktreeDiff", worktreeDiff)
.handle("worktreeDiffSummary", worktreeDiffSummary)
.handle("worktreeDiffFile", worktreeDiffFile)
// kilocode_change end
.handle("session", session)
.handle("resource", resource)
)
}),
)
@@ -36,6 +36,7 @@ import {
ShellPayload,
SummarizePayload,
UpdatePayload,
ViewedPayload,
} from "../groups/session"
const mapNotFound = <A, E, R>(self: Effect.Effect<A, E, R>) =>
@@ -360,6 +361,14 @@ export const sessionHandlers = HttpApiBuilder.group(InstanceHttpApi, "session",
return yield* session.updatePart(payload)
})
// kilocode_change start
const viewed = Effect.fn("SessionHttpApi.viewed")(function* (ctx: { payload: typeof ViewedPayload.Type }) {
const { KiloSessions } = yield* Effect.promise(() => import("@/kilo-sessions/kilo-sessions"))
KiloSessions.setViewedSessions({ focused: ctx.payload.focused ?? [], open: ctx.payload.open ?? [] })
return true
})
// kilocode_change end
return handlers
.handle("list", list)
.handle("status", status)
@@ -388,5 +397,6 @@ export const sessionHandlers = HttpApiBuilder.group(InstanceHttpApi, "session",
.handle("deleteMessage", deleteMessage)
.handle("deletePart", deletePart)
.handle("updatePart", updatePart)
.handle("viewed", viewed) // kilocode_change
}),
)
@@ -69,6 +69,9 @@ export const InstanceRoutes = (upgrade: UpgradeWebSocket, opts?: CorsOptions): H
app.get(ExperimentalPaths.worktree, (c) => handler(c.req.raw, context))
app.post(ExperimentalPaths.worktree, (c) => handler(c.req.raw, context))
app.delete(ExperimentalPaths.worktree, (c) => handler(c.req.raw, context))
app.get(ExperimentalPaths.worktreeDiff, (c) => handler(c.req.raw, context)) // kilocode_change
app.get(ExperimentalPaths.worktreeDiffFile, (c) => handler(c.req.raw, context)) // kilocode_change
app.get(ExperimentalPaths.worktreeDiffSummary, (c) => handler(c.req.raw, context)) // kilocode_change
app.post(ExperimentalPaths.worktreeReset, (c) => handler(c.req.raw, context))
app.get(ExperimentalPaths.session, (c) => handler(c.req.raw, context))
app.get(ExperimentalPaths.resource, (c) => handler(c.req.raw, context))
@@ -140,6 +143,7 @@ export const InstanceRoutes = (upgrade: UpgradeWebSocket, opts?: CorsOptions): H
app.delete(SessionPaths.deleteMessage, (c) => handler(c.req.raw, context))
app.delete(SessionPaths.deletePart, (c) => handler(c.req.raw, context))
app.patch(SessionPaths.updatePart, (c) => handler(c.req.raw, context))
app.post(SessionPaths.viewed, (c) => handler(c.req.raw, context)) // kilocode_change
app.post(TuiPaths.appendPrompt, (c) => handler(c.req.raw, context))
app.post(TuiPaths.openHelp, (c) => handler(c.req.raw, context))
app.post(TuiPaths.openSessions, (c) => handler(c.req.raw, context))
+285
View File
@@ -62,6 +62,8 @@ import type {
GlobalUpgradeResponses,
IndexingStatusResponses,
InstanceDisposeResponses,
KiloAudioTranscriptionsErrors,
KiloAudioTranscriptionsResponses,
KiloClawChatCredentialsResponses,
KiloClawStatusErrors,
KiloClawStatusResponses,
@@ -85,6 +87,9 @@ import type {
KilocodeSessionImportProjectResponses,
KilocodeSessionImportSessionErrors,
KilocodeSessionImportSessionResponses,
KiloFimErrors,
KiloFimResponses,
KiloModesResponses,
KiloNotificationsErrors,
KiloNotificationsResponses,
KiloOrganizationSetErrors,
@@ -211,6 +216,7 @@ import type {
SessionUnshareResponses,
SessionUpdateErrors,
SessionUpdateResponses,
SessionViewedResponses,
SubtaskPartInput,
SuggestionAcceptErrors,
SuggestionAcceptResponses,
@@ -261,6 +267,12 @@ import type {
WorktreeCreateErrors,
WorktreeCreateInput,
WorktreeCreateResponses,
WorktreeDiffErrors,
WorktreeDiffFileErrors,
WorktreeDiffFileResponses,
WorktreeDiffResponses,
WorktreeDiffSummaryErrors,
WorktreeDiffSummaryResponses,
WorktreeListResponses,
WorktreeRemoveErrors,
WorktreeRemoveInput,
@@ -853,6 +865,8 @@ export class Session extends HeyApiClient {
parameters?: {
directory?: string
workspace?: string
projectID?: string
worktrees?: "true" | "false"
roots?: boolean | "true" | "false"
start?: number
cursor?: number
@@ -869,6 +883,8 @@ export class Session extends HeyApiClient {
args: [
{ in: "query", key: "directory" },
{ in: "query", key: "workspace" },
{ in: "query", key: "projectID" },
{ in: "query", key: "worktrees" },
{ in: "query", key: "roots" },
{ in: "query", key: "start" },
{ in: "query", key: "cursor" },
@@ -1373,6 +1389,104 @@ export class Worktree extends HeyApiClient {
},
})
}
/**
* Get worktree diff
*
* Get file diffs for a worktree compared to its base branch. Includes uncommitted changes.
*/
public diff<ThrowOnError extends boolean = false>(
parameters?: {
directory?: string
workspace?: string
base?: string
},
options?: Options<never, ThrowOnError>,
) {
const params = buildClientParams(
[parameters],
[
{
args: [
{ in: "query", key: "directory" },
{ in: "query", key: "workspace" },
{ in: "query", key: "base" },
],
},
],
)
return (options?.client ?? this.client).get<WorktreeDiffResponses, WorktreeDiffErrors, ThrowOnError>({
url: "/experimental/worktree/diff",
...options,
...params,
})
}
/**
* Get worktree diff summary
*
* Get lightweight file diff metadata for a worktree compared to its base branch.
*/
public diffSummary<ThrowOnError extends boolean = false>(
parameters?: {
directory?: string
workspace?: string
base?: string
},
options?: Options<never, ThrowOnError>,
) {
const params = buildClientParams(
[parameters],
[
{
args: [
{ in: "query", key: "directory" },
{ in: "query", key: "workspace" },
{ in: "query", key: "base" },
],
},
],
)
return (options?.client ?? this.client).get<WorktreeDiffSummaryResponses, WorktreeDiffSummaryErrors, ThrowOnError>({
url: "/experimental/worktree/diff/summary",
...options,
...params,
})
}
/**
* Get worktree diff detail
*
* Get full diff contents for one worktree file compared to its base branch.
*/
public diffFile<ThrowOnError extends boolean = false>(
parameters: {
directory?: string
workspace?: string
base?: string
file: string
},
options?: Options<never, ThrowOnError>,
) {
const params = buildClientParams(
[parameters],
[
{
args: [
{ in: "query", key: "directory" },
{ in: "query", key: "workspace" },
{ in: "query", key: "base" },
{ in: "query", key: "file" },
],
},
],
)
return (options?.client ?? this.client).get<WorktreeDiffFileResponses, WorktreeDiffFileErrors, ThrowOnError>({
url: "/experimental/worktree/diff/file",
...options,
...params,
})
}
}
export class Find extends HeyApiClient {
@@ -3941,6 +4055,45 @@ export class Session2 extends HeyApiClient {
...params,
})
}
/**
* Set viewed sessions
*
* Notify the server which sessions the user is currently viewing, or clear all.
*/
public viewed<ThrowOnError extends boolean = false>(
parameters?: {
directory?: string
workspace?: string
focused?: Array<string>
open?: Array<string>
},
options?: Options<never, ThrowOnError>,
) {
const params = buildClientParams(
[parameters],
[
{
args: [
{ in: "query", key: "directory" },
{ in: "query", key: "workspace" },
{ in: "body", key: "focused" },
{ in: "body", key: "open" },
],
},
],
)
return (options?.client ?? this.client).post<SessionViewedResponses, unknown, ThrowOnError>({
url: "/session/viewed",
...options,
...params,
headers: {
"Content-Type": "application/json",
...options?.headers,
...params.headers,
},
})
}
}
export class Part extends HeyApiClient {
@@ -4930,6 +5083,58 @@ export class Indexing extends HeyApiClient {
}
}
export class Audio extends HeyApiClient {
/**
* Speech to text transcription
*
* Proxy an audio transcription request to the Kilo Gateway
*/
public transcriptions<ThrowOnError extends boolean = false>(
parameters?: {
directory?: string
workspace?: string
model?: string
input_audio?: {
data: string
format: string
}
language?: string
temperature?: number
},
options?: Options<never, ThrowOnError>,
) {
const params = buildClientParams(
[parameters],
[
{
args: [
{ in: "query", key: "directory" },
{ in: "query", key: "workspace" },
{ in: "body", key: "model" },
{ in: "body", key: "input_audio" },
{ in: "body", key: "language" },
{ in: "body", key: "temperature" },
],
},
],
)
return (options?.client ?? this.client).post<
KiloAudioTranscriptionsResponses,
KiloAudioTranscriptionsErrors,
ThrowOnError
>({
url: "/kilo/audio/transcriptions",
...options,
...params,
headers: {
"Content-Type": "application/json",
...options?.headers,
...params.headers,
},
})
}
}
export class Organization extends HeyApiClient {
/**
* Update Kilo Gateway organization
@@ -5146,6 +5351,81 @@ export class Kilo extends HeyApiClient {
})
}
/**
* Get organization custom modes
*
* Fetch custom modes defined for the current organization
*/
public modes<ThrowOnError extends boolean = false>(
parameters?: {
directory?: string
workspace?: string
},
options?: Options<never, ThrowOnError>,
) {
const params = buildClientParams(
[parameters],
[
{
args: [
{ in: "query", key: "directory" },
{ in: "query", key: "workspace" },
],
},
],
)
return (options?.client ?? this.client).get<KiloModesResponses, unknown, ThrowOnError>({
url: "/kilo/modes",
...options,
...params,
})
}
/**
* FIM completion
*
* Proxy a Fill-in-the-Middle completion request to the Kilo Gateway
*/
public fim<ThrowOnError extends boolean = false>(
parameters?: {
directory?: string
workspace?: string
prefix?: string
suffix?: string
model?: string
maxTokens?: number
temperature?: number
},
options?: Options<never, ThrowOnError>,
) {
const params = buildClientParams(
[parameters],
[
{
args: [
{ in: "query", key: "directory" },
{ in: "query", key: "workspace" },
{ in: "body", key: "prefix" },
{ in: "body", key: "suffix" },
{ in: "body", key: "model" },
{ in: "body", key: "maxTokens" },
{ in: "body", key: "temperature" },
],
},
],
)
return (options?.client ?? this.client).sse.post<KiloFimResponses, KiloFimErrors, ThrowOnError>({
url: "/kilo/fim",
...options,
...params,
headers: {
"Content-Type": "application/json",
...options?.headers,
...params.headers,
},
})
}
/**
* Get Kilo notifications
*
@@ -5212,6 +5492,11 @@ export class Kilo extends HeyApiClient {
})
}
private _audio?: Audio
get audio(): Audio {
return (this._audio ??= new Audio({ client: this.client }))
}
private _organization?: Organization
get organization(): Organization {
return (this._organization ??= new Organization({ client: this.client }))
+244
View File
@@ -1465,6 +1465,20 @@ export type WorktreeResetInput = {
directory: string
}
export type WorktreeDiffItem = {
file: string
patch: string
additions: number
deletions: number
status?: "added" | "deleted" | "modified"
before: string
after: string
tracked: boolean
generatedLike: boolean
summarized: boolean
stamp: string
}
export type ProjectSummary = {
id: string
name?: string
@@ -4077,12 +4091,102 @@ export type WorktreeResetResponses = {
export type WorktreeResetResponse = WorktreeResetResponses[keyof WorktreeResetResponses]
export type WorktreeDiffData = {
body?: never
path?: never
query?: {
directory?: string
workspace?: string
base?: string
}
url: "/experimental/worktree/diff"
}
export type WorktreeDiffErrors = {
/**
* Bad request
*/
400: BadRequestError
}
export type WorktreeDiffError = WorktreeDiffErrors[keyof WorktreeDiffErrors]
export type WorktreeDiffResponses = {
/**
* File diffs
*/
200: Array<SnapshotFileDiff>
}
export type WorktreeDiffResponse = WorktreeDiffResponses[keyof WorktreeDiffResponses]
export type WorktreeDiffSummaryData = {
body?: never
path?: never
query?: {
directory?: string
workspace?: string
base?: string
}
url: "/experimental/worktree/diff/summary"
}
export type WorktreeDiffSummaryErrors = {
/**
* Bad request
*/
400: BadRequestError
}
export type WorktreeDiffSummaryError = WorktreeDiffSummaryErrors[keyof WorktreeDiffSummaryErrors]
export type WorktreeDiffSummaryResponses = {
/**
* Diff summary items
*/
200: Array<WorktreeDiffItem>
}
export type WorktreeDiffSummaryResponse = WorktreeDiffSummaryResponses[keyof WorktreeDiffSummaryResponses]
export type WorktreeDiffFileData = {
body?: never
path?: never
query: {
directory?: string
workspace?: string
base?: string
file: string
}
url: "/experimental/worktree/diff/file"
}
export type WorktreeDiffFileErrors = {
/**
* Bad request
*/
400: BadRequestError
}
export type WorktreeDiffFileError = WorktreeDiffFileErrors[keyof WorktreeDiffFileErrors]
export type WorktreeDiffFileResponses = {
/**
* Diff detail item
*/
200: WorktreeDiffItem
}
export type WorktreeDiffFileResponse = WorktreeDiffFileResponses[keyof WorktreeDiffFileResponses]
export type ExperimentalSessionListData = {
body?: never
path?: never
query?: {
directory?: string
workspace?: string
projectID?: string
worktrees?: "true" | "false"
roots?: boolean | "true" | "false"
start?: number
cursor?: number
@@ -6322,6 +6426,28 @@ export type PartUpdateResponses = {
export type PartUpdateResponse = PartUpdateResponses[keyof PartUpdateResponses]
export type SessionViewedData = {
body?: {
focused?: Array<string>
open?: Array<string>
}
path?: never
query?: {
directory?: string
workspace?: string
}
url: "/session/viewed"
}
export type SessionViewedResponses = {
/**
* Viewed sessions updated
*/
200: boolean
}
export type SessionViewedResponse = SessionViewedResponses[keyof SessionViewedResponses]
export type SyncStartData = {
body?: never
path?: never
@@ -7172,6 +7298,124 @@ export type KiloProfileResponses = {
export type KiloProfileResponse = KiloProfileResponses[keyof KiloProfileResponses]
export type KiloModesData = {
body?: never
path?: never
query?: {
directory?: string
workspace?: string
}
url: "/kilo/modes"
}
export type KiloModesResponses = {
/**
* Organization modes list
*/
200: {
modes: Array<{
id: string
organization_id: string
name: string
slug: string
created_by: string
created_at: string
updated_at: string
config: {
roleDefinition?: string
whenToUse?: string
description?: string
customInstructions?: string
groups?: Array<
| string
| [
string,
{
fileRegex?: string | null
description?: string | null
},
]
>
}
}>
}
}
export type KiloModesResponse = KiloModesResponses[keyof KiloModesResponses]
export type KiloFimData = {
body?: {
prefix: string
suffix: string
model?: string
maxTokens?: number
temperature?: number
}
path?: never
query?: {
directory?: string
workspace?: string
}
url: "/kilo/fim"
}
export type KiloFimErrors = {
/**
* Bad request
*/
400: BadRequestError
}
export type KiloFimError = KiloFimErrors[keyof KiloFimErrors]
export type KiloFimResponses = {
/**
* Success
*/
200: string
}
export type KiloFimResponse = KiloFimResponses[keyof KiloFimResponses]
export type KiloAudioTranscriptionsData = {
body?: {
model: string
input_audio: {
data: string
format: string
}
language?: string
temperature?: number
}
path?: never
query?: {
directory?: string
workspace?: string
}
url: "/kilo/audio/transcriptions"
}
export type KiloAudioTranscriptionsErrors = {
/**
* Bad request
*/
400: BadRequestError
}
export type KiloAudioTranscriptionsError = KiloAudioTranscriptionsErrors[keyof KiloAudioTranscriptionsErrors]
export type KiloAudioTranscriptionsResponses = {
/**
* Transcription response
*/
200: {
text: string
usage?: unknown
}
}
export type KiloAudioTranscriptionsResponse = KiloAudioTranscriptionsResponses[keyof KiloAudioTranscriptionsResponses]
export type KiloNotificationsData = {
body?: never
path?: never
+675
View File
@@ -1253,6 +1253,208 @@
]
}
},
"/experimental/worktree/diff": {
"get": {
"tags": ["experimental"],
"operationId": "worktree.diff",
"parameters": [
{
"name": "directory",
"in": "query",
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "workspace",
"in": "query",
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "base",
"in": "query",
"schema": {
"type": "string"
},
"required": false
}
],
"responses": {
"200": {
"description": "File diffs",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/SnapshotFileDiff"
},
"description": "File diffs"
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/BadRequestError"
}
}
}
}
},
"description": "Get file diffs for a worktree compared to its base branch. Includes uncommitted changes.",
"summary": "Get worktree diff",
"x-codeSamples": [
{
"lang": "js",
"source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.worktree.diff({\n ...\n})"
}
]
}
},
"/experimental/worktree/diff/summary": {
"get": {
"tags": ["experimental"],
"operationId": "worktree.diffSummary",
"parameters": [
{
"name": "directory",
"in": "query",
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "workspace",
"in": "query",
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "base",
"in": "query",
"schema": {
"type": "string"
},
"required": false
}
],
"responses": {
"200": {
"description": "Diff summary items",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/WorktreeDiffItem"
},
"description": "Diff summary items"
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/BadRequestError"
}
}
}
}
},
"description": "Get lightweight file diff metadata for a worktree compared to its base branch.",
"summary": "Get worktree diff summary",
"x-codeSamples": [
{
"lang": "js",
"source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.worktree.diffSummary({\n ...\n})"
}
]
}
},
"/experimental/worktree/diff/file": {
"get": {
"tags": ["experimental"],
"operationId": "worktree.diffFile",
"parameters": [
{
"name": "directory",
"in": "query",
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "workspace",
"in": "query",
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "base",
"in": "query",
"schema": {
"type": "string"
},
"required": false
},
{
"name": "file",
"in": "query",
"schema": {
"type": "string"
},
"required": true
}
],
"responses": {
"200": {
"description": "Diff detail item",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WorktreeDiffItem"
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/BadRequestError"
}
}
}
}
},
"description": "Get full diff contents for one worktree file compared to its base branch.",
"summary": "Get worktree diff detail",
"x-codeSamples": [
{
"lang": "js",
"source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.worktree.diffFile({\n ...\n})"
}
]
}
},
"/experimental/session": {
"get": {
"tags": ["experimental"],
@@ -1274,6 +1476,23 @@
"type": "string"
}
},
{
"name": "projectID",
"in": "query",
"schema": {
"type": "string"
},
"required": false
},
{
"name": "worktrees",
"in": "query",
"schema": {
"type": "string",
"enum": ["true", "false"]
},
"required": false
},
{
"name": "roots",
"in": "query",
@@ -6917,6 +7136,75 @@
]
}
},
"/session/viewed": {
"post": {
"tags": ["session"],
"operationId": "session.viewed",
"parameters": [
{
"name": "directory",
"in": "query",
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "workspace",
"in": "query",
"required": false,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Viewed sessions updated",
"content": {
"application/json": {
"schema": {
"type": "boolean",
"description": "Viewed sessions updated"
}
}
}
}
},
"description": "Notify the server which sessions the user is currently viewing, or clear all.",
"summary": "Set viewed sessions",
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"focused": {
"type": "array",
"items": {
"type": "string"
}
},
"open": {
"type": "array",
"items": {
"type": "string"
}
}
},
"additionalProperties": false
}
}
}
},
"x-codeSamples": [
{
"lang": "js",
"source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.session.viewed({\n ...\n})"
}
]
}
},
"/sync/start": {
"post": {
"tags": ["sync"],
@@ -8967,6 +9255,339 @@
]
}
},
"/kilo/modes": {
"get": {
"tags": ["kilo"],
"operationId": "kilo.modes",
"parameters": [
{
"name": "directory",
"in": "query",
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "workspace",
"in": "query",
"required": false,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Organization modes list",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"modes": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"organization_id": {
"type": "string"
},
"name": {
"type": "string"
},
"slug": {
"type": "string"
},
"created_by": {
"type": "string"
},
"created_at": {
"type": "string"
},
"updated_at": {
"type": "string"
},
"config": {
"type": "object",
"properties": {
"roleDefinition": {
"type": "string"
},
"whenToUse": {
"type": "string"
},
"description": {
"type": "string"
},
"customInstructions": {
"type": "string"
},
"groups": {
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "array",
"prefixItems": [
{
"type": "string"
},
{
"type": "object",
"properties": {
"fileRegex": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
}
],
"maxItems": 2,
"minItems": 2
}
]
}
}
},
"additionalProperties": false
}
},
"required": [
"id",
"organization_id",
"name",
"slug",
"created_by",
"created_at",
"updated_at",
"config"
],
"additionalProperties": false
}
}
},
"required": ["modes"],
"additionalProperties": false,
"description": "Organization modes list"
}
}
}
}
},
"description": "Fetch custom modes defined for the current organization",
"summary": "Get organization custom modes",
"x-codeSamples": [
{
"lang": "js",
"source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.kilo.modes({\n ...\n})"
}
]
}
},
"/kilo/fim": {
"post": {
"tags": ["kilo"],
"operationId": "kilo.fim",
"parameters": [
{
"name": "directory",
"in": "query",
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "workspace",
"in": "query",
"required": false,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Success",
"content": {
"text/event-stream": {
"schema": {
"type": "string"
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/BadRequestError"
}
}
}
}
},
"description": "Proxy a Fill-in-the-Middle completion request to the Kilo Gateway",
"summary": "FIM completion",
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"prefix": {
"type": "string"
},
"suffix": {
"type": "string"
},
"model": {
"type": "string"
},
"maxTokens": {
"type": "number"
},
"temperature": {
"type": "number"
}
},
"required": ["prefix", "suffix"],
"additionalProperties": false
}
}
}
},
"x-codeSamples": [
{
"lang": "js",
"source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.kilo.fim({\n ...\n})"
}
]
}
},
"/kilo/audio/transcriptions": {
"post": {
"tags": ["kilo"],
"operationId": "kilo.audio.transcriptions",
"parameters": [
{
"name": "directory",
"in": "query",
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "workspace",
"in": "query",
"required": false,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Transcription response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"text": {
"type": "string"
},
"usage": {}
},
"required": ["text"],
"additionalProperties": false,
"description": "Transcription response"
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/BadRequestError"
}
}
}
}
},
"description": "Proxy an audio transcription request to the Kilo Gateway",
"summary": "Speech to text transcription",
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"model": {
"type": "string"
},
"input_audio": {
"type": "object",
"properties": {
"data": {
"type": "string"
},
"format": {
"type": "string"
}
},
"required": ["data", "format"],
"additionalProperties": false
},
"language": {
"type": "string"
},
"temperature": {
"type": "number"
}
},
"required": ["model", "input_audio"],
"additionalProperties": false
}
}
}
},
"x-codeSamples": [
{
"lang": "js",
"source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.kilo.audio.transcriptions({\n ...\n})"
}
]
}
},
"/kilo/notifications": {
"get": {
"tags": ["kilo"],
@@ -15586,6 +16207,60 @@
"required": ["directory"],
"additionalProperties": false
},
"WorktreeDiffItem": {
"type": "object",
"properties": {
"file": {
"type": "string"
},
"patch": {
"type": "string"
},
"additions": {
"type": "integer",
"minimum": 0
},
"deletions": {
"type": "integer",
"minimum": 0
},
"status": {
"type": "string",
"enum": ["added", "deleted", "modified"]
},
"before": {
"type": "string"
},
"after": {
"type": "string"
},
"tracked": {
"type": "boolean"
},
"generatedLike": {
"type": "boolean"
},
"summarized": {
"type": "boolean"
},
"stamp": {
"type": "string"
}
},
"required": [
"file",
"patch",
"additions",
"deletions",
"before",
"after",
"tracked",
"generatedLike",
"summarized",
"stamp"
],
"additionalProperties": false
},
"ProjectSummary": {
"type": "object",
"properties": {