From 729c8785bafb89ec7edef3b6a56c373843423949 Mon Sep 17 00:00:00 2001 From: davidmonterocrespo24 Date: Thu, 14 May 2026 16:44:05 +0200 Subject: [PATCH] feat(compile): expose compile logs via Zustand store + UI slot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two minimal hooks so the velxio-pro agent overlay can offer a 'Diagnose this compile failure with AI' affordance without touching upstream component internals: - New store/useCompileLogsStore: holds the editor's compile output as Zustand state instead of local React useState in EditorPage. The setter accepts both a value and an updater fn so the EditorToolbar callers that used setCompileLogs(prev => [...prev, log]) keep working without changes. - CompilationConsole header now renders a
when errorCount > 0. The pro overlay mounts a 'Diagnose with AI' button into this slot via slotMounter. Empty in the OSS image — no behaviour change. EditorPage replaces its local useState with the store selector. The downstream prop-drilled setCompileLogs callers (toolbar, sub-toolbars) keep their signature. Companion commit lands the button + diagnostic prompt builder in the velxio-prod overlay. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../components/editor/CompilationConsole.tsx | 6 +++ frontend/src/pages/EditorPage.tsx | 7 +++- frontend/src/store/useCompileLogsStore.ts | 42 +++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 frontend/src/store/useCompileLogsStore.ts diff --git a/frontend/src/components/editor/CompilationConsole.tsx b/frontend/src/components/editor/CompilationConsole.tsx index 2c1bc666..18a2f14f 100644 --- a/frontend/src/components/editor/CompilationConsole.tsx +++ b/frontend/src/components/editor/CompilationConsole.tsx @@ -75,6 +75,12 @@ export const CompilationConsole: React.FC = ({ ⚠ {warningCount} )} + {/* Pro overlay mounts a "Diagnose with AI" button here when + errorCount > 0. Empty in the OSS image — slotMounter + only fires when the pro tree is present. */} + {errorCount > 0 && ( +
+ )}
diff --git a/frontend/src/pages/EditorPage.tsx b/frontend/src/pages/EditorPage.tsx index 4e335f2c..474acd36 100644 --- a/frontend/src/pages/EditorPage.tsx +++ b/frontend/src/pages/EditorPage.tsx @@ -27,6 +27,7 @@ import { LoginPromptModal } from '../components/layout/LoginPromptModal'; import { GitHubStarBanner } from '../components/layout/GitHubStarBanner'; import { useSimulatorStore, DEFAULT_BOARD_POSITION } from '../store/useSimulatorStore'; import { useEditorStore } from '../store/useEditorStore'; +import { useCompileLogsStore } from '../store/useCompileLogsStore'; import { useOscilloscopeStore } from '../store/useOscilloscopeStore'; import { useAuthStore } from '../store/useAuthStore'; import { useProjectStore } from '../store/useProjectStore'; @@ -81,7 +82,11 @@ export const EditorPage: React.FC = () => { const isRaspberryPi3 = activeBoardKind === 'raspberry-pi-3'; const oscilloscopeOpen = useOscilloscopeStore((s) => s.open); const [consoleOpen, setConsoleOpen] = useState(false); - const [compileLogs, setCompileLogs] = useState([]); + // compileLogs live in a Zustand store so the velxio-pro agent overlay + // (mounted in a separate React tree via slotMounter) can subscribe and + // build a "diagnose this failure" prompt without prop-drilling. + const compileLogs = useCompileLogsStore((s) => s.logs); + const setCompileLogs = useCompileLogsStore((s) => s.setLogs); const [bottomPanelHeight, setBottomPanelHeight] = useState(BOTTOM_PANEL_DEFAULT); const [saveModalOpen, setSaveModalOpen] = useState(false); const [loginPromptOpen, setLoginPromptOpen] = useState(false); diff --git a/frontend/src/store/useCompileLogsStore.ts b/frontend/src/store/useCompileLogsStore.ts new file mode 100644 index 00000000..b7a0925e --- /dev/null +++ b/frontend/src/store/useCompileLogsStore.ts @@ -0,0 +1,42 @@ +/** + * Zustand store for the editor's compile output. + * + * Lives outside so other components (notably the velxio-pro + * agent overlay, mounted into a different React tree via slotMounter) can + * subscribe without prop-drilling. The overlay reads `logs` to build a + * "diagnose this compile failure with AI" prompt; without the store it + * would have no way to reach the upstream component state. Board target + * is read from `useEditorStore` by the overlay independently. + */ + +import { create } from 'zustand'; + +import type { CompilationLog } from '../utils/compilationLogger'; + +/** React-style setter — accepts either a new value OR an updater fn so + * callers that used `useState`'s `setX(prev => ...)` form can be + * swapped in without rewriting the call sites. */ +type LogsSetter = ( + next: CompilationLog[] | ((prev: CompilationLog[]) => CompilationLog[]), +) => void; + +interface CompileLogsState { + logs: CompilationLog[]; + setLogs: LogsSetter; + appendLogs: (logs: CompilationLog[]) => void; + clear: () => void; +} + +export const useCompileLogsStore = create((set, get) => ({ + logs: [], + setLogs: (next) => { + if (typeof next === 'function') { + set({ logs: (next as (prev: CompilationLog[]) => CompilationLog[])(get().logs) }); + } else { + set({ logs: next }); + } + }, + appendLogs: (entries) => + set((s) => ({ logs: [...s.logs, ...entries] })), + clear: () => set({ logs: [] }), +}));