# AutoMaker Shared Packages - LLM Guide This guide helps AI assistants understand how to use AutoMaker's shared packages effectively. ## Package Overview AutoMaker uses a monorepo structure with shared packages in `libs/`: ``` libs/ ├── types/ # Type definitions (no dependencies) ├── utils/ # Utility functions ├── platform/ # Platform utilities ├── model-resolver/ # Claude model resolution ├── dependency-resolver/# Feature dependency resolution └── git-utils/ # Git operations ``` ## When to Use Each Package ### @automaker/types **Use when:** You need type definitions for any AutoMaker concept. **Import for:** - `Feature` - Feature interface with all properties - `ExecuteOptions` - Claude agent execution options - `ConversationMessage` - Chat message format - `ErrorType`, `ErrorInfo` - Error handling types - `CLAUDE_MODEL_MAP` - Model alias to ID mapping - `DEFAULT_MODELS` - Default model configurations **Example:** ```typescript import type { Feature, ExecuteOptions } from '@automaker/types'; ``` **Never import from:** `services/feature-loader`, `providers/types` ### @automaker/utils **Use when:** You need common utilities like logging, error handling, or image processing. **Import for:** - `createLogger(context)` - Structured logging - `isAbortError(error)` - Error type checking - `classifyError(error)` - Error classification - `buildPromptWithImages()` - Prompt building with images - `readImageAsBase64()` - Image handling - `extractTextFromContent()` - Message parsing **Example:** ```typescript import { createLogger, classifyError } from '@automaker/utils'; ``` **Never import from:** `lib/logger`, `lib/error-handler`, `lib/prompt-builder`, `lib/image-handler` ### @automaker/platform **Use when:** You need to work with AutoMaker's directory structure or spawn processes. **Import for:** - `getAutomakerDir(projectPath)` - Get .automaker directory - `getFeaturesDir(projectPath)` - Get features directory - `getFeatureDir(projectPath, featureId)` - Get specific feature directory - `ensureAutomakerDir(projectPath)` - Create .automaker if needed - `spawnJSONLProcess()` - Spawn process with JSONL output - `initAllowedPaths()` - Security path validation **Example:** ```typescript import { getFeatureDir, ensureAutomakerDir } from '@automaker/platform'; ``` **Never import from:** `lib/automaker-paths`, `lib/subprocess-manager`, `lib/security` ### @automaker/model-resolver **Use when:** You need to convert model aliases to full model IDs. **Import for:** - `resolveModelString(modelOrAlias)` - Convert alias to full ID - `DEFAULT_MODELS` - Access default models **Example:** ```typescript import { resolveModelString, DEFAULT_MODELS } from '@automaker/model-resolver'; // Convert user input to model ID const modelId = resolveModelString('sonnet'); // → 'claude-sonnet-4-20250514' ``` **Never import from:** `lib/model-resolver` **Model aliases:** - `haiku` → `claude-haiku-4-5` (fast, simple tasks) - `sonnet` → `claude-sonnet-4-20250514` (balanced, recommended) - `opus` → `claude-opus-4-5-20251101` (maximum capability) ### @automaker/dependency-resolver **Use when:** You need to order features by dependencies or check if dependencies are satisfied. **Import for:** - `resolveDependencies(features)` - Topological sort with priority - `areDependenciesSatisfied(feature, allFeatures)` - Check if ready to execute - `getBlockingDependencies(feature, allFeatures)` - Get incomplete dependencies **Example:** ```typescript import { resolveDependencies, areDependenciesSatisfied } from '@automaker/dependency-resolver'; const { orderedFeatures, hasCycle } = resolveDependencies(features); if (!hasCycle) { for (const feature of orderedFeatures) { if (areDependenciesSatisfied(feature, features)) { await execute(feature); } } } ``` **Never import from:** `lib/dependency-resolver` **Used in:** - Auto-mode feature execution (server) - Board view feature ordering (UI) ### @automaker/git-utils **Use when:** You need git operations, status parsing, or diff generation. **Import for:** - `isGitRepo(path)` - Check if path is a git repository - `parseGitStatus(output)` - Parse `git status --porcelain` output - `getGitRepositoryDiffs(path)` - Get complete diffs (tracked + untracked) - `generateSyntheticDiffForNewFile()` - Create diff for untracked file - `listAllFilesInDirectory()` - List files excluding build artifacts **Example:** ```typescript import { isGitRepo, getGitRepositoryDiffs } from '@automaker/git-utils'; if (await isGitRepo(projectPath)) { const { diff, files, hasChanges } = await getGitRepositoryDiffs(projectPath); console.log(`Found ${files.length} changed files`); } ``` **Never import from:** `routes/common` **Handles:** - Binary file detection - Large file handling (>1MB) - Untracked file diffs - Non-git directory support ## Common Patterns ### Creating a Feature Executor ```typescript import type { Feature, ExecuteOptions } from '@automaker/types'; import { createLogger, classifyError } from '@automaker/utils'; import { resolveModelString, DEFAULT_MODELS } from '@automaker/model-resolver'; import { areDependenciesSatisfied } from '@automaker/dependency-resolver'; import { getFeatureDir } from '@automaker/platform'; const logger = createLogger('FeatureExecutor'); async function executeFeature( feature: Feature, allFeatures: Feature[], projectPath: string ) { // Check dependencies if (!areDependenciesSatisfied(feature, allFeatures)) { logger.warn(`Dependencies not satisfied for ${feature.id}`); return; } // Resolve model const model = resolveModelString(feature.model, DEFAULT_MODELS.autoMode); // Get feature directory const featureDir = getFeatureDir(projectPath, feature.id); try { // Execute with Claude const options: ExecuteOptions = { model, temperature: 0.7 }; await runAgent(featureDir, options); logger.info(`Feature ${feature.id} completed`); } catch (error) { const errorInfo = classifyError(error); logger.error(`Feature ${feature.id} failed:`, errorInfo.message); } } ``` ### Analyzing Git Changes ```typescript import { getGitRepositoryDiffs, parseGitStatus } from '@automaker/git-utils'; import { createLogger } from '@automaker/utils'; const logger = createLogger('GitAnalyzer'); async function analyzeChanges(projectPath: string) { const { diff, files, hasChanges } = await getGitRepositoryDiffs(projectPath); if (!hasChanges) { logger.info('No changes detected'); return; } // Group by status const modified = files.filter(f => f.status === 'M'); const added = files.filter(f => f.status === 'A'); const deleted = files.filter(f => f.status === 'D'); const untracked = files.filter(f => f.status === '?'); logger.info(`Changes: ${modified.length}M ${added.length}A ${deleted.length}D ${untracked.length}U`); return diff; } ``` ### Ordering Features for Execution ```typescript import type { Feature } from '@automaker/types'; import { resolveDependencies, getBlockingDependencies } from '@automaker/dependency-resolver'; import { createLogger } from '@automaker/utils'; const logger = createLogger('FeatureOrdering'); function orderAndFilterFeatures(features: Feature[]): Feature[] { const { orderedFeatures, hasCycle, cyclicFeatures } = resolveDependencies(features); if (hasCycle) { logger.error(`Circular dependency detected: ${cyclicFeatures.join(' → ')}`); throw new Error('Cannot execute features with circular dependencies'); } // Filter to only ready features const readyFeatures = orderedFeatures.filter(feature => { const blocking = getBlockingDependencies(feature, features); if (blocking.length > 0) { logger.debug(`${feature.id} blocked by: ${blocking.join(', ')}`); return false; } return true; }); logger.info(`${readyFeatures.length} of ${features.length} features ready`); return readyFeatures; } ``` ## Import Rules for LLMs ### ✅ DO ```typescript // Import types from @automaker/types import type { Feature, ExecuteOptions } from '@automaker/types'; // Import constants from @automaker/types import { CLAUDE_MODEL_MAP, DEFAULT_MODELS } from '@automaker/types'; // Import utilities from @automaker/utils import { createLogger, classifyError } from '@automaker/utils'; // Import platform utils from @automaker/platform import { getFeatureDir, ensureAutomakerDir } from '@automaker/platform'; // Import model resolution from @automaker/model-resolver import { resolveModelString } from '@automaker/model-resolver'; // Import dependency resolution from @automaker/dependency-resolver import { resolveDependencies } from '@automaker/dependency-resolver'; // Import git utils from @automaker/git-utils import { getGitRepositoryDiffs } from '@automaker/git-utils'; ``` ### ❌ DON'T ```typescript // DON'T import from old paths import { Feature } from '../services/feature-loader'; // ❌ import { ExecuteOptions } from '../providers/types'; // ❌ import { createLogger } from '../lib/logger'; // ❌ import { resolveModelString } from '../lib/model-resolver'; // ❌ import { isGitRepo } from '../routes/common'; // ❌ import { resolveDependencies } from '../lib/dependency-resolver'; // ❌ // DON'T import from old lib/ paths import { getFeatureDir } from '../lib/automaker-paths'; // ❌ import { classifyError } from '../lib/error-handler'; // ❌ // DON'T define types that exist in @automaker/types interface Feature { ... } // ❌ Use: import type { Feature } from '@automaker/types'; ``` ## Migration Checklist When refactoring server code, check: - [ ] All `Feature` imports use `@automaker/types` - [ ] All `ExecuteOptions` imports use `@automaker/types` - [ ] All logger usage uses `@automaker/utils` - [ ] All path operations use `@automaker/platform` - [ ] All model resolution uses `@automaker/model-resolver` - [ ] All dependency checks use `@automaker/dependency-resolver` - [ ] All git operations use `@automaker/git-utils` - [ ] No imports from old `lib/` paths - [ ] No imports from `services/feature-loader` for types - [ ] No imports from `providers/types` ## Package Dependencies Understanding the dependency chain helps prevent circular dependencies: ``` @automaker/types (no dependencies) ↓ @automaker/utils @automaker/platform @automaker/model-resolver @automaker/dependency-resolver ↓ @automaker/git-utils ↓ @automaker/server @automaker/ui ``` **Rule:** Packages can only depend on packages above them in the chain. ## Building Packages All packages must be built before use: ```bash # Build all packages cd libs/types && npm run build cd libs/utils && npm run build cd libs/platform && npm run build cd libs/model-resolver && npm run build cd libs/dependency-resolver && npm run build cd libs/git-utils && npm run build # Or from root npm install # Installs and links workspace packages ``` ## Module Format - **dependency-resolver**: ES modules (`type: "module"`) for Vite compatibility - **All others**: CommonJS for Node.js compatibility ## Testing When writing tests: ```typescript // ✅ Import from packages import type { Feature } from '@automaker/types'; import { createLogger } from '@automaker/utils'; // ❌ Don't import from src import { Feature } from '../../../src/services/feature-loader'; ``` ## Summary for LLMs **Quick reference:** - Types → `@automaker/types` - Logging/Errors → `@automaker/utils` - Paths/Security → `@automaker/platform` - Model Resolution → `@automaker/model-resolver` - Dependency Ordering → `@automaker/dependency-resolver` - Git Operations → `@automaker/git-utils` **Never import from:** `lib/*`, `services/feature-loader` (for types), `providers/types`, `routes/common` **Always:** Use the shared packages instead of local implementations.