Merge main into feat/extend-models-support

Resolved conflicts:
- feature_list.json: Merged all features from both branches
- feature-loader.js: Included both model/thinkingLevel and error fields
- board-view.tsx: Merged model/thinkingLevel and error fields, kept currentProject check
- settings-view.tsx: Merged CLI status checks with navigation/scroll code
- app-store.ts: Included both model/thinkingLevel and error fields in Feature interface

Fixed linting errors in settings-view.tsx
This commit is contained in:
Kacper
2025-12-10 10:25:13 +01:00
19 changed files with 856 additions and 395 deletions

View File

@@ -1,6 +1,6 @@
import { create } from "zustand";
import { persist } from "zustand/middleware";
import type { Project } from "@/lib/electron";
import type { Project, TrashedProject } from "@/lib/electron";
export type ViewMode =
| "welcome"
@@ -107,12 +107,14 @@ export interface Feature {
summary?: string; // Summary of what was done/modified by the agent
model?: AgentModel; // Model to use for this feature (defaults to opus)
thinkingLevel?: ThinkingLevel; // Thinking level for extended thinking (defaults to none)
error?: string; // Error message if the agent errored during processing
}
export interface AppState {
// Project state
projects: Project[];
currentProject: Project | null;
trashedProjects: TrashedProject[];
// View state
currentView: ViewMode;
@@ -175,6 +177,10 @@ export interface AppActions {
setProjects: (projects: Project[]) => void;
addProject: (project: Project) => void;
removeProject: (projectId: string) => void;
moveProjectToTrash: (projectId: string) => void;
restoreTrashedProject: (projectId: string) => void;
deleteTrashedProject: (projectId: string) => void;
emptyTrash: () => void;
setCurrentProject: (project: Project | null) => void;
reorderProjects: (oldIndex: number, newIndex: number) => void;
@@ -237,6 +243,7 @@ export interface AppActions {
const initialState: AppState = {
projects: [],
currentProject: null,
trashedProjects: [],
currentView: "welcome",
sidebarOpen: true,
theme: "dark",
@@ -291,6 +298,82 @@ export const useAppStore = create<AppState & AppActions>()(
set({ projects: get().projects.filter((p) => p.id !== projectId) });
},
moveProjectToTrash: (projectId) => {
const project = get().projects.find((p) => p.id === projectId);
if (!project) return;
const remainingProjects = get().projects.filter(
(p) => p.id !== projectId
);
const existingTrash = get().trashedProjects.filter(
(p) => p.id !== projectId
);
const trashedProject: TrashedProject = {
...project,
trashedAt: new Date().toISOString(),
deletedFromDisk: false,
};
const isCurrent = get().currentProject?.id === projectId;
set({
projects: remainingProjects,
trashedProjects: [trashedProject, ...existingTrash],
currentProject: isCurrent ? null : get().currentProject,
currentView: isCurrent ? "welcome" : get().currentView,
});
},
restoreTrashedProject: (projectId) => {
const trashed = get().trashedProjects.find((p) => p.id === projectId);
if (!trashed) return;
const remainingTrash = get().trashedProjects.filter(
(p) => p.id !== projectId
);
const existingProjects = get().projects;
const samePathProject = existingProjects.find(
(p) => p.path === trashed.path
);
const projectsWithoutId = existingProjects.filter(
(p) => p.id !== projectId
);
// If a project with the same path already exists, keep it and just remove from trash
if (samePathProject) {
set({
trashedProjects: remainingTrash,
currentProject: samePathProject,
currentView: "board",
});
return;
}
const restoredProject: Project = {
id: trashed.id,
name: trashed.name,
path: trashed.path,
lastOpened: new Date().toISOString(),
};
set({
trashedProjects: remainingTrash,
projects: [...projectsWithoutId, restoredProject],
currentProject: restoredProject,
currentView: "board",
});
},
deleteTrashedProject: (projectId) => {
set({
trashedProjects: get().trashedProjects.filter(
(p) => p.id !== projectId
),
});
},
emptyTrash: () => set({ trashedProjects: [] }),
reorderProjects: (oldIndex, newIndex) => {
const projects = [...get().projects];
const [movedProject] = projects.splice(oldIndex, 1);
@@ -517,6 +600,7 @@ export const useAppStore = create<AppState & AppActions>()(
partialize: (state) => ({
projects: state.projects,
currentProject: state.currentProject,
trashedProjects: state.trashedProjects,
currentView: state.currentView,
theme: state.theme,
sidebarOpen: state.sidebarOpen,