mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-09-24 16:02:55 +08:00
refactor(kilo-gateway): extract cloud sessions logic and wire up cloud sync endpoints
Move inline cloud-sessions fetch logic from Hono route handler into a reusable getCloudSessions function in handlers.ts, and introduce new Effect HttpApi endpoints for fetching and importing individual cloud sessions. - Extract getCloudSessions handler from routes.ts inline implementation - Export fetchCloudSession, fetchCloudSessionForImport, importSessionToDb from kilo-gateway package - Add cloudSession (GET /kilo/cloud/session/:id) endpoint for previewing remote session data - Add cloudSessionImport (POST /kilo/cloud/session/import) endpoint to download and persist cloud sessions locally - Define CloudSession, CloudSessionData, CloudMessage schemas in the kilo-gateway API group - Change claw status error response from 500 InternalServerError to 503 ServiceUnavailable - Register new cloud routes in instance router - Add test coverage for route disambiguation between import and :id paths - Regenerate SDK types and OpenAPI spec
This commit is contained in:
@@ -48,6 +48,7 @@ export {
|
||||
type OrganizationModeConfig,
|
||||
} from "./api/modes.js"
|
||||
export { fetchKilocodeNotifications, type KilocodeNotification } from "./api/notifications.js"
|
||||
export { fetchCloudSession, fetchCloudSessionForImport, importSessionToDb } from "./cloud-sessions.js"
|
||||
|
||||
// ============================================================================
|
||||
// Server Routes (optional - requires hono and OpenCode dependencies)
|
||||
@@ -59,6 +60,7 @@ export {
|
||||
getOrganizationId,
|
||||
getClawChatCredentials,
|
||||
getClawStatus,
|
||||
getCloudSessions,
|
||||
getNotifications,
|
||||
getProfile,
|
||||
getToken,
|
||||
|
||||
@@ -3,6 +3,7 @@ import { fetchKilocodeNotifications } from "../api/notifications.js"
|
||||
import { clearModesCache } from "../api/modes.js"
|
||||
import { HEADER_ORGANIZATIONID, KILO_API_BASE, KILO_CHAT_URL, KILO_EVENT_SERVICE_URL } from "../api/constants.js"
|
||||
import type { KilocodeBalance, KilocodeProfile } from "../types.js"
|
||||
import { buildKiloHeaders } from "../headers.js"
|
||||
|
||||
export type KiloAuth =
|
||||
| { type: "api"; key: string }
|
||||
@@ -33,6 +34,12 @@ export interface OrganizationDeps {
|
||||
dispose(): Promise<void>
|
||||
}
|
||||
|
||||
export interface CloudSessionsInput {
|
||||
cursor?: string
|
||||
limit?: number
|
||||
gitUrl?: string
|
||||
}
|
||||
|
||||
export class UnauthorizedError extends Error {}
|
||||
|
||||
export class GatewayError extends Error {
|
||||
@@ -126,3 +133,58 @@ export async function getClawChatCredentials(auth: AuthStore): Promise<ClawChatC
|
||||
eventServiceUrl: KILO_EVENT_SERVICE_URL,
|
||||
}
|
||||
}
|
||||
|
||||
export async function getCloudSessions(token: string, input: CloudSessionsInput) {
|
||||
const query: Record<string, unknown> = {}
|
||||
if (input.cursor) query.cursor = input.cursor
|
||||
if (input.limit) query.limit = input.limit
|
||||
if (input.gitUrl) query.gitUrl = input.gitUrl
|
||||
|
||||
const params = new URLSearchParams({
|
||||
batch: "1",
|
||||
input: JSON.stringify({ "0": query }),
|
||||
})
|
||||
|
||||
const response = await fetch(`${KILO_API_BASE}/api/trpc/cliSessionsV2.list?${params.toString()}`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
"Content-Type": "application/json",
|
||||
...buildKiloHeaders(),
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const text = await response.text()
|
||||
console.error("[Kilo Gateway] cloud-sessions: tRPC request failed", {
|
||||
status: response.status,
|
||||
body: text.slice(0, 500),
|
||||
})
|
||||
throw new GatewayError(`Cloud sessions fetch failed: ${response.status}`, response.status)
|
||||
}
|
||||
|
||||
const raw = await response.text()
|
||||
const json = JSON.parse(raw)
|
||||
const data = Array.isArray(json) ? json[0]?.result?.data : null
|
||||
const result = data?.json ?? data
|
||||
if (!result) return { cliSessions: [], nextCursor: null }
|
||||
|
||||
const cliSessions = (result.cliSessions ?? []).map((item: any) => ({
|
||||
session_id: item.session_id,
|
||||
title: item.title ?? null,
|
||||
created_at:
|
||||
typeof item.created_at === "string"
|
||||
? item.created_at
|
||||
: item.created_at
|
||||
? new Date(item.created_at).toISOString()
|
||||
: new Date().toISOString(),
|
||||
updated_at:
|
||||
typeof item.updated_at === "string"
|
||||
? item.updated_at
|
||||
: item.updated_at
|
||||
? new Date(item.updated_at).toISOString()
|
||||
: new Date().toISOString(),
|
||||
version: item.version ?? 0,
|
||||
}))
|
||||
|
||||
return { cliSessions, nextCursor: result.nextCursor ?? null }
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
UnauthorizedError,
|
||||
getClawChatCredentials,
|
||||
getClawStatus,
|
||||
getCloudSessions,
|
||||
getNotifications,
|
||||
getProfile,
|
||||
setOrganization,
|
||||
@@ -710,63 +711,9 @@ export function createKiloRoutes(deps: KiloRoutesDeps) {
|
||||
const token = auth.type === "api" ? auth.key : auth.type === "oauth" ? auth.access : undefined
|
||||
if (!token) return c.json({ error: "No valid token found" }, 401)
|
||||
|
||||
const { cursor, limit, gitUrl } = c.req.valid("query")
|
||||
|
||||
const input: Record<string, unknown> = {}
|
||||
if (cursor) input.cursor = cursor
|
||||
if (limit) input.limit = limit
|
||||
if (gitUrl) input.gitUrl = gitUrl
|
||||
|
||||
const params = new URLSearchParams({
|
||||
batch: "1",
|
||||
input: JSON.stringify({ "0": input }),
|
||||
})
|
||||
|
||||
const url = `${KILO_API_BASE}/api/trpc/cliSessionsV2.list?${params.toString()}`
|
||||
|
||||
const response = await fetch(url, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
"Content-Type": "application/json",
|
||||
...buildKiloHeaders(),
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const text = await response.text()
|
||||
console.error("[Kilo Gateway] cloud-sessions: tRPC request failed", {
|
||||
status: response.status,
|
||||
body: text.slice(0, 500),
|
||||
})
|
||||
return c.json({ error: `Cloud sessions fetch failed: ${response.status}` }, response.status as any)
|
||||
}
|
||||
|
||||
const raw = await response.text()
|
||||
const json = JSON.parse(raw)
|
||||
const data = Array.isArray(json) ? json[0]?.result?.data : null
|
||||
const result = data?.json ?? data
|
||||
if (!result) return c.json({ cliSessions: [], nextCursor: null })
|
||||
|
||||
const sessions = (result.cliSessions ?? []).map((s: any) => ({
|
||||
session_id: s.session_id,
|
||||
title: s.title ?? null,
|
||||
created_at:
|
||||
typeof s.created_at === "string"
|
||||
? s.created_at
|
||||
: s.created_at
|
||||
? new Date(s.created_at).toISOString()
|
||||
: new Date().toISOString(),
|
||||
updated_at:
|
||||
typeof s.updated_at === "string"
|
||||
? s.updated_at
|
||||
: s.updated_at
|
||||
? new Date(s.updated_at).toISOString()
|
||||
: new Date().toISOString(),
|
||||
version: s.version ?? 0,
|
||||
}))
|
||||
|
||||
return c.json({ cliSessions: sessions, nextCursor: result.nextCursor ?? null })
|
||||
return c.json(await getCloudSessions(token, c.req.valid("query")))
|
||||
} catch (err: any) {
|
||||
if (err instanceof GatewayError) return c.json({ error: err.message }, err.status as any)
|
||||
console.error("[Kilo Gateway] cloud-sessions: unhandled error", err?.message ?? err)
|
||||
return c.json({ error: "Internal error" }, 500)
|
||||
}
|
||||
|
||||
@@ -86,12 +86,64 @@ export const ClawChatCredentials = Schema.NullOr(
|
||||
}),
|
||||
)
|
||||
|
||||
export const CloudSession = Schema.Struct({
|
||||
session_id: Schema.String,
|
||||
title: Schema.NullOr(Schema.String),
|
||||
created_at: Schema.String,
|
||||
updated_at: Schema.String,
|
||||
version: Schema.Finite,
|
||||
})
|
||||
|
||||
export const CloudSessions = Schema.Struct({
|
||||
cliSessions: Schema.Array(CloudSession),
|
||||
nextCursor: Schema.NullOr(Schema.String),
|
||||
})
|
||||
|
||||
export const CloudSessionImportBody = Schema.Struct({
|
||||
sessionId: Schema.String,
|
||||
})
|
||||
|
||||
export const CloudMessage = Schema.Struct({
|
||||
info: Schema.Struct({
|
||||
id: Schema.String,
|
||||
sessionID: Schema.String,
|
||||
role: Schema.Literals(["user", "assistant"]),
|
||||
time: Schema.Struct({
|
||||
created: Schema.Finite,
|
||||
completed: Schema.optional(Schema.Finite),
|
||||
}),
|
||||
}),
|
||||
parts: Schema.Array(
|
||||
Schema.Struct({
|
||||
id: Schema.String,
|
||||
sessionID: Schema.String,
|
||||
messageID: Schema.String,
|
||||
type: Schema.String,
|
||||
}),
|
||||
),
|
||||
})
|
||||
|
||||
export const CloudSessionData = Schema.Struct({
|
||||
info: Schema.Struct({
|
||||
id: Schema.String,
|
||||
title: Schema.String,
|
||||
time: Schema.Struct({
|
||||
created: Schema.Finite,
|
||||
updated: Schema.Finite,
|
||||
}),
|
||||
}),
|
||||
messages: Schema.Array(CloudMessage),
|
||||
})
|
||||
|
||||
export const KiloGatewayPaths = {
|
||||
profile: `${root}/profile`,
|
||||
notifications: `${root}/notifications`,
|
||||
organization: `${root}/organization`,
|
||||
clawStatus: `${root}/claw/status`,
|
||||
clawChatCredentials: `${root}/claw/chat-credentials`,
|
||||
cloudSessions: `${root}/cloud-sessions`,
|
||||
cloudSession: `${root}/cloud/session/:id`,
|
||||
cloudSessionImport: `${root}/cloud/session/import`,
|
||||
} as const
|
||||
|
||||
export const KiloGatewayApi = HttpApi.make("kilo")
|
||||
@@ -152,6 +204,43 @@ export const KiloGatewayApi = HttpApi.make("kilo")
|
||||
"event-service both verify it directly with NEXTAUTH_SECRET, so no separate token mint is needed.",
|
||||
}),
|
||||
),
|
||||
HttpApiEndpoint.get("cloudSessions", KiloGatewayPaths.cloudSessions, {
|
||||
query: {
|
||||
cursor: Schema.optional(Schema.String),
|
||||
limit: Schema.optional(Schema.String),
|
||||
gitUrl: Schema.optional(Schema.String),
|
||||
},
|
||||
success: described(CloudSessions, "Cloud sessions list"),
|
||||
error: [HttpApiError.BadRequest, HttpApiError.Unauthorized],
|
||||
}).annotateMerge(
|
||||
OpenApi.annotations({
|
||||
identifier: "kilo.cloudSessions",
|
||||
summary: "Get cloud sessions",
|
||||
description: "Fetch cloud CLI sessions from Kilo API",
|
||||
}),
|
||||
),
|
||||
HttpApiEndpoint.get("cloudSession", KiloGatewayPaths.cloudSession, {
|
||||
params: { id: Schema.String },
|
||||
success: described(CloudSessionData, "Cloud session data"),
|
||||
error: [HttpApiError.Unauthorized, HttpApiError.NotFound],
|
||||
}).annotateMerge(
|
||||
OpenApi.annotations({
|
||||
identifier: "kilo.cloud.session.get",
|
||||
summary: "Get cloud session",
|
||||
description: "Fetch full session data from the Kilo cloud for preview",
|
||||
}),
|
||||
),
|
||||
HttpApiEndpoint.post("cloudSessionImport", KiloGatewayPaths.cloudSessionImport, {
|
||||
payload: CloudSessionImportBody,
|
||||
success: described(CloudSessionData.fields.info, "Imported session info"),
|
||||
error: [HttpApiError.BadRequest, HttpApiError.Unauthorized, HttpApiError.NotFound],
|
||||
}).annotateMerge(
|
||||
OpenApi.annotations({
|
||||
identifier: "kilo.cloud.session.import",
|
||||
summary: "Import session from cloud",
|
||||
description: "Download a cloud-synced session and write it to local storage with fresh IDs.",
|
||||
}),
|
||||
),
|
||||
)
|
||||
.annotateMerge(
|
||||
OpenApi.annotations({
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
import { GatewayError, UnauthorizedError, getOrganizationId, getToken } from "@kilocode/kilo-gateway"
|
||||
import {
|
||||
GatewayError,
|
||||
fetchCloudSession,
|
||||
fetchCloudSessionForImport,
|
||||
getCloudSessions,
|
||||
getOrganizationId,
|
||||
getToken,
|
||||
importSessionToDb,
|
||||
} from "@kilocode/kilo-gateway"
|
||||
import {
|
||||
HEADER_ORGANIZATIONID,
|
||||
KILO_API_BASE,
|
||||
@@ -12,9 +20,15 @@ import {
|
||||
import { Effect } from "effect"
|
||||
import { HttpApiBuilder, HttpApiError } from "effect/unstable/httpapi"
|
||||
import { Auth } from "@/auth"
|
||||
import { Bus } from "@/bus"
|
||||
import { Identifier } from "@/id/id"
|
||||
import { Instance } from "@/project/instance"
|
||||
import { InstanceStore } from "@/project/instance-store"
|
||||
import { ModelCache } from "@/provider/model-cache"
|
||||
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"
|
||||
|
||||
export const kiloGatewayHandlers = HttpApiBuilder.group(InstanceHttpApi, "kilo", (handlers) =>
|
||||
Effect.gen(function* () {
|
||||
@@ -85,7 +99,7 @@ export const kiloGatewayHandlers = HttpApiBuilder.group(InstanceHttpApi, "kilo",
|
||||
return response.json()
|
||||
},
|
||||
catch: (err) =>
|
||||
err instanceof UnauthorizedError
|
||||
err instanceof GatewayError && err.status === 401
|
||||
? new HttpApiError.Unauthorized({})
|
||||
: new HttpApiError.ServiceUnavailable({}),
|
||||
})
|
||||
@@ -105,11 +119,71 @@ export const kiloGatewayHandlers = HttpApiBuilder.group(InstanceHttpApi, "kilo",
|
||||
}
|
||||
})
|
||||
|
||||
const cloudSessions = Effect.fn("KiloGatewayHttpApi.cloudSessions")(function* (ctx) {
|
||||
const info = yield* auth.get("kilo").pipe(Effect.mapError(() => new HttpApiError.BadRequest({})))
|
||||
const token = getToken(info)
|
||||
if (!token) return yield* Effect.fail(new HttpApiError.Unauthorized({}))
|
||||
|
||||
const query = {
|
||||
...ctx.query,
|
||||
limit: ctx.query.limit === undefined ? undefined : Number(ctx.query.limit),
|
||||
}
|
||||
|
||||
return yield* Effect.tryPromise({
|
||||
try: () => getCloudSessions(token, query),
|
||||
catch: (err) =>
|
||||
err instanceof GatewayError && err.status === 401
|
||||
? new HttpApiError.Unauthorized({})
|
||||
: new HttpApiError.BadRequest({}),
|
||||
})
|
||||
})
|
||||
|
||||
const cloudSession = Effect.fn("KiloGatewayHttpApi.cloudSession")(function* (ctx) {
|
||||
const info = yield* auth.get("kilo").pipe(Effect.mapError(() => new HttpApiError.Unauthorized({})))
|
||||
const token = getToken(info)
|
||||
if (!token) return yield* Effect.fail(new HttpApiError.Unauthorized({}))
|
||||
|
||||
const result = yield* Effect.promise(() => fetchCloudSession(token, ctx.params.id))
|
||||
if (!result.ok && result.status === 404) return yield* Effect.fail(new HttpApiError.NotFound({}))
|
||||
if (!result.ok) return yield* Effect.fail(new HttpApiError.Unauthorized({}))
|
||||
return result.data
|
||||
})
|
||||
|
||||
const cloudSessionImport = Effect.fn("KiloGatewayHttpApi.cloudSessionImport")(function* (ctx) {
|
||||
const info = yield* auth.get("kilo").pipe(Effect.mapError(() => new HttpApiError.Unauthorized({})))
|
||||
const token = getToken(info)
|
||||
if (!token) return yield* Effect.fail(new HttpApiError.Unauthorized({}))
|
||||
|
||||
const fetched = yield* Effect.promise(() => fetchCloudSessionForImport(token, ctx.payload.sessionId))
|
||||
if (!fetched.ok && fetched.status === 404) return yield* Effect.fail(new HttpApiError.NotFound({}))
|
||||
if (!fetched.ok) return yield* Effect.fail(new HttpApiError.BadRequest({}))
|
||||
if (!fetched.data?.info?.id) return yield* Effect.fail(new HttpApiError.BadRequest({}))
|
||||
|
||||
return yield* Effect.try({
|
||||
try: () =>
|
||||
importSessionToDb(fetched.data, {
|
||||
Database,
|
||||
Instance,
|
||||
SessionTable,
|
||||
MessageTable,
|
||||
PartTable,
|
||||
SessionToRow: Session.toRow,
|
||||
Bus,
|
||||
SessionCreatedEvent: Session.Event.Created,
|
||||
Identifier,
|
||||
}),
|
||||
catch: () => new HttpApiError.BadRequest({}),
|
||||
})
|
||||
})
|
||||
|
||||
return handlers
|
||||
.handle("profile", profile)
|
||||
.handle("notifications", notifications)
|
||||
.handle("organization", organization)
|
||||
.handle("clawStatus", clawStatus)
|
||||
.handle("clawChatCredentials", clawChatCredentials)
|
||||
.handle("cloudSessions", cloudSessions)
|
||||
.handle("cloudSession", cloudSession)
|
||||
.handle("cloudSessionImport", cloudSessionImport)
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -39,6 +39,9 @@ export function register(app: Hono, handler: Handler, context: Context.Context<u
|
||||
app.post(KiloGatewayPaths.organization, (c) => handler(c.req.raw, context))
|
||||
app.get(KiloGatewayPaths.clawStatus, (c) => handler(c.req.raw, context))
|
||||
app.get(KiloGatewayPaths.clawChatCredentials, (c) => handler(c.req.raw, context))
|
||||
app.get(KiloGatewayPaths.cloudSessions, (c) => handler(c.req.raw, context))
|
||||
app.get(KiloGatewayPaths.cloudSession, (c) => handler(c.req.raw, context))
|
||||
app.post(KiloGatewayPaths.cloudSessionImport, (c) => handler(c.req.raw, context))
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ const QueryNumberParameters = new Set(["start", "cursor", "limit", "method"])
|
||||
const QueryBooleanParameters = new Set(["roots", "archived"])
|
||||
const QueryParameterSchemas = {
|
||||
"GET /find/file limit": { type: "integer", minimum: 1, maximum: 200 },
|
||||
"GET /kilo/cloud-sessions cursor": { type: "string" }, // kilocode_change
|
||||
"GET /session/{sessionID}/diff messageID": { type: "string", pattern: "^msg.*" },
|
||||
"GET /session/{sessionID}/message limit": { type: "integer", minimum: 0, maximum: Number.MAX_SAFE_INTEGER },
|
||||
} satisfies Record<string, OpenApiSchema>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Instance } from "../../src/project/instance"
|
||||
import { ControlPaths } from "../../src/server/routes/instance/httpapi/groups/control"
|
||||
import { FilePaths } from "../../src/server/routes/instance/httpapi/groups/file"
|
||||
import { GlobalPaths } from "../../src/server/routes/instance/httpapi/groups/global"
|
||||
import { KiloGatewayPaths } from "../../src/kilocode/server/httpapi/groups/kilo-gateway"
|
||||
import { PublicApi } from "../../src/server/routes/instance/httpapi/public"
|
||||
import { ExperimentalHttpApiServer } from "../../src/server/routes/instance/httpapi/server"
|
||||
import { Server } from "../../src/server/server"
|
||||
@@ -292,10 +293,10 @@ describe("HttpApi server", () => {
|
||||
"POST /kilocode/session-import/session",
|
||||
"POST /kilocode/session-import/message",
|
||||
"POST /kilocode/session-import/part",
|
||||
"GET /indexing/status",
|
||||
]
|
||||
expect(kilo.filter((route) => !hono.has(route))).toEqual([])
|
||||
expect(kilo.filter((route) => !effect.has(route))).toEqual([])
|
||||
expect(effect.has("GET /indexing/status")).toBe(true)
|
||||
})
|
||||
// kilocode_change end
|
||||
|
||||
@@ -334,6 +335,16 @@ describe("HttpApi server", () => {
|
||||
expect(time?.properties?.archived).toEqual({ type: "number" })
|
||||
})
|
||||
|
||||
// kilocode_change start - cloud session literal route must not be swallowed by :id.
|
||||
test("documents cloud session import separately from session id lookup", () => {
|
||||
const effect = effectOpenApi()
|
||||
|
||||
expect(effect.paths["/kilo/cloud/session/import"]?.post).toBeDefined()
|
||||
expect(effect.paths["/kilo/cloud/session/{id}"]?.get).toBeDefined()
|
||||
expect(KiloGatewayPaths.cloudSessionImport).not.toBe(KiloGatewayPaths.cloudSession)
|
||||
})
|
||||
// kilocode_change end
|
||||
|
||||
test("documents event routes as server-sent events", () => {
|
||||
const effect = effectOpenApi()
|
||||
|
||||
|
||||
@@ -65,6 +65,12 @@ import type {
|
||||
KiloClawChatCredentialsResponses,
|
||||
KiloClawStatusErrors,
|
||||
KiloClawStatusResponses,
|
||||
KiloCloudSessionGetErrors,
|
||||
KiloCloudSessionGetResponses,
|
||||
KiloCloudSessionImportErrors,
|
||||
KiloCloudSessionImportResponses,
|
||||
KiloCloudSessionsErrors,
|
||||
KiloCloudSessionsResponses,
|
||||
KilocodeHeapSnapshotErrors,
|
||||
KilocodeHeapSnapshotResponses,
|
||||
KilocodeRemoveAgentErrors,
|
||||
@@ -5027,6 +5033,88 @@ export class Claw extends HeyApiClient {
|
||||
}
|
||||
}
|
||||
|
||||
export class Session4 extends HeyApiClient {
|
||||
/**
|
||||
* Get cloud session
|
||||
*
|
||||
* Fetch full session data from the Kilo cloud for preview
|
||||
*/
|
||||
public get<ThrowOnError extends boolean = false>(
|
||||
parameters: {
|
||||
id: string
|
||||
directory?: string
|
||||
workspace?: string
|
||||
},
|
||||
options?: Options<never, ThrowOnError>,
|
||||
) {
|
||||
const params = buildClientParams(
|
||||
[parameters],
|
||||
[
|
||||
{
|
||||
args: [
|
||||
{ in: "path", key: "id" },
|
||||
{ in: "query", key: "directory" },
|
||||
{ in: "query", key: "workspace" },
|
||||
],
|
||||
},
|
||||
],
|
||||
)
|
||||
return (options?.client ?? this.client).get<KiloCloudSessionGetResponses, KiloCloudSessionGetErrors, ThrowOnError>({
|
||||
url: "/kilo/cloud/session/{id}",
|
||||
...options,
|
||||
...params,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Import session from cloud
|
||||
*
|
||||
* Download a cloud-synced session and write it to local storage with fresh IDs.
|
||||
*/
|
||||
public import<ThrowOnError extends boolean = false>(
|
||||
parameters?: {
|
||||
directory?: string
|
||||
workspace?: string
|
||||
sessionId?: string
|
||||
},
|
||||
options?: Options<never, ThrowOnError>,
|
||||
) {
|
||||
const params = buildClientParams(
|
||||
[parameters],
|
||||
[
|
||||
{
|
||||
args: [
|
||||
{ in: "query", key: "directory" },
|
||||
{ in: "query", key: "workspace" },
|
||||
{ in: "body", key: "sessionId" },
|
||||
],
|
||||
},
|
||||
],
|
||||
)
|
||||
return (options?.client ?? this.client).post<
|
||||
KiloCloudSessionImportResponses,
|
||||
KiloCloudSessionImportErrors,
|
||||
ThrowOnError
|
||||
>({
|
||||
url: "/kilo/cloud/session/import",
|
||||
...options,
|
||||
...params,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...options?.headers,
|
||||
...params.headers,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export class Cloud extends HeyApiClient {
|
||||
private _session?: Session4
|
||||
get session(): Session4 {
|
||||
return (this._session ??= new Session4({ client: this.client }))
|
||||
}
|
||||
}
|
||||
|
||||
export class Kilo extends HeyApiClient {
|
||||
/**
|
||||
* Get Kilo Gateway profile
|
||||
@@ -5088,6 +5176,42 @@ export class Kilo extends HeyApiClient {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cloud sessions
|
||||
*
|
||||
* Fetch cloud CLI sessions from Kilo API
|
||||
*/
|
||||
public cloudSessions<ThrowOnError extends boolean = false>(
|
||||
parameters?: {
|
||||
directory?: string
|
||||
workspace?: string
|
||||
cursor?: string
|
||||
limit?: number
|
||||
gitUrl?: string
|
||||
},
|
||||
options?: Options<never, ThrowOnError>,
|
||||
) {
|
||||
const params = buildClientParams(
|
||||
[parameters],
|
||||
[
|
||||
{
|
||||
args: [
|
||||
{ in: "query", key: "directory" },
|
||||
{ in: "query", key: "workspace" },
|
||||
{ in: "query", key: "cursor" },
|
||||
{ in: "query", key: "limit" },
|
||||
{ in: "query", key: "gitUrl" },
|
||||
],
|
||||
},
|
||||
],
|
||||
)
|
||||
return (options?.client ?? this.client).get<KiloCloudSessionsResponses, KiloCloudSessionsErrors, ThrowOnError>({
|
||||
url: "/kilo/cloud-sessions",
|
||||
...options,
|
||||
...params,
|
||||
})
|
||||
}
|
||||
|
||||
private _organization?: Organization
|
||||
get organization(): Organization {
|
||||
return (this._organization ??= new Organization({ client: this.client }))
|
||||
@@ -5097,6 +5221,11 @@ export class Kilo extends HeyApiClient {
|
||||
get claw(): Claw {
|
||||
return (this._claw ??= new Claw({ client: this.client }))
|
||||
}
|
||||
|
||||
private _cloud?: Cloud
|
||||
get cloud(): Cloud {
|
||||
return (this._cloud ??= new Cloud({ client: this.client }))
|
||||
}
|
||||
}
|
||||
|
||||
export class Heap extends HeyApiClient {
|
||||
|
||||
@@ -1856,8 +1856,8 @@ export type EffectHttpApiErrorUnauthorized = {
|
||||
_tag: "Unauthorized"
|
||||
}
|
||||
|
||||
export type EffectHttpApiErrorInternalServerError = {
|
||||
_tag: "InternalServerError"
|
||||
export type EffectHttpApiErrorServiceUnavailable = {
|
||||
_tag: "ServiceUnavailable"
|
||||
}
|
||||
|
||||
export type KilocodeSessionImportResult = {
|
||||
@@ -7252,9 +7252,9 @@ export type KiloClawStatusData = {
|
||||
|
||||
export type KiloClawStatusErrors = {
|
||||
/**
|
||||
* InternalServerError
|
||||
* ServiceUnavailable
|
||||
*/
|
||||
500: EffectHttpApiErrorInternalServerError
|
||||
503: EffectHttpApiErrorServiceUnavailable
|
||||
}
|
||||
|
||||
export type KiloClawStatusError = KiloClawStatusErrors[keyof KiloClawStatusErrors]
|
||||
@@ -7315,6 +7315,143 @@ export type KiloClawChatCredentialsResponses = {
|
||||
|
||||
export type KiloClawChatCredentialsResponse = KiloClawChatCredentialsResponses[keyof KiloClawChatCredentialsResponses]
|
||||
|
||||
export type KiloCloudSessionsData = {
|
||||
body?: never
|
||||
path?: never
|
||||
query?: {
|
||||
directory?: string
|
||||
workspace?: string
|
||||
cursor?: string
|
||||
limit?: number
|
||||
gitUrl?: string
|
||||
}
|
||||
url: "/kilo/cloud-sessions"
|
||||
}
|
||||
|
||||
export type KiloCloudSessionsErrors = {
|
||||
/**
|
||||
* Bad request
|
||||
*/
|
||||
400: BadRequestError
|
||||
}
|
||||
|
||||
export type KiloCloudSessionsError = KiloCloudSessionsErrors[keyof KiloCloudSessionsErrors]
|
||||
|
||||
export type KiloCloudSessionsResponses = {
|
||||
/**
|
||||
* Cloud sessions list
|
||||
*/
|
||||
200: {
|
||||
cliSessions: Array<{
|
||||
session_id: string
|
||||
title: string
|
||||
created_at: string
|
||||
updated_at: string
|
||||
version: number
|
||||
}>
|
||||
nextCursor: string
|
||||
}
|
||||
}
|
||||
|
||||
export type KiloCloudSessionsResponse = KiloCloudSessionsResponses[keyof KiloCloudSessionsResponses]
|
||||
|
||||
export type KiloCloudSessionGetData = {
|
||||
body?: never
|
||||
path: {
|
||||
id: string
|
||||
}
|
||||
query?: {
|
||||
directory?: string
|
||||
workspace?: string
|
||||
}
|
||||
url: "/kilo/cloud/session/{id}"
|
||||
}
|
||||
|
||||
export type KiloCloudSessionGetErrors = {
|
||||
/**
|
||||
* Not found
|
||||
*/
|
||||
404: NotFoundError
|
||||
}
|
||||
|
||||
export type KiloCloudSessionGetError = KiloCloudSessionGetErrors[keyof KiloCloudSessionGetErrors]
|
||||
|
||||
export type KiloCloudSessionGetResponses = {
|
||||
/**
|
||||
* Cloud session data
|
||||
*/
|
||||
200: {
|
||||
info: {
|
||||
id: string
|
||||
title: string
|
||||
time: {
|
||||
created: number
|
||||
updated: number
|
||||
}
|
||||
}
|
||||
messages: Array<{
|
||||
info: {
|
||||
id: string
|
||||
sessionID: string
|
||||
role: "user" | "assistant"
|
||||
time: {
|
||||
created: number
|
||||
completed?: number
|
||||
}
|
||||
}
|
||||
parts: Array<{
|
||||
id: string
|
||||
sessionID: string
|
||||
messageID: string
|
||||
type: string
|
||||
}>
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
export type KiloCloudSessionGetResponse = KiloCloudSessionGetResponses[keyof KiloCloudSessionGetResponses]
|
||||
|
||||
export type KiloCloudSessionImportData = {
|
||||
body?: {
|
||||
sessionId: string
|
||||
}
|
||||
path?: never
|
||||
query?: {
|
||||
directory?: string
|
||||
workspace?: string
|
||||
}
|
||||
url: "/kilo/cloud/session/import"
|
||||
}
|
||||
|
||||
export type KiloCloudSessionImportErrors = {
|
||||
/**
|
||||
* Bad request
|
||||
*/
|
||||
400: BadRequestError
|
||||
/**
|
||||
* Not found
|
||||
*/
|
||||
404: NotFoundError
|
||||
}
|
||||
|
||||
export type KiloCloudSessionImportError = KiloCloudSessionImportErrors[keyof KiloCloudSessionImportErrors]
|
||||
|
||||
export type KiloCloudSessionImportResponses = {
|
||||
/**
|
||||
* Imported session info
|
||||
*/
|
||||
200: {
|
||||
id: string
|
||||
title: string
|
||||
time: {
|
||||
created: number
|
||||
updated: number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export type KiloCloudSessionImportResponse = KiloCloudSessionImportResponses[keyof KiloCloudSessionImportResponses]
|
||||
|
||||
export type KilocodeHeapSnapshotData = {
|
||||
body?: never
|
||||
path?: never
|
||||
|
||||
+375
-5
@@ -9222,12 +9222,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "InternalServerError",
|
||||
"503": {
|
||||
"description": "ServiceUnavailable",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/effect_HttpApiError_InternalServerError"
|
||||
"$ref": "#/components/schemas/effect_HttpApiError_ServiceUnavailable"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9303,6 +9303,376 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/kilo/cloud-sessions": {
|
||||
"get": {
|
||||
"tags": ["kilo"],
|
||||
"operationId": "kilo.cloudSessions",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "directory",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "workspace",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "cursor",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": false
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "number"
|
||||
},
|
||||
"required": false
|
||||
},
|
||||
{
|
||||
"name": "gitUrl",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": false
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Cloud sessions list",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cliSessions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"session_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"required": ["session_id", "title", "created_at", "updated_at", "version"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"nextCursor": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["cliSessions", "nextCursor"],
|
||||
"additionalProperties": false,
|
||||
"description": "Cloud sessions list"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad request",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/BadRequestError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Fetch cloud CLI sessions from Kilo API",
|
||||
"summary": "Get cloud sessions",
|
||||
"x-codeSamples": [
|
||||
{
|
||||
"lang": "js",
|
||||
"source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.kilo.cloudSessions({\n ...\n})"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/kilo/cloud/session/{id}": {
|
||||
"get": {
|
||||
"tags": ["kilo"],
|
||||
"operationId": "kilo.cloud.session.get",
|
||||
"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": "Cloud session data",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"time": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"created": {
|
||||
"type": "number"
|
||||
},
|
||||
"updated": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"required": ["created", "updated"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": ["id", "title", "time"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"messages": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"sessionID": {
|
||||
"type": "string"
|
||||
},
|
||||
"role": {
|
||||
"type": "string",
|
||||
"enum": ["user", "assistant"]
|
||||
},
|
||||
"time": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"created": {
|
||||
"type": "number"
|
||||
},
|
||||
"completed": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"required": ["created"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": ["id", "sessionID", "role", "time"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"parts": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"sessionID": {
|
||||
"type": "string"
|
||||
},
|
||||
"messageID": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["id", "sessionID", "messageID", "type"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["info", "parts"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["info", "messages"],
|
||||
"additionalProperties": false,
|
||||
"description": "Cloud session data"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/NotFoundError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Fetch full session data from the Kilo cloud for preview",
|
||||
"summary": "Get cloud session",
|
||||
"x-codeSamples": [
|
||||
{
|
||||
"lang": "js",
|
||||
"source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.kilo.cloud.session.get({\n ...\n})"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/kilo/cloud/session/import": {
|
||||
"post": {
|
||||
"tags": ["kilo"],
|
||||
"operationId": "kilo.cloud.session.import",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "directory",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "workspace",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Imported session info",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"time": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"created": {
|
||||
"type": "number"
|
||||
},
|
||||
"updated": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"required": ["created", "updated"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": ["id", "title", "time"],
|
||||
"additionalProperties": false,
|
||||
"description": "Imported session info"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad request",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/BadRequestError"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not found",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/NotFoundError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Download a cloud-synced session and write it to local storage with fresh IDs.",
|
||||
"summary": "Import session from cloud",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"sessionId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["sessionId"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-codeSamples": [
|
||||
{
|
||||
"lang": "js",
|
||||
"source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.kilo.cloud.session.import({\n ...\n})"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/kilocode/heap/snapshot": {
|
||||
"post": {
|
||||
"tags": ["kilocode"],
|
||||
@@ -16391,12 +16761,12 @@
|
||||
"required": ["_tag"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"effect_HttpApiError_InternalServerError": {
|
||||
"effect_HttpApiError_ServiceUnavailable": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"_tag": {
|
||||
"type": "string",
|
||||
"enum": ["InternalServerError"]
|
||||
"enum": ["ServiceUnavailable"]
|
||||
}
|
||||
},
|
||||
"required": ["_tag"],
|
||||
|
||||
Reference in New Issue
Block a user