From e22afa6981e6ea01fa2ef36088e3e4a6b72f2f0c Mon Sep 17 00:00:00 2001 From: Robby Date: Sat, 6 Jun 2026 19:07:05 +0200 Subject: [PATCH] feat: add debug logging to surface silent failures #6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - logDebugEvent on init with hasApiKey flag - logDebugEvent on each fetch: ok (currency/total/ms) or error (status/reason) - No API key → sidebar warning + debug log - HTTP error → sidebar shows status code + debug log - Enable: DEEPSEEK_DEBUG=true opencode --- src/tui.tsx | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/tui.tsx b/src/tui.tsx index 83fea4d..65c2ef7 100644 --- a/src/tui.tsx +++ b/src/tui.tsx @@ -1,6 +1,7 @@ /** @jsxImportSource @opentui/solid */ import { createSignal, createMemo, onCleanup, onMount, Show } from "solid-js"; import type { TuiPlugin } from "@opencode-ai/plugin/tui"; +import { logDebugEvent } from "./debug-logger.js"; const BALANCE_URL = "https://api.deepseek.com/user/balance"; const REFRESH_INTERVAL_MS = 30_000; @@ -67,29 +68,49 @@ const DeepseekBalance = (props: { palette: Palette }) => { const fetchBalance = async () => { const apiKey = process.env.DEEPSEEK_API_KEY; if (!apiKey) { + logDebugEvent("fetch.error", { reason: "no_api_key" }); setErrorMsg("DEEPSEEK_API_KEY not set"); setLoading(false); return; } try { + const started = Date.now(); const res = await fetch(BALANCE_URL, { headers: { Authorization: `Bearer ${apiKey}`, Accept: "application/json", }, }); - if (!res.ok) throw new Error(`HTTP ${res.status}`); + + if (!res.ok) { + const status = res.status; + logDebugEvent("fetch.error", { status, ms: Date.now() - started }); + setErrorMsg(`DeepSeek API ${status}`); + setLoading(false); + return; + } + const data = (await res.json()) as BalanceResponse; const info = data.balance_infos?.[0]; if (info) { + logDebugEvent("fetch.ok", { + currency: info.currency, + total: info.total_balance, + ms: Date.now() - started, + }); setBalance(info); setIsAvailable(data.is_available); setErrorMsg(""); } else { + logDebugEvent("fetch.error", { reason: "empty_balance_infos" }); setErrorMsg("No balance data"); } - } catch { + } catch (err) { + logDebugEvent("fetch.error", { + reason: "network", + message: err instanceof Error ? err.message : String(err), + }); if (!balance()) { setErrorMsg("DeepSeek API unreachable"); } @@ -132,6 +153,7 @@ const DeepseekBalance = (props: { palette: Palette }) => { }); onMount(() => { + logDebugEvent("lifecycle", { event: "mount" }); void fetchBalance(); const timer = setInterval(() => void fetchBalance(), REFRESH_INTERVAL_MS); onCleanup(() => clearInterval(timer)); @@ -171,6 +193,8 @@ const SidebarBalance = (props: { theme: Record }) => { }; const tui: TuiPlugin = (api) => { + logDebugEvent("lifecycle", { event: "init", hasApiKey: !!process.env.DEEPSEEK_API_KEY }); + api.slots.register({ order: SIDEBAR_ORDER, slots: {