tasks/prd-code-organization-optimization.md
Reorganize the codebase to improve maintainability by splitting large files into focused modules and restructuring the component directory. This addresses two main issues:
sessionActions.ts (1798 lines, 37 exports) contains too many responsibilities mixing CRUD, AI generation, naming, threading, forking, and context buildingcomponents/ while 43 files are already organized into subdirectories (InputBox/, ModelSelector/, icons/, etc.)This refactor improves code discoverability, reduces merge conflicts, and makes the codebase more approachable for new contributors.
sessionActions.ts into focused modules (<300 lines each)types.ts (~150 lines)Description: As a developer, I need to map internal dependencies before splitting to avoid circular imports.
Acceptance Criteria:
pendingNameGenerations: Map<string, NodeJS.Timeout>activeNameGenerations: Map<string, AbortController>submitNewUserMessage -> generate -> scheduleGenerateNameAndThreadNamegenerate -> genMessageContextdocs/session-module-split-plan.md with findingsDescription: As a developer, I need to understand all the functions in sessionActions.ts to plan the split correctly.
Acceptance Criteria:
Description: As a developer, I want session create/read/update/delete operations in a dedicated file.
Acceptance Criteria:
stores/session/crud.tscreateEmpty, copyAndSwitchSessionswitchCurrentSession, switchToIndex, switchToNextreorderSessions, clearConversationList, clearDescription: As a developer, I want message-related operations in a dedicated file.
Acceptance Criteria:
stores/session/messages.tsinsertMessage, insertMessageAftermodifyMessage, removeMessagesubmitNewUserMessage (note: calls generate, handle import)Description: As a developer, I want thread/history operations in a dedicated file.
Acceptance Criteria:
stores/session/threads.tseditThread, removeThread, switchThreadrefreshContextAndCreateNewThread, startNewThreadremoveCurrentThread, compressAndCreateThreadmoveThreadToConversations, moveCurrentThreadToConversationsDescription: As a developer, I want message fork operations in a dedicated file.
Acceptance Criteria:
stores/session/forks.tscreateNewFork, switchForkdeleteFork, expandForkbuildCreateForkPatch, buildSwitchForkPatchbuildForkUpdatePatch, cleanupEmptyForkBranchesswitchForkInMessages, applyForkTransformMessageForkEntry, MessageLocationDescription: As a developer, I want AI generation operations in a dedicated file.
Acceptance Criteria:
stores/session/generation.tsgenerate, generateMore, generateMoreInNewForkregenerateInNewForktrackGenerateEventcreateLoadingPicturesgenMessageContext from context module (or packages/)Description: As a developer, I want session/thread naming operations in a dedicated file.
Acceptance Criteria:
stores/session/naming.ts_generateName, generateNameAndThreadName, generateThreadNamescheduleGenerateNameAndThreadName, scheduleGenerateThreadNamemodifyNameAndThreadName, modifyThreadNamestores/session/state.ts for shared MapsDescription: As a developer, I want context/prompt building operations properly placed.
Acceptance Criteria:
stores/session/context.ts (keeps it with session logic)packages/context-management/build-message-context.ts (domain logic separation)genMessageContext (200+ lines) contains AI prompt logic - consider Option BgetMessageThreadContextgetSessionWebBrowsing helperDescription: As a developer, I want export operations in a dedicated file.
Acceptance Criteria:
stores/session/export.tsexportSessionChatexportChat in sessionHelpers.ts (it's already there)Description: As a developer, I want sessionActions.ts to become a clean re-export facade.
Acceptance Criteria:
madge --circular)Description: As a developer, I want a clean index file for the session module.
Acceptance Criteria:
stores/session/index.ts_ or keep unexported)Description: As a developer, I want chat-related components grouped together.
Acceptance Criteria:
components/chat/ directorygit mv for history preservation:
Message.tsx (28KB), MessageList.tsx (20KB), MessageLoading.tsxMessageNavigation.tsx, MessageErrTips.tsxSummaryMessage.tsx, CompactionStatus.tsxmessage-parts/ contents into chat/parts/Description: As a developer, I want session-related components grouped together.
Acceptance Criteria:
components/session/ directorySessionList.tsx, SessionItem.tsxThreadHistoryDrawer.tsxDescription: As a developer, I want layout components grouped together.
Acceptance Criteria:
components/layout/ directoryHeader.tsx, Page.tsxWindowControls.tsx, Toolbar.tsxOverlay.tsx, ExitFullscreenButton.tsxDescription: As a developer, I want input-related components grouped together.
Acceptance Criteria:
components/InputBox/ already exists (7 files) - keep as-isAttachments.tsx to InputBox/ (it's input-related)TextFieldReset.tsx to common/Description: As a developer, I want commonly reused components grouped together.
Acceptance Criteria:
components/common/ directoryLink.tsx, Avatar.tsx, MiniButton.tsxAdaptiveModal.tsx, CompressionModal.tsx, PopoverConfirm.tsxLazyNumberInput.tsx, PasswordTextField.tsx, CreatableSelect.tsxToasts.tsx, ErrorBoundary.tsxLazySlider.tsx, SliderWithInput.tsx, TemperatureSlider.tsx, TopPSlider.tsxDescription: As a developer, I want to remove dead code and commented-out definitions from types.ts.
Acceptance Criteria:
types/session.tstypes/ subdirectorycreateMessage, isChatSession, isPictureSession)Updater, UpdaterFn, etc.)Description: As a developer, I want all types properly organized in the types/ directory.
Acceptance Criteria:
types/session.ts contains all session-related typestypes/settings.ts contains all settings-related typestypes/provider.ts contains all provider-related typesDescription: As a developer, I want path aliases to work correctly after reorganization.
Acceptance Criteria:
@/components/... alias works for all moved components@/stores/session/... alias works for new session modulesnpm run build)Description: As a developer, I want AGENTS.md to reflect the new code organization.
Acceptance Criteria:
stores/session/ module structure and file responsibilitiescomponents/ subdirectory structurestores/session/components/chat/Description: As a developer, I want to assess whether large components need internal restructuring.
Acceptance Criteria:
Message.tsx (28KB, ~800 lines) - document findings:
MessageActions.tsx?MessageList.tsx (20KB, ~550 lines) - document findingsMarkdown.tsx (17KB, ~450 lines) - document findings:
ActionMenu.tsx (9KB) - document findingsdocs/large-component-analysis.md with recommendationsDescription: As a developer, I want a verification plan to ensure nothing breaks.
Acceptance Criteria:
npm run test - all tests passnpm run check - no type errorsnpm run lint - no lint errorsnpm run build - build succeedsgit mv)madge --circular src/)stores/
├── session/
│ ├── index.ts # Public exports (37 functions)
│ ├── state.ts # Shared module state (Maps) - if needed
│ ├── crud.ts # Create, read, update, delete sessions (~200 lines)
│ ├── messages.ts # Message operations (~150 lines)
│ ├── threads.ts # Thread/history operations (~200 lines)
│ ├── forks.ts # Message fork operations (~400 lines)
│ ├── generation.ts # AI generation (~250 lines)
│ ├── naming.ts # Auto-naming (~150 lines)
│ ├── context.ts # Context building wrapper (or in packages/)
│ └── export.ts # Export functionality (~50 lines)
├── sessionActions.ts # Re-export facade (<50 lines, backward compat)
├── chatStore.ts # React Query operations (unchanged)
└── ...
Current State (59 flat + 43 organized):
components/
├── InputBox/ (7 files) ← Keep as-is
├── ModelSelector/ (6 files) ← Keep as-is
├── icons/ (17 files) ← Keep as-is
├── knowledge-base/ (5 files) ← Keep as-is
├── mcp/ (2 files) ← Keep as-is
├── settings/ (1 file) ← Keep as-is
├── ui/ (2 files) ← Keep as-is
├── message-parts/ (1 file) ← Consider merging into chat/
├── dev/ (2 files) ← Keep as-is
└── [59 flat files] ← Reorganize these
Post-Refactor:
components/
├── chat/ # Message display (7 files from flat)
│ ├── Message.tsx
│ ├── MessageList.tsx
│ ├── MessageLoading.tsx
│ ├── MessageNavigation.tsx
│ ├── MessageErrTips.tsx
│ ├── SummaryMessage.tsx
│ ├── CompactionStatus.tsx
│ └── parts/ # Merged from message-parts/
│ └── ToolCallPartUI.tsx
├── session/ # Session management (3 files from flat)
│ ├── SessionList.tsx
│ ├── SessionItem.tsx
│ └── ThreadHistoryDrawer.tsx
├── layout/ # Page structure (6 files from flat)
│ ├── Header.tsx
│ ├── Page.tsx
│ ├── Toolbar.tsx
│ ├── WindowControls.tsx
│ ├── Overlay.tsx
│ └── ExitFullscreenButton.tsx
├── common/ # Shared components (~20 files from flat)
│ ├── Avatar.tsx
│ ├── Link.tsx
│ ├── Toasts.tsx
│ ├── ErrorBoundary.tsx
│ ├── AdaptiveModal.tsx
│ ├── PopoverConfirm.tsx
│ ├── [sliders, inputs, etc.]
│ └── ...
├── InputBox/ # (existing, +1 Attachments.tsx)
├── ModelSelector/ # (existing, keep as-is)
├── [other existing dirs] # (keep as-is)
└── [~23 remaining flat] # Domain-specific, evaluate case by case
stores/session/: Use index.ts for clean public APIcomponents/*/: Use direct imports to avoid bundler tree-shaking issues and circular depsPhase 0: Dependency Analysis (US-000) - BLOCKER for Phase A
Phase A: Split sessionActions.ts (US-001 through US-011)
Phase B: Reorganize components (US-012 through US-016)
git mv for historyPhase C: Clean up types (US-017, US-018)
Phase D: Documentation & Analysis (US-019 through US-022)
Preferred: AST-based refactoring (safe, bulk updates)
# Using ast-grep for bulk import updates
ast-grep --pattern 'from "@/components/Message"' \
--rewrite 'from "@/components/chat/Message"' \
--lang typescript src/
# Or using LSP rename via editor/CLI for precise refactoring
Fallback: grep + manual (for edge cases)
# Find all imports of a component
grep -r "from.*['\"]@/components/Message['\"]" src/
# Install madge for dependency analysis
npm install -D madge
# Check for circular dependencies
npx madge --circular src/renderer/stores/
# Visualize dependency graph (optional)
npx madge --image graph.svg src/renderer/stores/sessionActions.ts
npm run check)npm run test)madge --circular returns emptynpm run test greennpm run build completes without errors| Question | Decision | Rationale |
|---|---|---|
| Barrel files in component dirs? | No | Avoid bundler tree-shaking issues, simpler imports |
| Component size limits? | Advisory 500 lines | Not enforced, but flagged for review |
components/legacy/ for misc? | No | Creates dumping ground; keep truly shared components flat |
| Lint rules for structure? | Yes, after stabilization | Add eslint-plugin-import rules in follow-up PR |
Where does genMessageContext go? | Evaluate in US-008 | Either stores/session/context.ts or packages/context-management/ |
| Shared naming state handling? | Decide in US-000 | Either stores/session/state.ts or keep in naming.ts |
message-parts/ be merged into chat/parts/ or kept separate?