feat: Implement worktree initialization script functionality

This commit introduces a new feature for managing worktree initialization scripts, allowing users to configure and execute scripts upon worktree creation. Key changes include:

1. **New API Endpoints**: Added endpoints for getting, setting, and deleting init scripts.
2. **Worktree Routes**: Updated worktree routes to include init script handling.
3. **Init Script Service**: Created a service to execute the init scripts asynchronously, with support for cross-platform compatibility.
4. **UI Components**: Added UI components for displaying and editing init scripts, including a dedicated section in the settings view.
5. **Event Handling**: Implemented event handling for init script execution status, providing real-time feedback in the UI.

This enhancement improves the user experience by allowing automated setup processes for new worktrees, streamlining project workflows.
This commit is contained in:
Kacper
2026-01-10 22:19:34 +01:00
parent 427832e72e
commit 05d96a7d6e
23 changed files with 1481 additions and 46 deletions

View File

@@ -459,6 +459,14 @@ export interface PersistedTerminalSettings {
maxSessions: number;
}
/** State for worktree init script execution */
export interface InitScriptState {
status: 'idle' | 'running' | 'success' | 'failed';
branch: string;
output: string[];
error?: string;
}
export interface AppState {
// Project state
projects: Project[];
@@ -664,6 +672,9 @@ export interface AppState {
lastProjectDir: string;
/** Recently accessed folders for quick access */
recentFolders: string[];
// Init Script State (per-project, keyed by project path)
initScriptState: Record<string, InitScriptState>;
}
// Claude Usage interface matching the server response
@@ -1095,6 +1106,12 @@ export interface AppActions {
}>
) => void;
// Init Script State actions
setInitScriptState: (projectPath: string, state: Partial<InitScriptState>) => void;
appendInitScriptOutput: (projectPath: string, content: string) => void;
clearInitScriptState: (projectPath: string) => void;
getInitScriptState: (projectPath: string) => InitScriptState | null;
// Reset
reset: () => void;
}
@@ -1195,6 +1212,7 @@ const initialState: AppState = {
worktreePanelCollapsed: false,
lastProjectDir: '',
recentFolders: [],
initScriptState: {},
};
export const useAppStore = create<AppState & AppActions>()((set, get) => ({
@@ -3119,6 +3137,44 @@ export const useAppStore = create<AppState & AppActions>()((set, get) => ({
set({ recentFolders: updated });
},
// Init Script State actions
setInitScriptState: (projectPath, state) => {
const current = get().initScriptState[projectPath] || {
status: 'idle',
branch: '',
output: [],
};
set({
initScriptState: {
...get().initScriptState,
[projectPath]: { ...current, ...state },
},
});
},
appendInitScriptOutput: (projectPath, content) => {
const current = get().initScriptState[projectPath];
if (!current) return;
set({
initScriptState: {
...get().initScriptState,
[projectPath]: {
...current,
output: [...current.output, content],
},
},
});
},
clearInitScriptState: (projectPath) => {
const { [projectPath]: _, ...rest } = get().initScriptState;
set({ initScriptState: rest });
},
getInitScriptState: (projectPath) => {
return get().initScriptState[projectPath] || null;
},
// Reset
reset: () => set(initialState),
}));