mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-03-18 22:33:08 +00:00
feat: Add settingsService integration for feature defaults and improve worktree handling
This commit is contained in:
@@ -833,18 +833,11 @@ export function hydrateStoreFromSettings(settings: GlobalSettings): void {
|
||||
)
|
||||
)
|
||||
: current.agentModelBySession,
|
||||
// Sanitize currentWorktreeByProject: only restore entries where path is null
|
||||
// (main branch). Non-null paths point to worktree directories that may have
|
||||
// been deleted while the app was closed. Restoring a stale path causes the
|
||||
// board to render an invalid worktree selection, triggering a crash loop
|
||||
// (error boundary reloads → restores same bad path → crash again).
|
||||
// The use-worktrees validation effect will re-discover valid worktrees
|
||||
// from the server once they load.
|
||||
currentWorktreeByProject: Object.fromEntries(
|
||||
Object.entries(sanitizeWorktreeByProject(settings.currentWorktreeByProject)).filter(
|
||||
([, worktree]) => worktree.path === null
|
||||
)
|
||||
),
|
||||
// Restore all valid worktree selections (both main branch and feature worktrees).
|
||||
// The validation effect in use-worktrees.ts handles deleted worktrees gracefully
|
||||
// by resetting to main branch when the worktree list loads and the cached
|
||||
// worktree no longer exists.
|
||||
currentWorktreeByProject: sanitizeWorktreeByProject(settings.currentWorktreeByProject),
|
||||
// UI State
|
||||
worktreePanelCollapsed: settings.worktreePanelCollapsed ?? false,
|
||||
lastProjectDir: settings.lastProjectDir ?? '',
|
||||
|
||||
@@ -864,8 +864,8 @@ export async function refreshSettingsFromServer(): Promise<boolean> {
|
||||
)
|
||||
)
|
||||
: currentAppState.agentModelBySession,
|
||||
// Sanitize: only restore entries with path === null (main branch).
|
||||
// Non-null paths may reference deleted worktrees, causing crash loops.
|
||||
// Restore all valid worktree selections (both main branch and feature worktrees).
|
||||
// The validation effect in use-worktrees.ts handles deleted worktrees gracefully.
|
||||
currentWorktreeByProject: sanitizeWorktreeByProject(
|
||||
serverSettings.currentWorktreeByProject ?? currentAppState.currentWorktreeByProject
|
||||
),
|
||||
|
||||
@@ -2512,9 +2512,33 @@ export const useAppStore = create<AppState & AppActions>()((set, get) => ({
|
||||
setSpecCreatingForProject: (projectPath) => set({ specCreatingForProject: projectPath }),
|
||||
isSpecCreatingForProject: (projectPath) => get().specCreatingForProject === projectPath,
|
||||
|
||||
setDefaultPlanningMode: (mode) => set({ defaultPlanningMode: mode }),
|
||||
setDefaultRequirePlanApproval: (require) => set({ defaultRequirePlanApproval: require }),
|
||||
setDefaultFeatureModel: (entry) => set({ defaultFeatureModel: entry }),
|
||||
setDefaultPlanningMode: async (mode) => {
|
||||
set({ defaultPlanningMode: mode });
|
||||
try {
|
||||
const httpApi = getHttpApiClient();
|
||||
await httpApi.settings.updateGlobal({ defaultPlanningMode: mode });
|
||||
} catch (error) {
|
||||
logger.error('Failed to sync defaultPlanningMode:', error);
|
||||
}
|
||||
},
|
||||
setDefaultRequirePlanApproval: async (require) => {
|
||||
set({ defaultRequirePlanApproval: require });
|
||||
try {
|
||||
const httpApi = getHttpApiClient();
|
||||
await httpApi.settings.updateGlobal({ defaultRequirePlanApproval: require });
|
||||
} catch (error) {
|
||||
logger.error('Failed to sync defaultRequirePlanApproval:', error);
|
||||
}
|
||||
},
|
||||
setDefaultFeatureModel: async (entry) => {
|
||||
set({ defaultFeatureModel: entry });
|
||||
try {
|
||||
const httpApi = getHttpApiClient();
|
||||
await httpApi.settings.updateGlobal({ defaultFeatureModel: entry });
|
||||
} catch (error) {
|
||||
logger.error('Failed to sync defaultFeatureModel:', error);
|
||||
}
|
||||
},
|
||||
|
||||
setDefaultThinkingLevel: async (level) => {
|
||||
const currentModel = get().defaultFeatureModel;
|
||||
@@ -2523,20 +2547,30 @@ export const useAppStore = create<AppState & AppActions>()((set, get) => ({
|
||||
|
||||
// Also update defaultFeatureModel's thinkingLevel if compatible
|
||||
if (availableLevels.includes(level)) {
|
||||
const updatedFeatureModel = { ...currentModel, thinkingLevel: level };
|
||||
set({
|
||||
defaultThinkingLevel: level,
|
||||
defaultFeatureModel: { ...currentModel, thinkingLevel: level },
|
||||
defaultFeatureModel: updatedFeatureModel,
|
||||
});
|
||||
// Sync to server - include defaultFeatureModel since thinkingLevel is embedded there too
|
||||
try {
|
||||
const httpApi = getHttpApiClient();
|
||||
await httpApi.settings.updateGlobal({
|
||||
defaultThinkingLevel: level,
|
||||
defaultFeatureModel: updatedFeatureModel,
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('Failed to sync defaultThinkingLevel:', error);
|
||||
}
|
||||
} else {
|
||||
set({ defaultThinkingLevel: level });
|
||||
}
|
||||
|
||||
// Sync to server
|
||||
try {
|
||||
const httpApi = getHttpApiClient();
|
||||
await httpApi.settings.updateGlobal({ defaultThinkingLevel: level });
|
||||
} catch (error) {
|
||||
logger.error('Failed to sync defaultThinkingLevel:', error);
|
||||
// Sync to server
|
||||
try {
|
||||
const httpApi = getHttpApiClient();
|
||||
await httpApi.settings.updateGlobal({ defaultThinkingLevel: level });
|
||||
} catch (error) {
|
||||
logger.error('Failed to sync defaultThinkingLevel:', error);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user