fix: vscode kiloclaw error handler

This commit is contained in:
Catriel Müller
2026-04-28 15:42:59 -03:00
parent f4a3863357
commit e64fe55788
5 changed files with 52 additions and 61 deletions
+2 -1
View File
@@ -2,6 +2,7 @@
"recommendations": [
"dbaeumer.vscode-eslint",
"connor4312.esbuild-problem-matchers",
"ms-vscode.extension-test-runner"
"ms-vscode.extension-test-runner",
"mkhl.direnv"
]
}
@@ -217,28 +217,21 @@ export class KiloClawProvider implements vscode.Disposable {
/**
* Fetch and validate instance status + chat credentials.
* Returns credentials on success, null when stale or after posting an error/state.
* Returns credentials on success, null when stale or after posting a state.
*
* Matches the TUI flow in packages/opencode/src/kilocode/kilo-commands.tsx:67,75 —
* any failure of status() (SDK error, non-2xx from the gateway, missing data, or
* missing userId) funnels to noInstance (SetupView). Any failure of
* chatCredentials() funnels to needsUpgrade (UpgradeView). The upstream Kilo API
* returns a non-2xx when no instance is provisioned, which the gateway mirrors
* and the SDK surfaces as res.error — not a thrown exception.
*/
private async fetchCreds(client: KiloClient, gen: number): Promise<ChatCredentials | null> {
const res = await client.kilo.claw.status().catch(() => null)
if (this.stale(gen)) return null
// Distinguish SDK/network errors from business states
if (!res || (res as Record<string, unknown>).error) {
this.post({
type: "kiloclaw.state",
state: { phase: "error", locale: this.locale, error: "Failed to connect to Kilo service" },
})
return null
}
if (!res.data || (res.data as Record<string, unknown>).error) {
this.post({ type: "kiloclaw.state", state: { phase: "noInstance", locale: this.locale } })
return null
}
const data = res.data as ClawStatus & { userId?: string }
if (!data.userId) {
const data = res?.data as (ClawStatus & { userId?: string }) | undefined
if (!res || (res as Record<string, unknown>).error || !data || !data.userId) {
this.post({ type: "kiloclaw.state", state: { phase: "noInstance", locale: this.locale } })
return null
}
@@ -248,16 +241,7 @@ export class KiloClawProvider implements vscode.Disposable {
const creds = await client.kilo.claw.chatCredentials().catch(() => null)
if (this.stale(gen)) return null
// Distinguish SDK/network errors from business states
if (!creds || (creds as Record<string, unknown>).error) {
this.post({
type: "kiloclaw.state",
state: { phase: "error", locale: this.locale, error: "Failed to fetch chat credentials" },
})
return null
}
if (!creds.data) {
if (!creds || (creds as Record<string, unknown>).error || !creds.data) {
this.post({ type: "kiloclaw.state", state: { phase: "needsUpgrade", locale: this.locale } })
return null
}
@@ -39,6 +39,12 @@
.kiloclaw-card {
max-width: 480px;
width: 100%;
padding: 12px;
}
.kiloclaw-card div[data-slot="card-actions"] {
display: flex;
justify-content: space-between;
}
.kiloclaw-card-subtitle {
+14 -14
View File
@@ -103,22 +103,26 @@
"@clack/prompts": "1.0.0-alpha.1",
"@effect/opentelemetry": "catalog:",
"@effect/platform-node": "catalog:",
"@gitlab/gitlab-ai-provider": "3.6.0",
"@gitlab/opencode-gitlab-auth": "1.3.3",
"@hono/node-server": "1.19.13",
"@hono/node-ws": "1.3.0",
"@hono/standard-validator": "0.1.5",
"@hono/zod-validator": "catalog:",
"@kilocode/kilo-gateway": "workspace:*",
"@kilocode/kilo-indexing": "workspace:*",
"@kilocode/kilo-telemetry": "workspace:*",
"@kilocode/plugin": "workspace:*",
"@kilocode/sdk": "workspace:*",
"@lydell/node-pty": "catalog:",
"@modelcontextprotocol/sdk": "1.29.0",
"@morphllm/morphsdk": "0.2.166",
"@npmcli/arborist": "9.4.0",
"@npmcli/config": "10.8.1",
"@octokit/graphql": "9.0.2",
"@octokit/rest": "catalog:",
"@openauthjs/openauth": "catalog:",
"@kilocode/plugin": "workspace:*",
"@kilocode/kilo-indexing": "workspace:*",
"@opencode-ai/script": "workspace:*",
"@kilocode/sdk": "workspace:*",
"@openrouter/ai-sdk-provider": "2.8.1",
"@opentelemetry/api": "1.9.0",
"@opentelemetry/context-async-hooks": "2.6.1",
@@ -152,8 +156,10 @@
"gray-matter": "4.0.3",
"hono": "catalog:",
"hono-openapi": "catalog:",
"iconv-lite": "0.7.2",
"ignore": "7.0.5",
"immer": "11.1.4",
"jschardet": "3.1.4",
"jsonc-parser": "3.3.1",
"mime-types": "3.0.2",
"minimatch": "10.2.5",
@@ -164,8 +170,12 @@
"opentui-spinner": "0.0.6",
"partial-json": "0.1.7",
"remeda": "catalog:",
"ripgrep": "0.3.1",
"rotating-file-stream": "3.2.9",
"semver": "^7.6.3",
"simple-git": "3.35.2",
"solid-js": "catalog:",
"stream-chat": "9.38.0",
"strip-ansi": "7.1.2",
"tree-sitter-bash": "0.25.0",
"tree-sitter-powershell": "0.25.10",
@@ -179,17 +189,7 @@
"xdg-basedir": "5.1.0",
"yargs": "18.0.0",
"zod": "catalog:",
"zod-to-json-schema": "3.24.5",
"@gitlab/gitlab-ai-provider": "3.6.0",
"@kilocode/kilo-gateway": "workspace:*",
"@kilocode/kilo-telemetry": "workspace:*",
"@morphllm/morphsdk": "0.2.166",
"iconv-lite": "0.7.2",
"jschardet": "3.1.4",
"ripgrep": "0.3.1",
"rotating-file-stream": "3.2.9",
"simple-git": "3.35.2",
"stream-chat": "9.38.0"
"zod-to-json-schema": "3.24.5"
},
"overrides": {
"drizzle-orm": "catalog:"
+19 -19
View File
@@ -590,23 +590,6 @@ export type EventVcsBranchUpdated = {
}
}
export type IndexingStatusState = "Disabled" | "In Progress" | "Complete" | "Error" | "Standby"
export type IndexingStatus = {
state: IndexingStatusState
message: string
processedFiles: number
totalFiles: number
percent: number
}
export type EventIndexingStatus = {
type: "indexing.status"
properties: {
status: IndexingStatus
}
}
export type EventSessionCompacted = {
type: "session.compacted"
properties: {
@@ -1170,6 +1153,23 @@ export type EventSessionDeleted = {
}
}
export type IndexingStatusState = "Disabled" | "In Progress" | "Complete" | "Error" | "Standby"
export type IndexingStatus = {
state: IndexingStatusState
message: string
processedFiles: number
totalFiles: number
percent: number
}
export type EventIndexingStatus = {
type: "indexing.status"
properties: {
status: IndexingStatus
}
}
export type SyncEventMessageUpdated = {
type: "sync"
name: "message.updated.1"
@@ -1331,7 +1331,6 @@ export type GlobalEvent = {
| EventSessionIdle
| EventTodoUpdated
| EventVcsBranchUpdated
| EventIndexingStatus
| EventSessionCompacted
| EventKiloSessionsRemoteStatusChanged
| EventWorktreeReady
@@ -1351,6 +1350,7 @@ export type GlobalEvent = {
| EventSessionCreated
| EventSessionUpdated
| EventSessionDeleted
| EventIndexingStatus
| SyncEventMessageUpdated
| SyncEventMessageRemoved
| SyncEventMessagePartUpdated
@@ -2449,7 +2449,6 @@ export type Event =
| EventSessionIdle
| EventTodoUpdated
| EventVcsBranchUpdated
| EventIndexingStatus
| EventSessionCompacted
| EventKiloSessionsRemoteStatusChanged
| EventWorktreeReady
@@ -2469,6 +2468,7 @@ export type Event =
| EventSessionCreated
| EventSessionUpdated
| EventSessionDeleted
| EventIndexingStatus
export type McpStatusConnected = {
status: "connected"