From bcc15a486e245c7bcc1d4179974c6b24b11480d3 Mon Sep 17 00:00:00 2001 From: Pedram Amini Date: Sun, 18 Jan 2026 13:05:30 -0600 Subject: [PATCH] MAESTRO: Phase 03 - Integrate props hooks into App.tsx - Import useMainPanelProps, useSessionListProps, useRightPanelProps hooks - Create memoized wizard handlers (handleWizardComplete, handleWizardLetsGo, handleToggleWizardShowThinking) - Integrate all three props hooks with comprehensive dependency objects - Update MainPanel, SessionList, and RightPanel JSX to use spread props pattern - Fix type mismatches: - BatchRunState null vs undefined - AITab type for activeTab - DocumentGenerationCallbacks function signature - mergeSourceName/mergeTargetName string | undefined - lastGraphFocusFilePath string | undefined This optimization prevents React from re-evaluating 50-100+ props on every state change in MaestroConsoleInner by memoizing props objects that only change when their dependencies change. --- src/renderer/App.tsx | 1042 +++++++++-------- src/renderer/hooks/props/useMainPanelProps.ts | 39 +- .../hooks/props/useRightPanelProps.ts | 6 +- 3 files changed, 582 insertions(+), 505 deletions(-) diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index c799bf2c..eb6d57fe 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -95,6 +95,11 @@ import { useAutoRunHandlers } from './hooks'; import type { TabCompletionSuggestion, TabCompletionFilter } from './hooks'; +import { + useMainPanelProps, + useSessionListProps, + useRightPanelProps +} from './hooks/props'; // Import contexts import { useLayerStack } from './contexts/LayerStackContext'; @@ -12504,6 +12509,547 @@ You are taking over this conversation. Based on the context above, provide a bri hasOpenModal ]); + // ============================================================================ + // MEMOIZED WIZARD HANDLERS FOR PROPS HOOKS + // ============================================================================ + + // Wizard complete handler - converts wizard tab to normal session with context + const handleWizardComplete = useCallback(() => { + if (!activeSession) return; + const activeTabLocal = getActiveTab(activeSession); + const wizardState = activeTabLocal?.wizardState; + if (!wizardState) return; + + // Convert wizard conversation history to log entries + const wizardLogEntries: LogEntry[] = + wizardState.conversationHistory.map(msg => ({ + id: `wizard-${msg.id}`, + timestamp: msg.timestamp, + source: msg.role === 'user' ? 'user' : 'ai', + text: msg.content, + delivered: true + })); + + // Create summary message with next steps + const generatedDocs = wizardState.generatedDocuments || []; + const totalTasks = generatedDocs.reduce( + (sum, doc) => sum + doc.taskCount, + 0 + ); + const docNames = generatedDocs.map(d => d.filename).join(', '); + + const summaryMessage: LogEntry = { + id: `wizard-summary-${Date.now()}`, + timestamp: Date.now(), + source: 'ai', + text: + `## Wizard Complete\n\n` + + `Created ${generatedDocs.length} document${ + generatedDocs.length !== 1 ? 's' : '' + } with ${totalTasks} task${totalTasks !== 1 ? 's' : ''}:\n` + + `${docNames}\n\n` + + `**Next steps:**\n` + + `1. Open the **Auto Run** tab in the right panel to view your playbook\n` + + `2. Review and edit tasks as needed\n` + + `3. Click **Run** to start executing tasks automatically\n\n` + + `You can continue chatting to iterate on your playbook - the AI has full context of what was created.`, + delivered: true + }; + + const subfolderName = wizardState.subfolderName || ''; + const tabName = subfolderName || 'Wizard'; + const wizardAgentSessionId = wizardState.agentSessionId; + const activeTabId = activeTabLocal.id; + + setSessions(prev => + prev.map(s => { + if (s.id !== activeSession.id) return s; + const updatedTabs = s.aiTabs.map(tab => { + if (tab.id !== activeTabId) return tab; + return { + ...tab, + logs: [...tab.logs, ...wizardLogEntries, summaryMessage], + agentSessionId: wizardAgentSessionId || tab.agentSessionId, + name: tabName, + wizardState: undefined + }; + }); + return { ...s, aiTabs: updatedTabs }; + }) + ); + + endInlineWizard(); + handleAutoRunRefresh(); + setInputValue(''); + }, [activeSession, getActiveTab, setSessions, endInlineWizard, handleAutoRunRefresh, setInputValue]); + + // Wizard lets go handler - generates documents for active tab + const handleWizardLetsGo = useCallback(() => { + const activeTabLocal = activeSession ? getActiveTab(activeSession) : null; + if (activeTabLocal) { + generateInlineWizardDocuments(undefined, activeTabLocal.id); + } + }, [activeSession, getActiveTab, generateInlineWizardDocuments]); + + // Wizard toggle thinking handler + const handleToggleWizardShowThinking = useCallback(() => { + if (!activeSession) return; + const activeTabLocal = getActiveTab(activeSession); + if (!activeTabLocal?.wizardState) return; + setSessions(prev => + prev.map(s => { + if (s.id !== activeSession.id) return s; + return { + ...s, + aiTabs: s.aiTabs.map(tab => { + if (tab.id !== activeTabLocal.id) return tab; + if (!tab.wizardState) return tab; + return { + ...tab, + wizardState: { + ...tab.wizardState, + showWizardThinking: !tab.wizardState.showWizardThinking, + thinkingContent: !tab.wizardState.showWizardThinking + ? '' + : tab.wizardState.thinkingContent + } + }; + }) + }; + }) + ); + }, [activeSession, getActiveTab, setSessions]); + + // ============================================================================ + // PROPS HOOKS FOR MAJOR COMPONENTS + // These hooks memoize the props objects for MainPanel, SessionList, and RightPanel + // to prevent re-evaluating 50-100+ props on every state change. + // ============================================================================ + + const mainPanelProps = useMainPanelProps({ + // Core state + logViewerOpen, + agentSessionsOpen, + activeAgentSessionId, + activeSession, + thinkingSessions, + theme, + fontFamily, + isMobileLandscape, + activeFocus, + outputSearchOpen, + outputSearchQuery, + inputValue, + enterToSendAI, + enterToSendTerminal, + stagedImages, + commandHistoryOpen, + commandHistoryFilter, + commandHistorySelectedIndex, + slashCommandOpen, + slashCommands: allSlashCommands, + selectedSlashCommandIndex, + previewFile, + filePreviewLoading, + markdownEditMode, + shortcuts, + rightPanelOpen, + maxOutputLines, + gitDiffPreview, + fileTreeFilterOpen, + logLevel, + logViewerSelectedLevels, + + // Tab completion state + tabCompletionOpen, + tabCompletionSuggestions, + selectedTabCompletionIndex, + tabCompletionFilter, + + // @ mention completion state + atMentionOpen, + atMentionFilter, + atMentionStartIndex, + atMentionSuggestions, + selectedAtMentionIndex, + + // Batch run state (convert null to undefined for component props) + activeBatchRunState: activeBatchRunState ?? undefined, + currentSessionBatchState: currentSessionBatchState ?? undefined, + + // File tree + fileTree: activeSession?.fileTree || [], + + // File preview navigation + canGoBack: filePreviewHistoryIndex > 0, + canGoForward: filePreviewHistoryIndex < filePreviewHistory.length - 1, + backHistory, + forwardHistory, + filePreviewHistoryIndex, + + // Active tab for error handling + activeTab, + + // Worktree + isWorktreeChild: !!activeSession?.parentSessionId, + + // Context management settings + contextWarningsEnabled: contextManagementSettings.contextWarningsEnabled, + contextWarningYellowThreshold: contextManagementSettings.contextWarningYellowThreshold, + contextWarningRedThreshold: contextManagementSettings.contextWarningRedThreshold, + + // Summarization progress + summarizeProgress, + summarizeResult, + summarizeStartTime: startTime, + isSummarizing: summarizeState === 'summarizing', + + // Merge progress + mergeProgress, + mergeStartTime, + isMerging: mergeState === 'merging', + mergeSourceName, + mergeTargetName, + + // Gist publishing + ghCliAvailable, + hasGist: previewFile ? !!fileGistUrls[previewFile.path] : false, + + // Unread filter + showUnreadOnly, + + // Audio feedback + audioFeedbackCommand, + + // Setters + setLogViewerSelectedLevels, + setGitDiffPreview, + setLogViewerOpen, + setAgentSessionsOpen, + setActiveAgentSessionId, + setActiveFocus, + setOutputSearchOpen, + setOutputSearchQuery, + setInputValue, + setEnterToSendAI, + setEnterToSendTerminal, + setStagedImages, + setCommandHistoryOpen, + setCommandHistoryFilter, + setCommandHistorySelectedIndex, + setSlashCommandOpen, + setSelectedSlashCommandIndex, + setTabCompletionOpen, + setSelectedTabCompletionIndex, + setTabCompletionFilter, + setAtMentionOpen, + setAtMentionFilter, + setAtMentionStartIndex, + setSelectedAtMentionIndex, + setPreviewFile, + setMarkdownEditMode, + setAboutModalOpen, + setRightPanelOpen, + setGitLogOpen, + + // Refs + inputRef, + logsEndRef, + terminalOutputRef, + fileTreeContainerRef, + fileTreeFilterInputRef, + + // Handlers + handleResumeSession, + handleNewAgentSession, + toggleInputMode, + processInput, + handleInterrupt, + handleInputKeyDown, + handlePaste, + handleDrop, + getContextColor, + setActiveSessionId, + handleStopBatchRun, + showConfirmation, + handleDeleteLog, + handleRemoveQueuedItem, + handleOpenQueueBrowser, + + // Tab management handlers + handleTabSelect, + handleTabClose, + handleNewTab, + handleRequestTabRename, + handleTabReorder, + handleUpdateTabByClaudeSessionId, + handleTabStar, + handleTabMarkUnread, + handleToggleTabReadOnlyMode, + handleToggleTabSaveToHistory, + handleToggleTabShowThinking, + toggleUnreadFilter, + handleOpenTabSearch, + handleCloseAllTabs, + handleCloseOtherTabs, + handleCloseTabsLeft, + handleCloseTabsRight, + handleScrollPositionChange, + handleAtBottomChange, + handleMainPanelInputBlur, + handleOpenPromptComposer, + handleReplayMessage, + handleMainPanelFileClick, + handleNavigateBack, + handleNavigateForward, + handleNavigateToIndex, + handleClearAgentErrorForMainPanel, + handleShowAgentErrorModal, + showSuccessFlash, + handleOpenFuzzySearch, + handleOpenWorktreeConfig, + handleOpenCreatePR, + handleSummarizeAndContinue, + handleMergeWith, + handleOpenSendToAgentModal, + handleCopyContext, + handleExportHtml, + handlePublishTabGist, + cancelTab, + cancelMergeTab, + recordShortcutUsage, + onKeyboardMasteryLevelUp, + handleSetLightboxImage, + + // Gist publishing + setGistPublishModalOpen, + + // Document Graph + setGraphFocusFilePath, + setLastGraphFocusFilePath, + setIsGraphViewOpen, + + // Wizard callbacks + generateInlineWizardDocuments, + retryInlineWizardMessage, + clearInlineWizardError, + endInlineWizard, + handleAutoRunRefresh, + + // Complex wizard handlers + onWizardComplete: handleWizardComplete, + onWizardLetsGo: handleWizardLetsGo, + onWizardRetry: retryInlineWizardMessage, + onWizardClearError: clearInlineWizardError, + onToggleWizardShowThinking: handleToggleWizardShowThinking, + + // Helper functions + getActiveTab, + }); + + const sessionListProps = useSessionListProps({ + // Core state + theme, + sessions, + groups, + sortedSessions, + activeSessionId, + leftSidebarOpen, + leftSidebarWidth, + activeFocus, + selectedSidebarIndex, + editingGroupId, + editingSessionId, + draggingSessionId, + shortcuts, + + // Global Live Mode + isLiveMode, + webInterfaceUrl, + + // Web Interface Port Settings + webInterfaceUseCustomPort: settings.webInterfaceUseCustomPort, + webInterfaceCustomPort: settings.webInterfaceCustomPort, + + // Folder states + bookmarksCollapsed, + ungroupedCollapsed: settings.ungroupedCollapsed, + + // Auto mode + activeBatchSessionIds, + + // Session jump shortcuts + showSessionJumpNumbers, + visibleSessions, + + // Achievement system + autoRunStats, + + // Group Chat state + groupChats, + activeGroupChatId, + groupChatsExpanded, + groupChatState, + participantStates, + groupChatStates, + allGroupChatParticipantStates, + + // Setters + setWebInterfaceUseCustomPort: settings.setWebInterfaceUseCustomPort, + setWebInterfaceCustomPort: settings.setWebInterfaceCustomPort, + setBookmarksCollapsed, + setUngroupedCollapsed: settings.setUngroupedCollapsed, + setActiveFocus, + setActiveSessionId, + setLeftSidebarOpen, + setLeftSidebarWidth, + setShortcutsHelpOpen, + setSettingsModalOpen, + setSettingsTab, + setAboutModalOpen, + setUpdateCheckModalOpen, + setLogViewerOpen, + setProcessMonitorOpen, + setUsageDashboardOpen, + setGroups, + setSessions, + setRenameInstanceModalOpen, + setRenameInstanceValue, + setRenameInstanceSessionId, + setDuplicatingSessionId, + setGroupChatsExpanded, + + // Handlers + toggleGlobalLive, + restartWebServer, + toggleGroup, + handleDragStart, + handleDragOver, + handleDropOnGroup, + handleDropOnUngrouped, + finishRenamingGroup, + finishRenamingSession, + startRenamingGroup, + startRenamingSession, + showConfirmation, + createNewGroup, + handleCreateGroupAndMove, + addNewSession, + deleteSession, + deleteWorktreeGroup, + handleEditAgent, + handleOpenCreatePRSession, + handleQuickCreateWorktree, + handleOpenWorktreeConfigSession, + handleDeleteWorktreeSession, + handleToggleWorktreeExpanded, + openWizardModal, + handleStartTour, + + // Group Chat handlers + handleOpenGroupChat, + handleNewGroupChat, + handleEditGroupChat, + handleOpenRenameGroupChatModal, + handleOpenDeleteGroupChatModal, + + // Ref + sidebarContainerRef, + }); + + const rightPanelProps = useRightPanelProps({ + // Session & Theme + activeSession, + theme, + shortcuts, + + // Panel state + rightPanelOpen, + rightPanelWidth, + + // Tab state + activeRightTab, + + // Focus management + activeFocus, + + // File explorer state + fileTreeFilter, + fileTreeFilterOpen, + filteredFileTree, + selectedFileIndex, + previewFile, + showHiddenFiles, + + // Auto Run state + autoRunDocumentList, + autoRunDocumentTree, + autoRunIsLoadingDocuments, + autoRunDocumentTaskCounts, + + // Batch processing (convert null to undefined for component props) + activeBatchRunState: activeBatchRunState ?? undefined, + currentSessionBatchState: currentSessionBatchState ?? undefined, + + // Document Graph + lastGraphFocusFilePath: lastGraphFocusFilePath || undefined, + + // Refs + fileTreeContainerRef, + fileTreeFilterInputRef, + + // Setters + setRightPanelOpen, + setRightPanelWidth, + setActiveFocus, + setFileTreeFilter, + setFileTreeFilterOpen, + setSelectedFileIndex, + setShowHiddenFiles, + setSessions, + + // Handlers + handleSetActiveRightTab, + toggleFolder, + handleFileClick, + expandAllFolders, + collapseAllFolders, + updateSessionWorkingDirectory, + refreshFileTree, + handleAutoRefreshChange, + showSuccessFlash, + + // Auto Run handlers + handleAutoRunContentChange, + handleAutoRunModeChange, + handleAutoRunStateChange, + handleAutoRunSelectDocument, + handleAutoRunCreateDocument, + handleAutoRunRefresh, + handleAutoRunOpenSetup, + + // Batch processing handlers + handleOpenBatchRunner, + handleStopBatchRun, + handleSkipCurrentDocument, + handleAbortBatchOnError, + handleResumeAfterError, + handleJumpToAgentSession, + handleResumeSession, + + // Modal handlers + handleOpenAboutModal, + handleOpenMarketplace, + handleLaunchWizardTab, + + // File linking + handleMainPanelFileClick, + + // Document Graph handlers + handleFocusFileInGraph, + handleOpenLastDocumentGraph, + }); + return ( 0 && ( - + )} @@ -13385,344 +13841,7 @@ You are taking over this conversation. Based on the context above, provide a bri {sessions.length > 0 && !activeGroupChatId && !logViewerOpen && ( 0} - canGoForward={ - filePreviewHistoryIndex < filePreviewHistory.length - 1 - } - onNavigateBack={handleNavigateBack} - onNavigateForward={handleNavigateForward} - backHistory={backHistory} - forwardHistory={forwardHistory} - currentHistoryIndex={filePreviewHistoryIndex} - onNavigateToIndex={handleNavigateToIndex} - onClearAgentError={activeTab?.agentError ? handleClearAgentErrorForMainPanel : undefined} - onShowAgentErrorModal={activeTab?.agentError ? handleShowAgentErrorModal : undefined} - showFlashNotification={showSuccessFlash} - onOpenFuzzySearch={handleOpenFuzzySearch} - onOpenWorktreeConfig={handleOpenWorktreeConfig} - onOpenCreatePR={handleOpenCreatePR} - isWorktreeChild={!!activeSession?.parentSessionId} - onSummarizeAndContinue={handleSummarizeAndContinue} - onMergeWith={handleMergeWith} - onSendToAgent={handleOpenSendToAgentModal} - onCopyContext={handleCopyContext} - onExportHtml={handleExportHtml} - onPublishTabGist={handlePublishTabGist} - // Context warning sash settings (Phase 6) - contextWarningsEnabled={ - contextManagementSettings.contextWarningsEnabled - } - contextWarningYellowThreshold={ - contextManagementSettings.contextWarningYellowThreshold - } - contextWarningRedThreshold={ - contextManagementSettings.contextWarningRedThreshold - } - // Summarization progress props (non-blocking, per-tab) - summarizeProgress={summarizeProgress} - summarizeResult={summarizeResult} - summarizeStartTime={startTime} - isSummarizing={summarizeState === 'summarizing'} - onCancelSummarize={() => { - if (activeSession?.activeTabId) { - cancelTab(activeSession.activeTabId); - } - }} - // Merge progress props (non-blocking, per-tab) - mergeProgress={mergeProgress} - mergeResult={null} - mergeStartTime={mergeStartTime} - isMerging={mergeState === 'merging'} - mergeSourceName={mergeSourceName} - mergeTargetName={mergeTargetName} - onCancelMerge={() => { - if (activeSession?.activeTabId) { - cancelMergeTab(activeSession.activeTabId); - } - }} - onShortcutUsed={(shortcutId: string) => { - const result = recordShortcutUsage(shortcutId); - if (result.newLevel !== null) { - onKeyboardMasteryLevelUp(result.newLevel); - } - }} - ghCliAvailable={ghCliAvailable} - onPublishGist={() => setGistPublishModalOpen(true)} - hasGist={previewFile ? !!fileGistUrls[previewFile.path] : false} - onOpenInGraph={() => { - if (previewFile && activeSession) { - // Use the same rootPath that DocumentGraphView will use - const graphRootPath = - activeSession.projectRoot || activeSession.cwd || ''; - // Compute relative path from the preview file - const relativePath = previewFile.path.startsWith( - graphRootPath + '/' - ) - ? previewFile.path.slice(graphRootPath.length + 1) - : previewFile.path.startsWith(graphRootPath) - ? previewFile.path.slice(graphRootPath.length + 1) - : previewFile.name; - setGraphFocusFilePath(relativePath); - setLastGraphFocusFilePath(relativePath); // Track for "Last Document Graph" in command palette - setIsGraphViewOpen(true); - } - }} - // Inline wizard completion callback - switches tab to wizard session for context continuity - onWizardComplete={() => { - if (!activeSession) return; - // Get wizard state from the active tab (not session level) - const activeTab = getActiveTab(activeSession); - const wizardState = activeTab?.wizardState; - if (!wizardState) return; - - // Convert wizard conversation history to log entries - const wizardLogEntries: import('./types').LogEntry[] = - wizardState.conversationHistory.map(msg => ({ - id: `wizard-${msg.id}`, - timestamp: msg.timestamp, - source: msg.role === 'user' ? 'user' : 'ai', - text: msg.content, - delivered: true - })); - - // Create summary message with next steps - const generatedDocs = wizardState.generatedDocuments || []; - const totalTasks = generatedDocs.reduce( - (sum, doc) => sum + doc.taskCount, - 0 - ); - const docNames = generatedDocs.map(d => d.filename).join(', '); - - const summaryMessage: import('./types').LogEntry = { - id: `wizard-summary-${Date.now()}`, - timestamp: Date.now(), - source: 'ai', - text: - `## Wizard Complete\n\n` + - `Created ${generatedDocs.length} document${ - generatedDocs.length !== 1 ? 's' : '' - } with ${totalTasks} task${totalTasks !== 1 ? 's' : ''}:\n` + - `${docNames}\n\n` + - `**Next steps:**\n` + - `1. Open the **Auto Run** tab in the right panel to view your playbook\n` + - `2. Review and edit tasks as needed\n` + - `3. Click **Run** to start executing tasks automatically\n\n` + - `You can continue chatting to iterate on your playbook - the AI has full context of what was created.`, - delivered: true - }; - - // Derive tab name from the subfolder where documents were saved - // The subfolderName is stored in the wizard state after generation completes - const subfolderName = wizardState.subfolderName || ''; - const tabName = subfolderName || 'Wizard'; - - // Get the wizard's agentSessionId for tab context switching - const wizardAgentSessionId = wizardState.agentSessionId; - - // Add wizard logs to active tab, switch to wizard session, rename tab, and clear wizard state - const activeTabId = activeTab.id; - setSessions(prev => - prev.map(s => { - if (s.id !== activeSession.id) return s; - - // Update tab: add logs, switch agentSessionId, rename, and clear wizard state - const updatedTabs = s.aiTabs.map(tab => { - if (tab.id !== activeTabId) return tab; - return { - ...tab, - logs: [...tab.logs, ...wizardLogEntries, summaryMessage], - // Switch to wizard's agentSessionId so user can continue iterating with full context - agentSessionId: - wizardAgentSessionId || tab.agentSessionId, - // Name the tab to indicate it's a project from the wizard - name: tabName, - // Clear wizard state from the tab - wizardState: undefined - }; - }); - - return { - ...s, - aiTabs: updatedTabs - }; - }) - ); - - // CRITICAL: Also reset the useInlineWizard hook state - // Without this, the hook remains active and will re-sync its state back to session.wizardState - endInlineWizard(); - - // Refresh the Auto Run panel to show newly generated documents - handleAutoRunRefresh(); - - // Clear the input value that may have wizard-related text - setInputValue(''); - }} - // Inline wizard callbacks - onWizardLetsGo={() => { - // Pass the active tab ID to ensure we generate for the correct tab - const activeTab = activeSession - ? getActiveTab(activeSession) - : null; - if (activeTab) { - generateInlineWizardDocuments(undefined, activeTab.id); - } - }} - onWizardRetry={retryInlineWizardMessage} - onWizardClearError={clearInlineWizardError} - // Inline wizard exit handler (for WizardInputPanel) - onExitWizard={endInlineWizard} - // Cancel generation and exit wizard - onWizardCancelGeneration={endInlineWizard} - // Wizard thinking toggle - onToggleWizardShowThinking={() => { - if (!activeSession) return; - const activeTab = getActiveTab(activeSession); - if (!activeTab?.wizardState) return; - setSessions(prev => - prev.map(s => { - if (s.id !== activeSession.id) return s; - return { - ...s, - aiTabs: s.aiTabs.map(tab => { - if (tab.id !== activeTab.id) return tab; - if (!tab.wizardState) return tab; - // Toggle showWizardThinking and clear thinkingContent when turning off - return { - ...tab, - wizardState: { - ...tab.wizardState, - showWizardThinking: - !tab.wizardState.showWizardThinking, - thinkingContent: !tab.wizardState.showWizardThinking - ? '' - : tab.wizardState.thinkingContent - } - }; - }) - }; - }) - ); - }} + {...mainPanelProps} /> )} @@ -13734,70 +13853,7 @@ You are taking over this conversation. Based on the context above, provide a bri )} diff --git a/src/renderer/hooks/props/useMainPanelProps.ts b/src/renderer/hooks/props/useMainPanelProps.ts index fef664e8..eb5e2fdc 100644 --- a/src/renderer/hooks/props/useMainPanelProps.ts +++ b/src/renderer/hooks/props/useMainPanelProps.ts @@ -18,11 +18,13 @@ import type { FocusArea, BatchRunState, LogEntry, - UsageStats + UsageStats, + AITab } from '../../types'; import type { TabCompletionSuggestion, TabCompletionFilter } from '../input/useTabCompletion'; import type { SummarizeProgress, SummarizeResult, GroomingProgress, MergeResult } from '../../types/contextMerge'; import type { FileNode } from '../../types/fileTree'; +import type { DocumentGenerationCallbacks } from '../../services/inlineWizardDocumentGeneration'; /** * Dependencies for computing MainPanel props. @@ -80,9 +82,9 @@ export interface UseMainPanelPropsDeps { }>; selectedAtMentionIndex: number; - // Batch run state - activeBatchRunState: BatchRunState | null; - currentSessionBatchState: BatchRunState | null; + // Batch run state (undefined matches component prop type) + activeBatchRunState: BatchRunState | undefined; + currentSessionBatchState: BatchRunState | undefined; // File tree fileTree: FileNode[]; @@ -95,7 +97,7 @@ export interface UseMainPanelPropsDeps { filePreviewHistoryIndex: number; // Active tab for error handling - activeTab: { agentError?: unknown } | null; + activeTab: AITab | undefined; // Worktree isWorktreeChild: boolean; @@ -115,8 +117,8 @@ export interface UseMainPanelPropsDeps { mergeProgress: GroomingProgress | null; mergeStartTime: number; isMerging: boolean; - mergeSourceName: string; - mergeTargetName: string; + mergeSourceName: string | undefined; + mergeTargetName: string | undefined; // Gist publishing ghCliAvailable: boolean; @@ -250,14 +252,21 @@ export interface UseMainPanelPropsDeps { setIsGraphViewOpen: (open: boolean) => void; // Wizard callbacks - generateInlineWizardDocuments: (content?: string, tabId?: string) => void; + generateInlineWizardDocuments: (callbacks?: DocumentGenerationCallbacks, tabId?: string) => Promise; retryInlineWizardMessage: () => void; clearInlineWizardError: () => void; endInlineWizard: () => void; handleAutoRunRefresh: () => void; + // Complex wizard handlers (passed through from App.tsx) + onWizardComplete?: () => void; + onWizardLetsGo?: () => void; + onWizardRetry?: () => void; + onWizardClearError?: () => void; + onToggleWizardShowThinking?: () => void; + // Helper functions - getActiveTab: (session: Session) => { id: string; wizardState?: unknown } | null; + getActiveTab: (session: Session) => AITab | undefined; } /** @@ -463,6 +472,12 @@ export function useMainPanelProps(deps: UseMainPanelPropsDeps) { // Inline wizard callbacks handled inline to maintain closure access onExitWizard: deps.endInlineWizard, onWizardCancelGeneration: deps.endInlineWizard, + // Complex wizard handlers (passed through from App.tsx) + onWizardComplete: deps.onWizardComplete, + onWizardLetsGo: deps.onWizardLetsGo, + onWizardRetry: deps.onWizardRetry, + onWizardClearError: deps.onWizardClearError, + onToggleWizardShowThinking: deps.onToggleWizardShowThinking, }), [ // Primitive dependencies for minimal re-computation deps.logViewerOpen, @@ -628,6 +643,12 @@ export function useMainPanelProps(deps: UseMainPanelPropsDeps) { deps.setLastGraphFocusFilePath, deps.setIsGraphViewOpen, deps.endInlineWizard, + // Complex wizard handlers + deps.onWizardComplete, + deps.onWizardLetsGo, + deps.onWizardRetry, + deps.onWizardClearError, + deps.onToggleWizardShowThinking, // Refs (stable, but included for completeness) deps.inputRef, deps.logsEndRef, diff --git a/src/renderer/hooks/props/useRightPanelProps.ts b/src/renderer/hooks/props/useRightPanelProps.ts index 794acbd5..767802b1 100644 --- a/src/renderer/hooks/props/useRightPanelProps.ts +++ b/src/renderer/hooks/props/useRightPanelProps.ts @@ -56,11 +56,11 @@ export interface UseRightPanelPropsDeps { autoRunDocumentTaskCounts: Map | undefined; // Batch processing - activeBatchRunState: BatchRunState | null; - currentSessionBatchState: BatchRunState | null; + activeBatchRunState: BatchRunState | undefined; + currentSessionBatchState: BatchRunState | undefined; // Document Graph - lastGraphFocusFilePath: string; + lastGraphFocusFilePath: string | undefined; // Refs fileTreeContainerRef: React.RefObject;