Skip to content
Closed
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
4c9f951
fix: re-enable batch state debouncing to resolve Auto Run performance…
Feb 26, 2026
48b8de3
MAESTRO: port agent-inbox shared types from feature/inbox-focus-polish
Feb 26, 2026
efe7dfc
MAESTRO: add unifiedInbox flag to EncoreFeatureFlags
Feb 26, 2026
9268995
MAESTRO: add Unified Inbox toggle card in Settings Encore tab
Feb 26, 2026
e29b425
MAESTRO: port useAgentInbox hook and AgentInbox components from featu…
Feb 26, 2026
615ff25
MAESTRO: integrate Unified Inbox modal into App.tsx with Encore Featu…
Feb 26, 2026
7eff634
MAESTRO: register Option+I keyboard shortcut for Unified Inbox with E…
Feb 26, 2026
d6842b1
MAESTRO: add Unified Inbox menu item to hamburger menu in SessionList
Feb 26, 2026
4403705
MAESTRO: add Unified Inbox action to command palette (QuickActionsModal)
Feb 26, 2026
2a05348
MAESTRO: fix unused-var eslint warning in FocusModeView
Feb 26, 2026
cd0734c
MAESTRO: fix Focus Mode auto-scroll bug with proximity-based approach
Feb 26, 2026
cf06151
MAESTRO: fix CodeRabbit bugs — group header a11y, scoped collapse, se…
Feb 26, 2026
1b65706
MAESTRO: align Inbox + Focus Mode headers with Director's Notes tokens
Feb 26, 2026
c47fca2
MAESTRO: align Focus Mode content spacing + reply input with Director…
Feb 26, 2026
d9698cb
MAESTRO: mark test verification gate as passed — 3 pre-existing Codex…
Feb 26, 2026
26d100b
MAESTRO: mark final verification gate as passed — ESLint clean + all …
Feb 26, 2026
3c388c7
MAESTRO: remove redundant star icons from Inbox + Focus Mode
Feb 26, 2026
b9252ef
MAESTRO: add description field to AITab and tabDescription flag to En…
Feb 26, 2026
d4829ed
MAESTRO: add Tab Description Settings toggle and handleUpdateTabDescr…
Feb 26, 2026
3cf3ccd
MAESTRO: wire tab description handler through prop chain and build in…
Feb 26, 2026
ed2e54b
MAESTRO: constrain tab description to 3-line max with ellipsis overflow
Feb 26, 2026
f494fad
fix: enable fuzzy matching for session filter in Left Bar
Feb 26, 2026
ad846a8
fix: enable fuzzy matching for slash command autocomplete in input area
Feb 26, 2026
f779e9a
fix: update fuzzy autocomplete test, remove duplicate log entry, cons…
Feb 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 4 additions & 115 deletions src/renderer/hooks/batch/useBatchProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,28 +220,7 @@ export function useBatchProcessor({
// Dispatch batch actions through the store. The store applies batchReducer
// synchronously, eliminating the need for manual ref syncing.
const dispatch = useCallback((action: BatchAction) => {
const prevStates = useBatchStore.getState().batchRunStates;
useBatchStore.getState().dispatchBatch(action);
const newStates = useBatchStore.getState().batchRunStates;

// DEBUG: Log dispatch to trace state updates
if (
action.type === 'START_BATCH' ||
action.type === 'UPDATE_PROGRESS' ||
action.type === 'SET_STOPPING' ||
action.type === 'COMPLETE_BATCH'
) {
const sessionId = action.sessionId;
console.log('[BatchProcessor:dispatch]', action.type, {
sessionId,
prevIsRunning: prevStates[sessionId]?.isRunning,
newIsRunning: newStates[sessionId]?.isRunning,
prevIsStopping: prevStates[sessionId]?.isStopping,
newIsStopping: newStates[sessionId]?.isStopping,
prevCompleted: prevStates[sessionId]?.completedTasksAcrossAllDocs,
newCompleted: newStates[sessionId]?.completedTasksAcrossAllDocs,
});
}
}, []);

// Custom prompts per session — lives in batchStore
Expand Down Expand Up @@ -274,10 +253,8 @@ export function useBatchProcessor({
// This handles React 18 StrictMode double-render and ensures ref is always correct
useEffect(() => {
isMountedRef.current = true;
console.log('[BatchProcessor] Mounted, isMountedRef set to true');
return () => {
isMountedRef.current = false;
console.log('[BatchProcessor] Unmounting, isMountedRef set to false');

// Reject all pending error resolution promises with 'abort' to unblock any waiting async code
// This prevents memory leaks from promises that would never resolve
Expand Down Expand Up @@ -321,7 +298,7 @@ export function useBatchProcessor({
}, []);

// Use extracted debounce hook for batch state updates (replaces manual debounce logic)
const { scheduleUpdate: _scheduleDebouncedUpdate, flushUpdate: flushDebouncedUpdate } =
const { scheduleUpdate: scheduleDebouncedUpdate, flushUpdate: flushDebouncedUpdate } =
useSessionDebounce<Record<string, BatchRunState>>({
delayMs: BATCH_STATE_DEBOUNCE_MS,
onUpdate: useCallback(
Expand All @@ -341,14 +318,6 @@ export function useBatchProcessor({
const newState = updater(currentState);
newStateForSession = newState[sessionId] || null;

// DEBUG: Log to trace progress updates
console.log('[BatchProcessor:onUpdate] Debounce fired:', {
sessionId,
refHasSession: !!currentState[sessionId],
refCompletedTasks: currentState[sessionId]?.completedTasksAcrossAllDocs,
newCompletedTasks: newStateForSession?.completedTasksAcrossAllDocs,
});

// Dispatch UPDATE_PROGRESS with the computed changes
// For complex state changes, we extract the session's new state and dispatch appropriately
if (newStateForSession) {
Expand Down Expand Up @@ -503,85 +472,11 @@ export function useBatchProcessor({
(
sessionId: string,
updater: (prev: Record<string, BatchRunState>) => Record<string, BatchRunState>,
_immediate: boolean = false
immediate: boolean = false
) => {
// DEBUG: Bypass debouncing entirely to test if that's the issue
// Apply update directly without debouncing
const currentState = useBatchStore.getState().batchRunStates;
const newState = updater(currentState);
const newStateForSession = newState[sessionId] || null;

console.log('[BatchProcessor:updateBatchStateAndBroadcast] DIRECT update (no debounce)', {
sessionId,
prevCompleted: currentState[sessionId]?.completedTasksAcrossAllDocs,
newCompleted: newStateForSession?.completedTasksAcrossAllDocs,
});

if (newStateForSession) {
const prevSessionState = currentState[sessionId] || DEFAULT_BATCH_STATE;

dispatch({
type: 'UPDATE_PROGRESS',
sessionId,
payload: {
currentDocumentIndex:
newStateForSession.currentDocumentIndex !== prevSessionState.currentDocumentIndex
? newStateForSession.currentDocumentIndex
: undefined,
currentDocTasksTotal:
newStateForSession.currentDocTasksTotal !== prevSessionState.currentDocTasksTotal
? newStateForSession.currentDocTasksTotal
: undefined,
currentDocTasksCompleted:
newStateForSession.currentDocTasksCompleted !==
prevSessionState.currentDocTasksCompleted
? newStateForSession.currentDocTasksCompleted
: undefined,
totalTasksAcrossAllDocs:
newStateForSession.totalTasksAcrossAllDocs !==
prevSessionState.totalTasksAcrossAllDocs
? newStateForSession.totalTasksAcrossAllDocs
: undefined,
completedTasksAcrossAllDocs:
newStateForSession.completedTasksAcrossAllDocs !==
prevSessionState.completedTasksAcrossAllDocs
? newStateForSession.completedTasksAcrossAllDocs
: undefined,
totalTasks:
newStateForSession.totalTasks !== prevSessionState.totalTasks
? newStateForSession.totalTasks
: undefined,
completedTasks:
newStateForSession.completedTasks !== prevSessionState.completedTasks
? newStateForSession.completedTasks
: undefined,
currentTaskIndex:
newStateForSession.currentTaskIndex !== prevSessionState.currentTaskIndex
? newStateForSession.currentTaskIndex
: undefined,
sessionIds:
newStateForSession.sessionIds !== prevSessionState.sessionIds
? newStateForSession.sessionIds
: undefined,
accumulatedElapsedMs:
newStateForSession.accumulatedElapsedMs !== prevSessionState.accumulatedElapsedMs
? newStateForSession.accumulatedElapsedMs
: undefined,
lastActiveTimestamp:
newStateForSession.lastActiveTimestamp !== prevSessionState.lastActiveTimestamp
? newStateForSession.lastActiveTimestamp
: undefined,
loopIteration:
newStateForSession.loopIteration !== prevSessionState.loopIteration
? newStateForSession.loopIteration
: undefined,
},
});
}

broadcastAutoRunState(sessionId, newStateForSession);
scheduleDebouncedUpdate(sessionId, updater, immediate);
},
[broadcastAutoRunState]
[scheduleDebouncedUpdate]
);

// Update ref to always have latest updateBatchStateAndBroadcast (fixes HMR stale closure)
Expand Down Expand Up @@ -1658,9 +1553,6 @@ export function useBatchProcessor({
// Critical: Always flush debounced updates and dispatch COMPLETE_BATCH to clean up state.
// These operations are safe regardless of mount state - React handles reducer dispatches gracefully,
// and broadcasts are external calls that don't affect React state.
console.log(
'[BatchProcessor:startBatchRun] Flushing debounced updates before COMPLETE_BATCH'
);
flushDebouncedUpdate(sessionId);

// Reset state for this session using COMPLETE_BATCH action
Expand Down Expand Up @@ -1728,7 +1620,6 @@ export function useBatchProcessor({
*/
const stopBatchRun = useCallback(
(sessionId: string) => {
console.log('[BatchProcessor:stopBatchRun] Called with sessionId:', sessionId);
stopRequestedRefs.current[sessionId] = true;
const errorResolution = errorResolutionRefs.current[sessionId];
if (errorResolution) {
Expand All @@ -1753,8 +1644,6 @@ export function useBatchProcessor({
*/
const killBatchRun = useCallback(
async (sessionId: string) => {
console.log('[BatchProcessor:killBatchRun] Force killing session:', sessionId);

// 1. Kill the agent process and wait for termination before cleaning up state
try {
await window.maestro.process.kill(sessionId);
Expand Down