From 1453a8fa95af2587a2838d7219f380d65b97fd99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Wed, 22 Apr 2026 15:00:35 -0400 Subject: [PATCH] fix(renderer): preserve desktop error codes --- src/renderer/App.tsx | 15 +- src/renderer/components/Toast.tsx | 27 ++- .../components/skills/SkillAgentToggles.tsx | 3 +- .../components/skills/SkillDetail.tsx | 7 +- .../components/skills/SkillImportModal.tsx | 5 +- .../components/skills/SkillsSection.tsx | 5 +- src/renderer/hooks/useAppActions.ts | 3 +- src/renderer/hooks/useCompanyController.ts | 10 +- src/renderer/hooks/useDataLoader.ts | 4 +- src/renderer/lib/desktop.ts | 155 ++++++++++++++++++ src/renderer/state/slices/company.ts | 17 +- src/renderer/state/slices/ui.ts | 5 +- src/renderer/views/SectionContentView.tsx | 20 ++- .../views/sections/OperationsSections.tsx | 12 +- tests/unit/desktop-error-notice.test.ts | 78 +++++++++ 15 files changed, 326 insertions(+), 40 deletions(-) create mode 100644 tests/unit/desktop-error-notice.test.ts diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index c64efd30..b44461ad 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -15,7 +15,7 @@ import { useCompanyController } from "./hooks/useCompanyController"; import { useCommandPaletteHotkeys } from "./hooks/useCommandPaletteHotkeys"; import { AppActionsContext, type AppActions } from "./hooks/useAppActions"; import { SectionContext } from "./hooks/useSectionContext"; -import { unwrap } from "./lib/desktop"; +import { createAppErrorNotice, describeDesktopError, formatDesktopResultError, unwrap } from "./lib/desktop"; function Shell({ locale, @@ -55,9 +55,16 @@ export function App() { const isMac = !showCustomTitleBar; const startRun = useCallback(async (taskId: string) => { - if (!company.currentCompany) { setError("Select a company before starting a run."); return; } + if (!company.currentCompany) { + setError(createAppErrorNotice( + "Select a company before starting a run.", + "COMPANY_REQUIRED", + "Select a company in the sidebar, then start the run.", + )); + return; + } const result = await window.agentCompany.startTaskRun({ companyId: company.currentCompany.id, taskId }); - if (!result.ok) { setError(result.error.message); return; } + if (!result.ok) { setError(formatDesktopResultError(result.error)); return; } setSelectedRunId(result.data); await company.refresh(); // eslint-disable-next-line react-hooks/exhaustive-deps -- Zustand setters and company.refresh are stable @@ -70,7 +77,7 @@ export function App() { unwrap(await window.agentCompany.cancelRun({ companyId: run.companyId, runId })); await company.refresh(); setError(null); - } catch (err) { setError(err instanceof Error ? err.message : String(err)); } + } catch (err) { setError(describeDesktopError(err)); } // eslint-disable-next-line react-hooks/exhaustive-deps -- setError is a stable Zustand setter }, [company.refresh, company.runs]); diff --git a/src/renderer/components/Toast.tsx b/src/renderer/components/Toast.tsx index 98685fa3..f891061a 100644 --- a/src/renderer/components/Toast.tsx +++ b/src/renderer/components/Toast.tsx @@ -2,6 +2,7 @@ import { AnimatePresence, motion } from "framer-motion" import { CheckCircle, Warning, X, XCircle } from "./ui/icons" import { useAppStore } from "../state/store" import { useReducedMotion } from "./ui" +import type { Toast } from "../state/slices/ui" const TONE_CONFIG = { success: { icon: CheckCircle, className: "bg-success-muted border-success text-success" }, @@ -34,9 +35,7 @@ export default function ToastContainer() { className={`flex w-[320px] items-start gap-2.5 rounded-lg border px-4 py-3 shadow-lg ${cfg.className}`} > - - {toast.message} - +