From e64fe5578893e4a990d0fe113523fd09f48d1514 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Catriel=20M=C3=BCller?= Date: Tue, 28 Apr 2026 15:42:59 -0300 Subject: [PATCH] fix: vscode kiloclaw error handler --- .vscode/extensions.json | 3 +- .../src/kiloclaw/KiloClawProvider.ts | 38 ++++++------------- .../webview-ui/kiloclaw/kiloclaw.css | 6 +++ packages/opencode/package.json | 28 +++++++------- packages/sdk/js/src/v2/gen/types.gen.ts | 38 +++++++++---------- 5 files changed, 52 insertions(+), 61 deletions(-) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 1895004b52..4e46621d9c 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -2,6 +2,7 @@ "recommendations": [ "dbaeumer.vscode-eslint", "connor4312.esbuild-problem-matchers", - "ms-vscode.extension-test-runner" + "ms-vscode.extension-test-runner", + "mkhl.direnv" ] } diff --git a/packages/kilo-vscode/src/kiloclaw/KiloClawProvider.ts b/packages/kilo-vscode/src/kiloclaw/KiloClawProvider.ts index 521f3dbaf1..aa5868bea7 100644 --- a/packages/kilo-vscode/src/kiloclaw/KiloClawProvider.ts +++ b/packages/kilo-vscode/src/kiloclaw/KiloClawProvider.ts @@ -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 { 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).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).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).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).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).error || !creds.data) { this.post({ type: "kiloclaw.state", state: { phase: "needsUpgrade", locale: this.locale } }) return null } diff --git a/packages/kilo-vscode/webview-ui/kiloclaw/kiloclaw.css b/packages/kilo-vscode/webview-ui/kiloclaw/kiloclaw.css index 94d6f25249..92867cbda2 100644 --- a/packages/kilo-vscode/webview-ui/kiloclaw/kiloclaw.css +++ b/packages/kilo-vscode/webview-ui/kiloclaw/kiloclaw.css @@ -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 { diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 3ba0d48f77..f1dc1ab1aa 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -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:" diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index 6a6cf68daa..b9d9265938 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -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"