mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-03-19 10:43:08 +00:00
Fix concurrency limits and remote branch fetching issues (#788)
* Changes from fix/bug-fixes * feat: Refactor worktree iteration and improve error logging across services * feat: Extract URL/port patterns to module level and fix abort condition * fix: Improve IPv6 loopback handling, select component layout, and terminal UI * feat: Add thinking level defaults and adjust list row padding * Update apps/ui/src/store/app-store.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * feat: Add worktree-aware terminal creation and split options, fix npm security issues from audit * feat: Add tracked remote detection to pull dialog flow * feat: Add merge state tracking to git operations * feat: Improve merge detection and add post-merge action preferences * Update apps/ui/src/components/views/board-view/dialogs/git-pull-dialog.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update apps/ui/src/components/views/board-view/dialogs/git-pull-dialog.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * fix: Pass merge detection info to stash reapplication and handle merge state consistently * fix: Call onPulled callback in merge handlers and add validation checks --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This commit is contained in:
@@ -298,6 +298,7 @@ const initialState: AppState = {
|
||||
enableDependencyBlocking: true,
|
||||
skipVerificationInAutoMode: false,
|
||||
enableAiCommitMessages: true,
|
||||
mergePostAction: null,
|
||||
planUseSelectedWorktreeBranch: true,
|
||||
addFeatureUseSelectedWorktreeBranch: false,
|
||||
useWorktrees: true,
|
||||
@@ -362,6 +363,8 @@ const initialState: AppState = {
|
||||
defaultPlanningMode: 'skip' as PlanningMode,
|
||||
defaultRequirePlanApproval: false,
|
||||
defaultFeatureModel: DEFAULT_GLOBAL_SETTINGS.defaultFeatureModel,
|
||||
defaultThinkingLevel: DEFAULT_GLOBAL_SETTINGS.defaultThinkingLevel ?? 'none',
|
||||
defaultReasoningEffort: DEFAULT_GLOBAL_SETTINGS.defaultReasoningEffort ?? 'none',
|
||||
pendingPlanApproval: null,
|
||||
claudeRefreshInterval: 60,
|
||||
claudeUsage: null,
|
||||
@@ -1117,6 +1120,16 @@ export const useAppStore = create<AppState & AppActions>()((set, get) => ({
|
||||
logger.error('Failed to sync enableAiCommitMessages:', error);
|
||||
}
|
||||
},
|
||||
setMergePostAction: async (action) => {
|
||||
set({ mergePostAction: action });
|
||||
// Sync to server
|
||||
try {
|
||||
const httpApi = getHttpApiClient();
|
||||
await httpApi.put('/api/settings', { mergePostAction: action });
|
||||
} catch (error) {
|
||||
logger.error('Failed to sync mergePostAction:', error);
|
||||
}
|
||||
},
|
||||
setPlanUseSelectedWorktreeBranch: async (enabled) => {
|
||||
set({ planUseSelectedWorktreeBranch: enabled });
|
||||
// Sync to server
|
||||
@@ -2313,6 +2326,28 @@ export const useAppStore = create<AppState & AppActions>()((set, get) => ({
|
||||
setDefaultRequirePlanApproval: (require) => set({ defaultRequirePlanApproval: require }),
|
||||
setDefaultFeatureModel: (entry) => set({ defaultFeatureModel: entry }),
|
||||
|
||||
setDefaultThinkingLevel: async (level) => {
|
||||
set({ defaultThinkingLevel: level });
|
||||
// Sync to server
|
||||
try {
|
||||
const httpApi = getHttpApiClient();
|
||||
await httpApi.put('/api/settings', { defaultThinkingLevel: level });
|
||||
} catch (error) {
|
||||
logger.error('Failed to sync defaultThinkingLevel:', error);
|
||||
}
|
||||
},
|
||||
|
||||
setDefaultReasoningEffort: async (effort) => {
|
||||
set({ defaultReasoningEffort: effort });
|
||||
// Sync to server
|
||||
try {
|
||||
const httpApi = getHttpApiClient();
|
||||
await httpApi.put('/api/settings', { defaultReasoningEffort: effort });
|
||||
} catch (error) {
|
||||
logger.error('Failed to sync defaultReasoningEffort:', error);
|
||||
}
|
||||
},
|
||||
|
||||
// Plan Approval actions
|
||||
setPendingPlanApproval: (approval) => set({ pendingPlanApproval: approval }),
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ import type {
|
||||
ClaudeApiProfile,
|
||||
ClaudeCompatibleProvider,
|
||||
SidebarStyle,
|
||||
ThinkingLevel,
|
||||
ReasoningEffort,
|
||||
} from '@automaker/types';
|
||||
|
||||
import type {
|
||||
@@ -127,6 +129,7 @@ export interface AppState {
|
||||
enableDependencyBlocking: boolean; // When true, show blocked badges and warnings for features with incomplete dependencies (default: true)
|
||||
skipVerificationInAutoMode: boolean; // When true, auto-mode grabs features even if dependencies are not verified (only checks they're not running)
|
||||
enableAiCommitMessages: boolean; // When true, auto-generate commit messages using AI when opening commit dialog
|
||||
mergePostAction: 'commit' | 'manual' | null; // User's preferred action after a clean merge (null = ask every time)
|
||||
planUseSelectedWorktreeBranch: boolean; // When true, Plan dialog creates features on the currently selected worktree branch
|
||||
addFeatureUseSelectedWorktreeBranch: boolean; // When true, Add Feature dialog defaults to custom mode with selected worktree branch
|
||||
|
||||
@@ -175,6 +178,10 @@ export interface AppState {
|
||||
phaseModels: PhaseModelConfig;
|
||||
favoriteModels: string[];
|
||||
|
||||
// Default thinking/reasoning levels for two-stage model selector primary button
|
||||
defaultThinkingLevel: ThinkingLevel;
|
||||
defaultReasoningEffort: ReasoningEffort;
|
||||
|
||||
// Cursor CLI Settings (global)
|
||||
enabledCursorModels: CursorModelId[]; // Which Cursor models are available in feature modal
|
||||
cursorDefaultModel: CursorModelId; // Default Cursor model selection
|
||||
@@ -488,6 +495,7 @@ export interface AppActions {
|
||||
setEnableDependencyBlocking: (enabled: boolean) => void;
|
||||
setSkipVerificationInAutoMode: (enabled: boolean) => Promise<void>;
|
||||
setEnableAiCommitMessages: (enabled: boolean) => Promise<void>;
|
||||
setMergePostAction: (action: 'commit' | 'manual' | null) => Promise<void>;
|
||||
setPlanUseSelectedWorktreeBranch: (enabled: boolean) => Promise<void>;
|
||||
setAddFeatureUseSelectedWorktreeBranch: (enabled: boolean) => Promise<void>;
|
||||
|
||||
@@ -548,6 +556,8 @@ export interface AppActions {
|
||||
setPhaseModels: (models: Partial<PhaseModelConfig>) => Promise<void>;
|
||||
resetPhaseModels: () => Promise<void>;
|
||||
toggleFavoriteModel: (modelId: string) => void;
|
||||
setDefaultThinkingLevel: (level: ThinkingLevel) => void;
|
||||
setDefaultReasoningEffort: (effort: ReasoningEffort) => void;
|
||||
|
||||
// Cursor CLI Settings actions
|
||||
setEnabledCursorModels: (models: CursorModelId[]) => void;
|
||||
|
||||
@@ -35,6 +35,8 @@ interface UICacheState {
|
||||
cachedWorktreePanelCollapsed: boolean;
|
||||
/** Collapsed nav sections */
|
||||
cachedCollapsedNavSections: Record<string, boolean>;
|
||||
/** Selected worktree per project (path + branch) for instant restore on PWA reload */
|
||||
cachedCurrentWorktreeByProject: Record<string, { path: string | null; branch: string }>;
|
||||
}
|
||||
|
||||
interface UICacheActions {
|
||||
@@ -52,19 +54,29 @@ export const useUICacheStore = create<UICacheState & UICacheActions>()(
|
||||
cachedSidebarStyle: 'unified',
|
||||
cachedWorktreePanelCollapsed: false,
|
||||
cachedCollapsedNavSections: {},
|
||||
cachedCurrentWorktreeByProject: {},
|
||||
|
||||
updateFromAppStore: (state) => set(state),
|
||||
}),
|
||||
{
|
||||
name: STORE_NAME,
|
||||
version: 1,
|
||||
version: 2,
|
||||
partialize: (state) => ({
|
||||
cachedProjectId: state.cachedProjectId,
|
||||
cachedSidebarOpen: state.cachedSidebarOpen,
|
||||
cachedSidebarStyle: state.cachedSidebarStyle,
|
||||
cachedWorktreePanelCollapsed: state.cachedWorktreePanelCollapsed,
|
||||
cachedCollapsedNavSections: state.cachedCollapsedNavSections,
|
||||
cachedCurrentWorktreeByProject: state.cachedCurrentWorktreeByProject,
|
||||
}),
|
||||
migrate: (persistedState: unknown, version: number) => {
|
||||
const state = persistedState as Record<string, unknown>;
|
||||
if (version < 2) {
|
||||
// Migration from v1: add cachedCurrentWorktreeByProject
|
||||
state.cachedCurrentWorktreeByProject = {};
|
||||
}
|
||||
return state as unknown as UICacheState & UICacheActions;
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
@@ -82,6 +94,7 @@ export function syncUICache(appState: {
|
||||
sidebarStyle?: 'unified' | 'discord';
|
||||
worktreePanelCollapsed?: boolean;
|
||||
collapsedNavSections?: Record<string, boolean>;
|
||||
currentWorktreeByProject?: Record<string, { path: string | null; branch: string }>;
|
||||
}): void {
|
||||
const update: Partial<UICacheState> = {};
|
||||
|
||||
@@ -100,6 +113,9 @@ export function syncUICache(appState: {
|
||||
if ('collapsedNavSections' in appState) {
|
||||
update.cachedCollapsedNavSections = appState.collapsedNavSections;
|
||||
}
|
||||
if ('currentWorktreeByProject' in appState) {
|
||||
update.cachedCurrentWorktreeByProject = appState.currentWorktreeByProject;
|
||||
}
|
||||
|
||||
if (Object.keys(update).length > 0) {
|
||||
useUICacheStore.getState().updateFromAppStore(update);
|
||||
@@ -142,6 +158,15 @@ export function restoreFromUICache(
|
||||
collapsedNavSections: cache.cachedCollapsedNavSections,
|
||||
};
|
||||
|
||||
// Restore last selected worktree per project so the board doesn't
|
||||
// reset to main branch after PWA memory eviction or tab discard.
|
||||
if (
|
||||
cache.cachedCurrentWorktreeByProject &&
|
||||
Object.keys(cache.cachedCurrentWorktreeByProject).length > 0
|
||||
) {
|
||||
stateUpdate.currentWorktreeByProject = cache.cachedCurrentWorktreeByProject;
|
||||
}
|
||||
|
||||
// Restore the project context when the project object is available.
|
||||
// When projects are not yet loaded (empty array), currentProject remains
|
||||
// null and will be properly set later by hydrateStoreFromSettings().
|
||||
|
||||
Reference in New Issue
Block a user