From bca27d99885060832b490a80d94cc7018571eaa9 Mon Sep 17 00:00:00 2001 From: Ammar Date: Sat, 2 May 2026 14:15:37 -0500 Subject: [PATCH 1/8] Replace sections with sub-projects --- src/browser/App.tsx | 6 +- .../ProjectCreateModal/ProjectCreateModal.tsx | 14 +- .../ProjectPage/ProjectPage.stories.tsx | 66 +- .../components/ProjectPage/ProjectPage.tsx | 10 +- .../ProjectSidebar/ProjectSidebar.test.tsx | 158 +--- .../ProjectSidebar/ProjectSidebar.tsx | 134 ++- .../SectionHeader/SectionHeader.test.tsx | 230 ------ .../SectionHeader/SectionHeader.tsx | 20 +- src/browser/contexts/ProjectContext.test.tsx | 9 +- src/browser/contexts/ProjectContext.tsx | 111 +-- src/browser/contexts/RouterContext.tsx | 16 +- src/browser/contexts/ThinkingContext.test.tsx | 4 +- src/browser/contexts/WorkspaceContext.tsx | 135 +-- .../features/ChatInput/CreationControls.tsx | 144 +--- src/browser/features/ChatInput/index.tsx | 94 +-- src/browser/features/ChatInput/types.ts | 4 +- .../ChatInput/useCreationWorkspace.ts | 10 +- .../stories/App.phoneViewports.stories.tsx | 26 +- src/browser/stories/helpers/drafts.ts | 11 +- src/browser/utils/commands/sources.ts | 15 +- .../utils/ui/workspaceFiltering.test.ts | 144 +--- src/browser/utils/ui/workspaceFiltering.ts | 13 +- src/browser/utils/workspace.ts | 2 +- src/common/constants/storage.ts | 2 +- src/common/orpc/schemas.ts | 2 +- src/common/orpc/schemas/api.ts | 45 +- src/common/orpc/schemas/project.ts | 6 +- src/common/orpc/schemas/workspace.ts | 5 +- src/common/schemas/project.ts | 35 +- src/common/types/deepLink.ts | 1 - src/common/types/project.ts | 8 +- src/common/utils/deepLink.test.ts | 3 +- src/common/utils/deepLink.ts | 3 - src/common/utils/sections.ts | 39 - src/common/utils/subProjects.test.ts | 75 ++ src/common/utils/subProjects.ts | 98 +++ src/node/config.ts | 35 +- src/node/orpc/router.ts | 44 +- src/node/runtime/runtimeHelpers.test.ts | 18 + src/node/runtime/runtimeHelpers.ts | 31 +- src/node/services/projectService.ts | 337 ++++---- src/node/services/systemMessage.test.ts | 25 +- src/node/services/systemMessage.ts | 55 +- src/node/services/workspaceService.ts | 74 +- tests/ui/chat/sections.test.ts | 774 ------------------ 45 files changed, 833 insertions(+), 2258 deletions(-) delete mode 100644 src/browser/components/SectionHeader/SectionHeader.test.tsx delete mode 100644 src/common/utils/sections.ts create mode 100644 src/common/utils/subProjects.test.ts create mode 100644 src/common/utils/subProjects.ts delete mode 100644 tests/ui/chat/sections.test.ts diff --git a/src/browser/App.tsx b/src/browser/App.tsx index 935d2b74ec..eda286922d 100644 --- a/src/browser/App.tsx +++ b/src/browser/App.tsx @@ -141,7 +141,7 @@ function AppInner() { selectedWorkspace, setSelectedWorkspace, pendingNewWorkspaceProject, - pendingNewWorkspaceSectionId, + pendingNewWorkspaceSubProjectPath, pendingNewWorkspaceDraftId, beginWorkspaceCreation, } = useWorkspaceContext(); @@ -169,6 +169,7 @@ function AppInner() { refreshProjects, removeProject, openProjectCreateModal, + projectCreateInitialPath, isProjectCreateModalOpen, closeProjectCreateModal, addProject, @@ -1154,7 +1155,7 @@ function AppInner() { projectName={projectName} leftSidebarCollapsed={sidebarCollapsed} onToggleLeftSidebarCollapsed={handleToggleSidebar} - pendingSectionId={pendingNewWorkspaceSectionId} + pendingSubProjectPath={pendingNewWorkspaceSubProjectPath} pendingDraftId={pendingNewWorkspaceDraftId} onWorkspaceCreated={(metadata, options) => { // IMPORTANT: Add workspace to store FIRST (synchronous) to ensure @@ -1217,6 +1218,7 @@ function AppInner() { ({ workspaceId: selectedWorkspace?.workspaceId })} /> { diff --git a/src/browser/components/ProjectCreateModal/ProjectCreateModal.tsx b/src/browser/components/ProjectCreateModal/ProjectCreateModal.tsx index 123b1a0d8a..e8b843e921 100644 --- a/src/browser/components/ProjectCreateModal/ProjectCreateModal.tsx +++ b/src/browser/components/ProjectCreateModal/ProjectCreateModal.tsx @@ -68,6 +68,7 @@ function useDirectoryPicker(params: { } interface ProjectCreateModalProps { + initialPath?: string; isOpen: boolean; onClose: () => void; onSuccess: (normalizedPath: string, projectConfig: ProjectConfig) => void; @@ -75,6 +76,8 @@ interface ProjectCreateModalProps { interface ProjectCreateFormProps { onSuccess: (normalizedPath: string, projectConfig: ProjectConfig) => void; + /** Optional initial path for parent-scoped sub-project creation. */ + initialPath?: string; /** * Optional close handler for modal-style usage. * When provided, the form will call it on cancel and after a successful add. @@ -102,6 +105,7 @@ export interface ProjectCreateFormHandle { export const ProjectCreateForm = React.forwardRef( function ProjectCreateForm( { + initialPath, onSuccess, onClose, showCancelButton = false, @@ -116,10 +120,14 @@ export const ProjectCreateForm = React.forwardRef { + setPath(initialPath ?? ""); + }, [initialPath]); + const setCreating = useCallback( (next: boolean) => { setIsCreating(next); @@ -776,6 +784,7 @@ export interface ProjectAddFormHandle { } interface ProjectAddFormProps { + initialPath?: string; onSuccess: (normalizedPath: string, projectConfig: ProjectConfig) => void; onClose?: () => void; isOpen: boolean; @@ -912,6 +921,7 @@ export const ProjectAddForm = React.forwardRef = ({ + initialPath, isOpen, onClose, onSuccess, @@ -984,6 +995,7 @@ export const ProjectCreateModal: React.FC = ({