feat: implement API-first settings management and description history tracking

- Migrated settings persistence from localStorage to an API-first approach, ensuring consistency between Electron and web modes.
- Introduced `useSettingsSync` hook for automatic synchronization of settings to the server with debouncing.
- Enhanced feature update logic to track description changes with a history, allowing for better management of feature descriptions.
- Updated various components and services to utilize the new settings structure and description history functionality.
- Removed persist middleware from Zustand store, streamlining state management and improving performance.
This commit is contained in:
webdevcody
2026-01-07 10:05:54 -05:00
parent 1316ead8c8
commit 11accac5ae
22 changed files with 3177 additions and 2262 deletions

View File

@@ -459,7 +459,9 @@ export interface FeaturesAPI {
update: (
projectPath: string,
featureId: string,
updates: Partial<Feature>
updates: Partial<Feature>,
descriptionHistorySource?: 'enhance' | 'edit',
enhancementMode?: 'improve' | 'technical' | 'simplify' | 'acceptance'
) => Promise<{ success: boolean; feature?: Feature; error?: string }>;
delete: (projectPath: string, featureId: string) => Promise<{ success: boolean; error?: string }>;
getAgentOutput: (

View File

@@ -1183,8 +1183,20 @@ export class HttpApiClient implements ElectronAPI {
this.post('/api/features/get', { projectPath, featureId }),
create: (projectPath: string, feature: Feature) =>
this.post('/api/features/create', { projectPath, feature }),
update: (projectPath: string, featureId: string, updates: Partial<Feature>) =>
this.post('/api/features/update', { projectPath, featureId, updates }),
update: (
projectPath: string,
featureId: string,
updates: Partial<Feature>,
descriptionHistorySource?: 'enhance' | 'edit',
enhancementMode?: 'improve' | 'technical' | 'simplify' | 'acceptance'
) =>
this.post('/api/features/update', {
projectPath,
featureId,
updates,
descriptionHistorySource,
enhancementMode,
}),
delete: (projectPath: string, featureId: string) =>
this.post('/api/features/delete', { projectPath, featureId }),
getAgentOutput: (projectPath: string, featureId: string) =>

View File

@@ -6,12 +6,10 @@
import { createLogger } from '@automaker/utils/logger';
import { getHttpApiClient } from './http-api-client';
import { getElectronAPI } from './electron';
import { getItem, setItem } from './storage';
import { useAppStore } from '@/store/app-store';
const logger = createLogger('WorkspaceConfig');
const LAST_PROJECT_DIR_KEY = 'automaker:lastProjectDir';
/**
* Browser-compatible path join utility
* Works in both Node.js and browser environments
@@ -67,10 +65,10 @@ export async function getDefaultWorkspaceDirectory(): Promise<string | null> {
}
// If ALLOWED_ROOT_DIRECTORY is not set, use priority:
// 1. Last used directory
// 1. Last used directory (from store, synced via API)
// 2. Documents/Automaker
// 3. DATA_DIR as fallback
const lastUsedDir = getItem(LAST_PROJECT_DIR_KEY);
const lastUsedDir = useAppStore.getState().lastProjectDir;
if (lastUsedDir) {
return lastUsedDir;
@@ -89,7 +87,7 @@ export async function getDefaultWorkspaceDirectory(): Promise<string | null> {
}
// If API call failed, still try last used dir and Documents
const lastUsedDir = getItem(LAST_PROJECT_DIR_KEY);
const lastUsedDir = useAppStore.getState().lastProjectDir;
if (lastUsedDir) {
return lastUsedDir;
@@ -101,7 +99,7 @@ export async function getDefaultWorkspaceDirectory(): Promise<string | null> {
logger.error('Failed to get default workspace directory:', error);
// On error, try last used dir and Documents
const lastUsedDir = getItem(LAST_PROJECT_DIR_KEY);
const lastUsedDir = useAppStore.getState().lastProjectDir;
if (lastUsedDir) {
return lastUsedDir;
@@ -113,9 +111,9 @@ export async function getDefaultWorkspaceDirectory(): Promise<string | null> {
}
/**
* Saves the last used project directory to localStorage
* Saves the last used project directory to the store (synced via API)
* @param path - The directory path to save
*/
export function saveLastProjectDirectory(path: string): void {
setItem(LAST_PROJECT_DIR_KEY, path);
useAppStore.getState().setLastProjectDir(path);
}