mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-01 08:13:37 +00:00
- STACK.md - Technologies and dependencies - ARCHITECTURE.md - System design and patterns - STRUCTURE.md - Directory layout - CONVENTIONS.md - Code style and patterns - TESTING.md - Test structure - INTEGRATIONS.md - External services - CONCERNS.md - Technical debt and issues
235 lines
8.8 KiB
Markdown
235 lines
8.8 KiB
Markdown
# Architecture
|
|
|
|
**Analysis Date:** 2026-01-27
|
|
|
|
## Pattern Overview
|
|
|
|
**Overall:** Monorepo with layered client-server architecture (Electron-first) and pluggable provider abstraction for AI models.
|
|
|
|
**Key Characteristics:**
|
|
|
|
- Event-driven communication via WebSocket between frontend and backend
|
|
- Multi-provider AI model abstraction layer (Claude, Cursor, Codex, Gemini, OpenCode, Copilot)
|
|
- Feature-centric workflow stored in `.automaker/` directories
|
|
- Isolated git worktree execution for each feature
|
|
- State management through Zustand stores with API persistence
|
|
|
|
## Layers
|
|
|
|
**Presentation Layer (UI):**
|
|
|
|
- Purpose: React 19 Electron/web frontend with TanStack Router file-based routing
|
|
- Location: `apps/ui/src/`
|
|
- Contains: Route components, view pages, custom React hooks, Zustand stores, API client
|
|
- Depends on: @automaker/types, @automaker/utils, HTTP API backend
|
|
- Used by: Electron main process (desktop), web browser (web mode)
|
|
|
|
**API Layer (Server):**
|
|
|
|
- Purpose: Express 5 backend exposing RESTful and WebSocket endpoints
|
|
- Location: `apps/server/src/`
|
|
- Contains: Route handlers, business logic services, middleware, provider adapters
|
|
- Depends on: @automaker/types, @automaker/utils, @automaker/platform, Claude Agent SDK
|
|
- Used by: UI frontend via HTTP/WebSocket
|
|
|
|
**Service Layer (Server):**
|
|
|
|
- Purpose: Business logic and domain operations
|
|
- Location: `apps/server/src/services/`
|
|
- Contains: AgentService, FeatureLoader, AutoModeService, SettingsService, DevServerService, etc.
|
|
- Depends on: Providers, secure filesystem, feature storage
|
|
- Used by: Route handlers
|
|
|
|
**Provider Abstraction (Server):**
|
|
|
|
- Purpose: Unified interface for different AI model providers
|
|
- Location: `apps/server/src/providers/`
|
|
- Contains: ProviderFactory, specific provider implementations (ClaudeProvider, CursorProvider, CodexProvider, GeminiProvider, OpencodeProvider, CopilotProvider)
|
|
- Depends on: @automaker/types, provider SDKs
|
|
- Used by: AgentService
|
|
|
|
**Shared Library Layer:**
|
|
|
|
- Purpose: Type definitions and utilities shared across apps
|
|
- Location: `libs/`
|
|
- Contains: @automaker/types, @automaker/utils, @automaker/platform, @automaker/prompts, @automaker/model-resolver, @automaker/dependency-resolver, @automaker/git-utils, @automaker/spec-parser
|
|
- Depends on: None (types has no external deps)
|
|
- Used by: All apps and services
|
|
|
|
## Data Flow
|
|
|
|
**Feature Execution Flow:**
|
|
|
|
1. User creates/updates feature via UI (`apps/ui/src/`)
|
|
2. UI sends HTTP request to backend (`POST /api/features`)
|
|
3. Server route handler invokes FeatureLoader to persist to `.automaker/features/{featureId}/`
|
|
4. When executing, AgentService loads feature, creates isolated git worktree via @automaker/git-utils
|
|
5. AgentService invokes ProviderFactory to get appropriate AI provider (Claude, Cursor, etc.)
|
|
6. Provider executes with context from CLAUDE.md files via @automaker/utils loadContextFiles()
|
|
7. Server emits events via EventEmitter throughout execution
|
|
8. Events stream to frontend via WebSocket
|
|
9. UI updates stores and renders real-time progress
|
|
10. Feature results persist back to `.automaker/features/` with generated agent-output.md
|
|
|
|
**State Management:**
|
|
|
|
**Frontend State (Zustand):**
|
|
|
|
- `app-store.ts`: Global app state (projects, features, settings, boards, themes)
|
|
- `setup-store.ts`: First-time setup wizard flow
|
|
- `ideation-store.ts`: Ideation feature state
|
|
- `test-runners-store.ts`: Test runner configurations
|
|
- Settings now persist via API (`/api/settings`) rather than localStorage (see use-settings-sync.ts)
|
|
|
|
**Backend State (Services):**
|
|
|
|
- SettingsService: Global and project-specific settings (in-memory with file persistence)
|
|
- AgentService: Active agent sessions and conversation history
|
|
- FeatureLoader: Feature data model operations
|
|
- DevServerService: Development server logs
|
|
- EventHistoryService: Persists event logs for replay
|
|
|
|
**Real-Time Updates (WebSocket):**
|
|
|
|
- Server EventEmitter emits TypedEvent (type + payload)
|
|
- WebSocket handler subscribes to events and broadcasts to all clients
|
|
- Frontend listens on multiple WebSocket subscriptions and updates stores
|
|
|
|
## Key Abstractions
|
|
|
|
**Feature:**
|
|
|
|
- Purpose: Represents a development task/story with rich metadata
|
|
- Location: @automaker/types → `libs/types/src/feature.ts`
|
|
- Fields: id, title, description, status, images, tasks, priority, etc.
|
|
- Stored: `.automaker/features/{featureId}/feature.json`
|
|
|
|
**Provider:**
|
|
|
|
- Purpose: Abstracts different AI model implementations
|
|
- Location: `apps/server/src/providers/{provider}-provider.ts`
|
|
- Interface: Common execute() method with consistent message format
|
|
- Implementations: Claude, Cursor, Codex, Gemini, OpenCode, Copilot
|
|
- Factory: ProviderFactory picks correct provider based on model ID
|
|
|
|
**Event:**
|
|
|
|
- Purpose: Real-time updates streamed to frontend
|
|
- Location: @automaker/types → `libs/types/src/event.ts`
|
|
- Format: { type: EventType, payload: unknown }
|
|
- Examples: agent-started, agent-step, agent-complete, feature-updated, etc.
|
|
|
|
**AgentSession:**
|
|
|
|
- Purpose: Represents a conversation between user and AI agent
|
|
- Location: @automaker/types → `libs/types/src/session.ts`
|
|
- Contains: Messages (user + assistant), metadata, creation timestamp
|
|
- Stored: `{DATA_DIR}/agent-sessions/{sessionId}.json`
|
|
|
|
**Settings:**
|
|
|
|
- Purpose: Configuration for global and per-project behavior
|
|
- Location: @automaker/types → `libs/types/src/settings.ts`
|
|
- Stored: Global in `{DATA_DIR}/settings.json`, per-project in `.automaker/settings.json`
|
|
- Service: SettingsService in `apps/server/src/services/settings-service.ts`
|
|
|
|
## Entry Points
|
|
|
|
**Server:**
|
|
|
|
- Location: `apps/server/src/index.ts`
|
|
- Triggers: `npm run dev:server` or Docker startup
|
|
- Responsibilities:
|
|
- Initialize Express app with middleware
|
|
- Create shared EventEmitter for WebSocket streaming
|
|
- Bootstrap services (SettingsService, AgentService, FeatureLoader, etc.)
|
|
- Mount API routes at `/api/*`
|
|
- Create WebSocket servers for agent streaming and terminal sessions
|
|
- Load and apply user settings (log level, request logging, etc.)
|
|
|
|
**UI (Web):**
|
|
|
|
- Location: `apps/ui/src/main.ts` (Vite entry), `apps/ui/src/app.tsx` (React component)
|
|
- Triggers: `npm run dev:web` or `npm run build`
|
|
- Responsibilities:
|
|
- Initialize Zustand stores from API settings
|
|
- Setup React Router with TanStack Router
|
|
- Render root layout with sidebar and main content area
|
|
- Handle authentication via verifySession()
|
|
|
|
**UI (Electron):**
|
|
|
|
- Location: `apps/ui/src/main.ts` (Vite entry), `apps/ui/electron/main-process.ts` (Electron main process)
|
|
- Triggers: `npm run dev:electron`
|
|
- Responsibilities:
|
|
- Launch local server via node-pty
|
|
- Create native Electron window
|
|
- Bridge IPC between renderer and main process
|
|
- Provide file system access via preload.ts APIs
|
|
|
|
## Error Handling
|
|
|
|
**Strategy:** Layered error classification and user-friendly messaging
|
|
|
|
**Patterns:**
|
|
|
|
**Backend Error Handling:**
|
|
|
|
- Errors classified via `classifyError()` from @automaker/utils
|
|
- Classification: ParseError, NetworkError, AuthenticationError, RateLimitError, etc.
|
|
- Response format: `{ success: false, error: { type, message, code }, details? }`
|
|
- Example: `apps/server/src/lib/error-handler.ts`
|
|
|
|
**Frontend Error Handling:**
|
|
|
|
- HTTP errors caught by api-fetch.ts with retry logic
|
|
- WebSocket disconnects trigger reconnection with exponential backoff
|
|
- Errors shown in toast notifications via `sonner` library
|
|
- Validation errors caught and displayed inline in forms
|
|
|
|
**Agent Execution Errors:**
|
|
|
|
- AgentService wraps provider calls in try-catch
|
|
- Aborts handled specially via `isAbortError()` check
|
|
- Rate limit errors trigger cooldown before retry
|
|
- Model-specific errors mapped to user guidance
|
|
|
|
## Cross-Cutting Concerns
|
|
|
|
**Logging:**
|
|
|
|
- Framework: @automaker/utils createLogger()
|
|
- Pattern: `const logger = createLogger('ModuleName')`
|
|
- Levels: ERROR, WARN, INFO, DEBUG (configurable via settings)
|
|
- Output: stdout (dev), files (production)
|
|
|
|
**Validation:**
|
|
|
|
- File path validation: @automaker/platform initAllowedPaths() enforces restrictions
|
|
- Model ID validation: @automaker/model-resolver resolveModelString()
|
|
- JSON schema validation: Manual checks in route handlers (no JSON schema lib)
|
|
- Authentication: Session token validation via validateWsConnectionToken()
|
|
|
|
**Authentication:**
|
|
|
|
- Frontend: Session token stored in httpOnly cookie
|
|
- Backend: authMiddleware checks token on protected routes
|
|
- WebSocket: validateWsConnectionToken() for upgrade requests
|
|
- Providers: API keys stored encrypted in `{DATA_DIR}/credentials.json`
|
|
|
|
**Internationalization:**
|
|
|
|
- Not detected - strings are English-only
|
|
|
|
**Performance:**
|
|
|
|
- Code splitting: File-based routing via TanStack Router
|
|
- Lazy loading: React.lazy() in route components
|
|
- Caching: React Query for HTTP requests (query-keys.ts defines cache strategy)
|
|
- Image optimization: Automatic base64 encoding for agent context
|
|
- State hydration: Settings loaded once at startup, synced via API
|
|
|
|
---
|
|
|
|
_Architecture analysis: 2026-01-27_
|