Merge pull request #11798 from Kilo-Org/funny-tarp

fix(kiloclaw): restore slash command access
This commit is contained in:
Catriel Müller
2026-06-29 09:54:01 -03:00
committed by GitHub
8 changed files with 69 additions and 2 deletions
+7
View File
@@ -0,0 +1,7 @@
---
"@kilocode/cli": patch
"@kilocode/kilo-gateway": patch
"kilo-code": patch
---
Fix opening KiloClaw from the CLI and VS Code slash commands.
+1
View File
@@ -76,6 +76,7 @@ export {
getNotifications,
getProfile,
getToken,
normalizeClawStatus,
setOrganization,
} from "./server/handlers.js"
+17 -1
View File
@@ -120,7 +120,23 @@ export async function getClawStatus(auth: AuthStore) {
const response = await fetch(`${KILO_API_BASE}/api/kiloclaw/status`, { headers })
if (!response.ok) throw new GatewayError(await response.text(), response.status)
return response.json()
return normalizeClawStatus(await response.json())
}
function normalizeTime(value: unknown) {
if (typeof value === "number" && Number.isFinite(value)) return new Date(value).toISOString()
return value
}
export function normalizeClawStatus(input: unknown) {
if (!input || typeof input !== "object" || Array.isArray(input)) return input
const data = input as Record<string, unknown>
return {
...data,
...("lastStartedAt" in data ? { lastStartedAt: normalizeTime(data.lastStartedAt) } : {}),
...("lastStoppedAt" in data ? { lastStoppedAt: normalizeTime(data.lastStoppedAt) } : {}),
}
}
export async function getClawChatCredentials(auth: AuthStore): Promise<ClawChatCredentials> {
+3
View File
@@ -1037,6 +1037,9 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
case "openSettingsPanel":
vscode.commands.executeCommand("kilo-code.new.settingsButtonClicked", message.tab)
break
case "openKiloClaw":
vscode.commands.executeCommand("kilo-code.new.kiloClawOpen")
break
case "openVSCodeSettings":
vscode.commands.executeCommand("workbench.action.openSettings", message.query)
break
@@ -143,6 +143,14 @@ export function useSlashCommand(
vscode.postMessage({ type: "toggleRemote" })
},
},
{
name: "kiloclaw",
description: "Open KiloClaw chat",
hints: ["claw"],
action: () => {
vscode.postMessage({ type: "openKiloClaw" })
},
},
{
name: "sandbox",
description: "Toggle sandbox",
@@ -228,6 +228,10 @@ export interface OpenAdvancedWorktreeRequest {
type: "openAdvancedWorktree"
}
export interface OpenKiloClawRequest {
type: "openKiloClaw"
}
export interface RequestAgentsMessage {
type: "requestAgents"
}
@@ -1173,6 +1177,7 @@ export type WebviewMessage =
| OpenMarketplacePanelRequest
| OpenAgentManagerRequest
| OpenAdvancedWorktreeRequest
| OpenKiloClawRequest
| OpenFileRequest
| ValidateFilesRequest
| CancelLoginRequest
@@ -6,6 +6,7 @@ import {
getOrganizationId,
getToken,
importSessionToDb,
normalizeClawStatus,
} from "@kilocode/kilo-gateway"
import {
HEADER_FEATURE,
@@ -360,7 +361,7 @@ export const kiloGatewayHandlers = HttpApiBuilder.group(InstanceHttpApi, "kilo",
try: async () => {
const response = await fetch(`${KILO_API_BASE}/api/kiloclaw/status`, { headers })
if (!response.ok) throw new GatewayError(await response.text(), response.status)
return Schema.decodeUnknownPromise(ClawStatus)(await response.json())
return Schema.decodeUnknownPromise(ClawStatus)(normalizeClawStatus(await response.json()))
},
catch: (err) => err,
}).pipe(
@@ -183,6 +183,32 @@ describe("Kilo gateway HttpApi statuses", () => {
}),
)
it.live("normalizes numeric KiloClaw timestamps", () =>
Effect.gen(function* () {
const started = 1_700_000_000_000
yield* stub(() =>
Response.json({
status: "running",
sandboxId: "sandbox",
userId: "user",
lastStartedAt: started,
lastStoppedAt: null,
}),
)
const response = yield* HttpClient.get(KiloGatewayPaths.clawStatus)
expect(response.status).toBe(200)
expect(yield* response.json).toEqual({
status: "running",
sandboxId: "sandbox",
userId: "user",
lastStartedAt: new Date(started).toISOString(),
lastStoppedAt: null,
})
}),
)
it.live("maps KiloClaw transport failures to bad gateway", () =>
Effect.gen(function* () {
yield* stub(() => Promise.reject(new TypeError("network error")))