From 7ad7b63da2fae4ab2d0ae0df2955a2974c6a3b79 Mon Sep 17 00:00:00 2001 From: Kacper Date: Fri, 19 Dec 2025 23:52:42 +0100 Subject: [PATCH] docs: add comprehensive documentation for shared packages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added README.md for all 6 shared packages: - @automaker/types: Type definitions and interfaces - @automaker/utils: Utility functions (logger, error handling, images) - @automaker/platform: Platform utilities (paths, subprocess, security) - @automaker/model-resolver: Claude model resolution - @automaker/dependency-resolver: Feature dependency ordering - @automaker/git-utils: Git operations and diff generation - Removed MIT license from all package.json files (using custom dual license) - Created comprehensive LLM guide (docs/llm-shared-packages.md): - When to use each package - Import patterns and examples - Common usage patterns - Migration checklist - Do's and don'ts for LLMs Documentation helps developers and AI assistants understand package purpose, usage, and best practices. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- docs/llm-shared-packages.md | 388 ++++++++++++++++++++++++++ libs/dependency-resolver/README.md | 178 ++++++++++++ libs/dependency-resolver/package.json | 1 - libs/git-utils/README.md | 204 ++++++++++++++ libs/git-utils/package.json | 1 - libs/model-resolver/README.md | 133 +++++++++ libs/model-resolver/package.json | 1 - libs/platform/README.md | 165 +++++++++++ libs/platform/package.json | 1 - libs/types/README.md | 129 +++++++++ libs/types/package.json | 1 - libs/utils/README.md | 154 ++++++++++ libs/utils/package.json | 1 - 13 files changed, 1351 insertions(+), 6 deletions(-) create mode 100644 docs/llm-shared-packages.md create mode 100644 libs/dependency-resolver/README.md create mode 100644 libs/git-utils/README.md create mode 100644 libs/model-resolver/README.md create mode 100644 libs/platform/README.md create mode 100644 libs/types/README.md create mode 100644 libs/utils/README.md diff --git a/docs/llm-shared-packages.md b/docs/llm-shared-packages.md new file mode 100644 index 00000000..537f263e --- /dev/null +++ b/docs/llm-shared-packages.md @@ -0,0 +1,388 @@ +# 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. diff --git a/libs/dependency-resolver/README.md b/libs/dependency-resolver/README.md new file mode 100644 index 00000000..ca79fda9 --- /dev/null +++ b/libs/dependency-resolver/README.md @@ -0,0 +1,178 @@ +# @automaker/dependency-resolver + +Feature dependency resolution using topological sorting. + +## Overview + +This package provides dependency resolution for AutoMaker features using Kahn's algorithm with priority-aware ordering. It ensures features are executed in the correct order based on their dependencies. + +## Installation + +```bash +npm install @automaker/dependency-resolver +``` + +## Exports + +### Resolve Dependencies +Order features based on dependencies and priorities. + +```typescript +import { resolveDependencies } from '@automaker/dependency-resolver'; +import type { Feature } from '@automaker/types'; + +const features: Feature[] = [ + { + id: 'database', + category: 'backend', + description: 'Setup database', + priority: 1 + }, + { + id: 'auth', + category: 'backend', + description: 'Add authentication', + dependencies: ['database'], + priority: 2 + }, + { + id: 'api', + category: 'backend', + description: 'Create API endpoints', + dependencies: ['auth'], + priority: 3 + } +]; + +const result = resolveDependencies(features); + +console.log(result.orderedFeatures); +// [database, auth, api] + +if (result.hasCycle) { + console.error('Circular dependency detected!'); + console.error('Features in cycle:', result.cyclicFeatures); +} +``` + +### Check Dependencies Satisfied +Check if a feature's dependencies are satisfied. + +```typescript +import { areDependenciesSatisfied } from '@automaker/dependency-resolver'; + +const allFeatures: Feature[] = [ + { id: 'database', status: 'completed', ... }, + { id: 'auth', status: 'pending', dependencies: ['database'], ... } +]; + +const authFeature = allFeatures.find(f => f.id === 'auth'); + +if (areDependenciesSatisfied(authFeature, allFeatures)) { + console.log('Auth feature is ready to execute'); +} else { + console.log('Waiting for dependencies'); +} +``` + +### Get Blocking Dependencies +Get list of incomplete dependencies blocking a feature. + +```typescript +import { getBlockingDependencies } from '@automaker/dependency-resolver'; + +const blocking = getBlockingDependencies(feature, allFeatures); + +if (blocking.length > 0) { + console.log(`Feature blocked by: ${blocking.join(', ')}`); +} else { + console.log('No blocking dependencies'); +} +``` + +## Usage Example + +```typescript +import { + resolveDependencies, + areDependenciesSatisfied, + getBlockingDependencies +} from '@automaker/dependency-resolver'; +import type { Feature } from '@automaker/types'; + +async function executeFeatures(features: Feature[]) { + // Resolve dependency order + const { orderedFeatures, hasCycle, cyclicFeatures } = resolveDependencies(features); + + if (hasCycle) { + throw new Error(`Circular dependency: ${cyclicFeatures.join(' → ')}`); + } + + // Execute in order + for (const feature of orderedFeatures) { + // Check if dependencies are satisfied + if (!areDependenciesSatisfied(feature, features)) { + const blocking = getBlockingDependencies(feature, features); + console.log(`Skipping ${feature.id}, blocked by: ${blocking.join(', ')}`); + continue; + } + + // Execute feature + console.log(`Executing: ${feature.id}`); + await executeFeature(feature); + + // Mark as completed + feature.status = 'completed'; + } +} +``` + +## Algorithm + +### Topological Sort (Kahn's Algorithm) +1. Calculate in-degree for each feature (number of dependencies) +2. Start with features that have no dependencies (in-degree = 0) +3. Process features in priority order +4. Remove processed features from dependency graph +5. Repeat until all features processed or cycle detected + +### Priority Handling +- Features with lower priority numbers execute first +- When multiple features have same in-degree, priority determines order +- Features without explicit priority default to lowest priority + +### Cycle Detection +- Detects circular dependencies +- Returns affected features in cycle +- Prevents infinite loops in execution + +## Return Types + +### DependencyResolutionResult +```typescript +interface DependencyResolutionResult { + orderedFeatures: Feature[]; // Features in execution order + hasCycle: boolean; // True if circular dependency detected + cyclicFeatures: string[]; // Feature IDs involved in cycle +} +``` + +## Edge Cases + +### Missing Dependencies +Features with dependencies on non-existent features are treated as if the dependency is satisfied (allows flexibility). + +### Self-Dependencies +Features depending on themselves are detected as cycles. + +### Empty Dependencies Array +Treated same as no dependencies - feature is ready immediately. + +## Dependencies + +- `@automaker/types` - Feature type definition + +## Used By + +- `@automaker/server` - Auto-mode feature execution +- `@automaker/ui` - Board view feature ordering diff --git a/libs/dependency-resolver/package.json b/libs/dependency-resolver/package.json index 4c9f498e..78531783 100644 --- a/libs/dependency-resolver/package.json +++ b/libs/dependency-resolver/package.json @@ -11,7 +11,6 @@ }, "keywords": ["automaker", "dependency", "resolver"], "author": "", - "license": "MIT", "dependencies": { "@automaker/types": "^1.0.0" }, diff --git a/libs/git-utils/README.md b/libs/git-utils/README.md new file mode 100644 index 00000000..0549b1d2 --- /dev/null +++ b/libs/git-utils/README.md @@ -0,0 +1,204 @@ +# @automaker/git-utils + +Git operations and utilities for AutoMaker. + +## Overview + +This package provides git-related utilities including repository detection, status parsing, and diff generation for both tracked and untracked files. + +## Installation + +```bash +npm install @automaker/git-utils +``` + +## Exports + +### Repository Detection +Check if a path is a git repository. + +```typescript +import { isGitRepo } from '@automaker/git-utils'; + +const isRepo = await isGitRepo('/project/path'); +if (isRepo) { + console.log('This is a git repository'); +} +``` + +### Status Parsing +Parse git status output into structured data. + +```typescript +import { parseGitStatus } from '@automaker/git-utils'; +import type { FileStatus } from '@automaker/git-utils'; + +const statusOutput = await execAsync('git status --porcelain'); +const files: FileStatus[] = parseGitStatus(statusOutput.stdout); + +files.forEach(file => { + console.log(`${file.statusText}: ${file.path}`); + // Example: "Modified: src/index.ts" + // Example: "Untracked: new-file.ts" +}); +``` + +### Diff Generation +Generate diffs including untracked files. + +```typescript +import { + generateSyntheticDiffForNewFile, + appendUntrackedFileDiffs, + getGitRepositoryDiffs +} from '@automaker/git-utils'; + +// Generate diff for single untracked file +const diff = await generateSyntheticDiffForNewFile( + '/project/path', + 'src/new-file.ts' +); + +// Get complete repository diffs (tracked + untracked) +const result = await getGitRepositoryDiffs('/project/path'); +console.log(result.diff); // Combined diff string +console.log(result.files); // Array of FileStatus +console.log(result.hasChanges); // Boolean +``` + +### Non-Git Directory Support +Handle non-git directories by treating all files as new. + +```typescript +import { + listAllFilesInDirectory, + generateDiffsForNonGitDirectory +} from '@automaker/git-utils'; + +// List all files (excluding build artifacts) +const files = await listAllFilesInDirectory('/project/path'); + +// Generate diffs for non-git directory +const result = await generateDiffsForNonGitDirectory('/project/path'); +console.log(result.diff); // Synthetic diffs for all files +console.log(result.files); // All files as "New" status +``` + +## Types + +### FileStatus +```typescript +interface FileStatus { + status: string; // Git status code (M/A/D/R/C/U/?/!) + path: string; // File path relative to repo root + statusText: string; // Human-readable status +} +``` + +### Status Codes +- `M` - Modified +- `A` - Added +- `D` - Deleted +- `R` - Renamed +- `C` - Copied +- `U` - Updated +- `?` - Untracked +- `!` - Ignored +- ` ` - Unmodified + +### Status Text Examples +- `"Modified"` - File has changes +- `"Added"` - New file in staging +- `"Deleted"` - File removed +- `"Renamed"` - File renamed +- `"Untracked"` - New file not in git +- `"Modified (staged), Modified (unstaged)"` - Changes in both areas + +## Usage Example + +```typescript +import { + isGitRepo, + getGitRepositoryDiffs, + parseGitStatus +} from '@automaker/git-utils'; + +async function getProjectChanges(projectPath: string) { + const isRepo = await isGitRepo(projectPath); + + if (!isRepo) { + console.log('Not a git repository, analyzing all files...'); + } + + const result = await getGitRepositoryDiffs(projectPath); + + if (!result.hasChanges) { + console.log('No changes detected'); + return; + } + + console.log(`Found ${result.files.length} changed files:\n`); + + // Group by status + const byStatus = result.files.reduce((acc, file) => { + acc[file.statusText] = acc[file.statusText] || []; + acc[file.statusText].push(file.path); + return acc; + }, {} as Record); + + Object.entries(byStatus).forEach(([status, paths]) => { + console.log(`${status}:`); + paths.forEach(path => console.log(` - ${path}`)); + }); + + return result.diff; +} +``` + +## Features + +### Binary File Detection +Automatically detects binary files by extension and generates appropriate diff markers. + +**Supported binary extensions:** +- Images: `.png`, `.jpg`, `.jpeg`, `.gif`, `.svg`, etc. +- Documents: `.pdf`, `.doc`, `.docx`, etc. +- Archives: `.zip`, `.tar`, `.gz`, etc. +- Media: `.mp3`, `.mp4`, `.wav`, etc. +- Fonts: `.ttf`, `.otf`, `.woff`, etc. + +### Large File Handling +Files larger than 1MB show size information instead of full content. + +### Synthetic Diff Format +Generates unified diff format for untracked files: +```diff +diff --git a/new-file.ts b/new-file.ts +new file mode 100644 +index 0000000..0000000 +--- /dev/null ++++ b/new-file.ts +@@ -0,0 +1,10 @@ ++export function hello() { ++ console.log('Hello'); ++} +``` + +### Directory Filtering +When scanning non-git directories, automatically excludes: +- `node_modules` +- `.git` +- `.automaker` +- `dist`, `build` +- `.next`, `.nuxt` +- `__pycache__`, `.cache` +- `coverage` + +## Dependencies + +- `@automaker/types` - FileStatus type definition +- `@automaker/utils` - Logger utilities + +## Used By + +- `@automaker/server` - Git routes, worktree operations, feature context diff --git a/libs/git-utils/package.json b/libs/git-utils/package.json index 7e03158e..488026ab 100644 --- a/libs/git-utils/package.json +++ b/libs/git-utils/package.json @@ -10,7 +10,6 @@ }, "keywords": ["automaker", "git", "utils"], "author": "", - "license": "MIT", "dependencies": { "@automaker/types": "^1.0.0", "@automaker/utils": "^1.0.0" diff --git a/libs/model-resolver/README.md b/libs/model-resolver/README.md new file mode 100644 index 00000000..22b6c54c --- /dev/null +++ b/libs/model-resolver/README.md @@ -0,0 +1,133 @@ +# @automaker/model-resolver + +Claude model resolution and mapping utilities. + +## Overview + +This package handles Claude model resolution, converting user-friendly aliases to actual Claude model identifiers and providing default model configurations. + +## Installation + +```bash +npm install @automaker/model-resolver +``` + +## Exports + +### Model Resolution +Convert model aliases to full model identifiers. + +```typescript +import { resolveModelString, DEFAULT_MODELS } from '@automaker/model-resolver'; +import { CLAUDE_MODEL_MAP } from '@automaker/types'; + +// Resolve model string +const model = resolveModelString('sonnet'); +// Returns: 'claude-sonnet-4-20250514' + +const model2 = resolveModelString('haiku'); +// Returns: 'claude-haiku-4-5' + +const model3 = resolveModelString('opus'); +// Returns: 'claude-opus-4-5-20251101' + +// Use with custom default +const model4 = resolveModelString(undefined, 'claude-sonnet-4-20250514'); +// Returns: 'claude-sonnet-4-20250514' (default) + +// Direct model ID passthrough +const model5 = resolveModelString('claude-opus-4-5-20251101'); +// Returns: 'claude-opus-4-5-20251101' (unchanged) +``` + +### Get Effective Model +Get the actual model that will be used. + +```typescript +import { getEffectiveModel } from '@automaker/model-resolver'; + +// Get effective model with fallback chain +const model = getEffectiveModel({ + requestedModel: 'sonnet', + featureModel: undefined, + defaultModel: 'claude-sonnet-4-20250514' +}); +``` + +### Model Constants +Access model mappings and defaults. + +```typescript +import { DEFAULT_MODELS } from '@automaker/model-resolver'; +import { CLAUDE_MODEL_MAP } from '@automaker/types'; + +// Default models for different contexts +console.log(DEFAULT_MODELS.claude); // 'claude-sonnet-4-20250514' +console.log(DEFAULT_MODELS.autoMode); // 'claude-sonnet-4-20250514' +console.log(DEFAULT_MODELS.chat); // 'claude-sonnet-4-20250514' + +// Model alias mappings +console.log(CLAUDE_MODEL_MAP.haiku); // 'claude-haiku-4-5' +console.log(CLAUDE_MODEL_MAP.sonnet); // 'claude-sonnet-4-20250514' +console.log(CLAUDE_MODEL_MAP.opus); // 'claude-opus-4-5-20251101' +``` + +## Usage Example + +```typescript +import { resolveModelString, DEFAULT_MODELS } from '@automaker/model-resolver'; +import type { Feature } from '@automaker/types'; + +function prepareFeatureExecution(feature: Feature) { + // Resolve model from feature or use default + const model = resolveModelString( + feature.model, + DEFAULT_MODELS.autoMode + ); + + console.log(`Executing feature with model: ${model}`); + + return { + featureId: feature.id, + model, + // ... other options + }; +} + +// Example usage +const feature: Feature = { + id: 'auth-feature', + category: 'backend', + description: 'Add authentication', + model: 'opus' // User-friendly alias +}; + +prepareFeatureExecution(feature); +// Output: Executing feature with model: claude-opus-4-5-20251101 +``` + +## Supported Models + +### Current Model Aliases +- `haiku` → `claude-haiku-4-5` +- `sonnet` → `claude-sonnet-4-20250514` +- `opus` → `claude-opus-4-5-20251101` + +### Model Selection Guide +- **Haiku**: Fast responses, simple tasks, lower cost +- **Sonnet**: Balanced performance, most tasks (recommended default) +- **Opus**: Maximum capability, complex reasoning, highest cost + +## Dependencies + +- `@automaker/types` - Model type definitions and constants + +## Used By + +- `@automaker/server` - Feature execution, agent chat, enhancement + +## Notes + +- Model strings that don't match aliases are passed through unchanged +- This allows direct use of specific model versions like `claude-sonnet-4-20250514` +- Always falls back to a sensible default if no model is specified diff --git a/libs/model-resolver/package.json b/libs/model-resolver/package.json index ad2f07e0..2adcf10a 100644 --- a/libs/model-resolver/package.json +++ b/libs/model-resolver/package.json @@ -10,7 +10,6 @@ }, "keywords": ["automaker", "model", "resolver"], "author": "", - "license": "MIT", "dependencies": { "@automaker/types": "^1.0.0" }, diff --git a/libs/platform/README.md b/libs/platform/README.md new file mode 100644 index 00000000..307b6966 --- /dev/null +++ b/libs/platform/README.md @@ -0,0 +1,165 @@ +# @automaker/platform + +Platform-specific utilities for AutoMaker. + +## Overview + +This package provides platform-specific utilities including path management, subprocess handling, and security validation. It handles AutoMaker's directory structure and system operations. + +## Installation + +```bash +npm install @automaker/platform +``` + +## Exports + +### Path Management +AutoMaker directory structure utilities. + +```typescript +import { + getAutomakerDir, + getFeaturesDir, + getFeatureDir, + getFeatureImagesDir, + getBoardDir, + getImagesDir, + getContextDir, + getWorktreesDir, + getAppSpecPath, + getBranchTrackingPath, + ensureAutomakerDir +} from '@automaker/platform'; + +// Get AutoMaker directory: /project/.automaker +const automakerDir = getAutomakerDir('/project/path'); + +// Get features directory: /project/.automaker/features +const featuresDir = getFeaturesDir('/project/path'); + +// Get specific feature directory: /project/.automaker/features/feature-id +const featureDir = getFeatureDir('/project/path', 'feature-id'); + +// Get feature images: /project/.automaker/features/feature-id/images +const imagesDir = getFeatureImagesDir('/project/path', 'feature-id'); + +// Ensure .automaker directory exists +await ensureAutomakerDir('/project/path'); +``` + +### Subprocess Management +Spawn and manage subprocesses with JSON-lines output. + +```typescript +import { spawnJSONLProcess, spawnProcess } from '@automaker/platform'; + +// Spawn process with JSONL output parsing +const result = await spawnJSONLProcess({ + command: 'claude-agent', + args: ['--output', 'jsonl'], + cwd: '/project/path', + onLine: (data) => console.log('Received:', data), + onError: (error) => console.error('Error:', error) +}); + +// Spawn regular process +const output = await spawnProcess({ + command: 'git', + args: ['status'], + cwd: '/project/path' +}); +``` + +### Security Validation +Path validation and security checks. + +```typescript +import { + initAllowedPaths, + addAllowedPath, + isPathAllowed, + validatePath, + getAllowedPaths +} from '@automaker/platform'; + +// Initialize allowed paths from environment +initAllowedPaths(); + +// Add custom allowed path +addAllowedPath('/custom/path'); + +// Check if path is allowed +if (isPathAllowed('/project/path')) { + console.log('Path is allowed'); +} + +// Validate and normalize path +const safePath = validatePath('/requested/path'); + +// Get all allowed paths +const allowed = getAllowedPaths(); +``` + +## Usage Example + +```typescript +import { + getFeatureDir, + ensureAutomakerDir, + spawnJSONLProcess, + validatePath +} from '@automaker/platform'; + +async function executeFeature(projectPath: string, featureId: string) { + // Validate project path + const safePath = validatePath(projectPath); + + // Ensure AutoMaker directory exists + await ensureAutomakerDir(safePath); + + // Get feature directory + const featureDir = getFeatureDir(safePath, featureId); + + // Execute agent in feature directory + const result = await spawnJSONLProcess({ + command: 'claude-agent', + args: ['execute'], + cwd: featureDir, + onLine: (data) => { + if (data.type === 'progress') { + console.log('Progress:', data.progress); + } + } + }); + + return result; +} +``` + +## Directory Structure + +AutoMaker uses the following directory structure: + +``` +/project/ +├── .automaker/ +│ ├── features/ # Feature storage +│ │ └── {featureId}/ +│ │ ├── feature.json +│ │ └── images/ +│ ├── board/ # Board configuration +│ ├── context/ # Context files +│ ├── images/ # Global images +│ ├── worktrees/ # Git worktrees +│ ├── app-spec.md # App specification +│ └── branch-tracking.json +``` + +## Dependencies + +- `@automaker/types` - Type definitions + +## Used By + +- `@automaker/server` diff --git a/libs/platform/package.json b/libs/platform/package.json index c9f4cb45..761549eb 100644 --- a/libs/platform/package.json +++ b/libs/platform/package.json @@ -10,7 +10,6 @@ }, "keywords": ["automaker", "platform"], "author": "", - "license": "MIT", "dependencies": { "@automaker/types": "^1.0.0" }, diff --git a/libs/types/README.md b/libs/types/README.md new file mode 100644 index 00000000..a3af5bd6 --- /dev/null +++ b/libs/types/README.md @@ -0,0 +1,129 @@ +# @automaker/types + +Shared TypeScript type definitions for AutoMaker. + +## Overview + +This package contains all core type definitions used across AutoMaker's server and UI components. It has no dependencies and serves as the foundation for other packages. + +## Installation + +```bash +npm install @automaker/types +``` + +## Exports + +### Provider Types +Types for AI provider integration and Claude SDK. + +```typescript +import type { + ProviderConfig, + ConversationMessage, + ExecuteOptions, + ContentBlock, + ProviderMessage, + InstallationStatus, + ValidationResult, + ModelDefinition +} from '@automaker/types'; +``` + +### Feature Types +Feature management and workflow types. + +```typescript +import type { + Feature, + FeatureStatus, + PlanningMode, + PlanSpec +} from '@automaker/types'; +``` + +**Feature Interface:** +- `id` - Unique feature identifier +- `category` - Feature category/type +- `description` - Feature description +- `dependencies` - Array of feature IDs this depends on +- `status` - Current status (pending/running/completed/failed/verified) +- `planningMode` - Planning approach (skip/lite/spec/full) +- `planSpec` - Plan specification and approval status + +### Session Types +Agent session management. + +```typescript +import type { + AgentSession, + SessionListItem, + CreateSessionParams, + UpdateSessionParams +} from '@automaker/types'; +``` + +### Error Types +Error classification and handling. + +```typescript +import type { + ErrorType, + ErrorInfo +} from '@automaker/types'; +``` + +### Image Types +Image handling for prompts. + +```typescript +import type { + ImageData, + ImageContentBlock +} from '@automaker/types'; +``` + +### Model Types +Claude model definitions and mappings. + +```typescript +import { + CLAUDE_MODEL_MAP, + DEFAULT_MODELS, + type ModelAlias +} from '@automaker/types'; +``` + +## Usage Example + +```typescript +import type { Feature, ExecuteOptions } from '@automaker/types'; + +const feature: Feature = { + id: 'auth-feature', + category: 'backend', + description: 'Implement user authentication', + dependencies: ['database-setup'], + status: 'pending', + planningMode: 'spec' +}; + +const options: ExecuteOptions = { + model: 'claude-sonnet-4-20250514', + temperature: 0.7 +}; +``` + +## Dependencies + +None - this is a pure types package. + +## Used By + +- `@automaker/utils` +- `@automaker/platform` +- `@automaker/model-resolver` +- `@automaker/dependency-resolver` +- `@automaker/git-utils` +- `@automaker/server` +- `@automaker/ui` diff --git a/libs/types/package.json b/libs/types/package.json index 032c8a19..52b42eeb 100644 --- a/libs/types/package.json +++ b/libs/types/package.json @@ -10,7 +10,6 @@ }, "keywords": ["automaker", "types"], "author": "", - "license": "MIT", "devDependencies": { "@types/node": "^22.10.5", "typescript": "^5.7.3" diff --git a/libs/utils/README.md b/libs/utils/README.md new file mode 100644 index 00000000..c409f9d0 --- /dev/null +++ b/libs/utils/README.md @@ -0,0 +1,154 @@ +# @automaker/utils + +Shared utility functions for AutoMaker. + +## Overview + +This package provides common utility functions used across AutoMaker's server and UI. It includes error handling, logging, conversation utilities, image handling, and prompt building. + +## Installation + +```bash +npm install @automaker/utils +``` + +## Exports + +### Logger +Structured logging with context. + +```typescript +import { createLogger, LogLevel } from '@automaker/utils'; + +const logger = createLogger('MyComponent'); +logger.info('Processing request'); +logger.error('Failed to process:', error); +logger.debug('Debug information', { data }); +``` + +### Error Handler +Error classification and user-friendly messages. + +```typescript +import { + isAbortError, + isCancellationError, + isAuthenticationError, + classifyError, + getUserFriendlyErrorMessage +} from '@automaker/utils'; + +try { + await operation(); +} catch (error) { + if (isAbortError(error)) { + console.log('Operation was aborted'); + } + + const errorInfo = classifyError(error); + const message = getUserFriendlyErrorMessage(error); +} +``` + +### Conversation Utils +Message formatting and conversion. + +```typescript +import { + extractTextFromContent, + normalizeContentBlocks, + formatHistoryAsText, + convertHistoryToMessages +} from '@automaker/utils'; + +const text = extractTextFromContent(contentBlocks); +const normalized = normalizeContentBlocks(content); +const formatted = formatHistoryAsText(messages); +const converted = convertHistoryToMessages(history); +``` + +### Image Handler +Image processing for Claude prompts. + +```typescript +import { + getMimeTypeForImage, + readImageAsBase64, + convertImagesToContentBlocks, + formatImagePathsForPrompt +} from '@automaker/utils'; + +const mimeType = getMimeTypeForImage('screenshot.png'); +const base64 = await readImageAsBase64('/path/to/image.jpg'); +const blocks = await convertImagesToContentBlocks(imagePaths, basePath); +const formatted = formatImagePathsForPrompt(imagePaths); +``` + +### Prompt Builder +Build prompts with images for Claude. + +```typescript +import { buildPromptWithImages } from '@automaker/utils'; + +const result = await buildPromptWithImages({ + basePrompt: 'Analyze this screenshot', + imagePaths: ['/path/to/screenshot.png'], + basePath: '/project/path' +}); + +console.log(result.prompt); // Prompt with image references +console.log(result.images); // Image data for Claude +``` + +### File System Utils +Common file system operations. + +```typescript +import { + ensureDir, + fileExists, + readJsonFile, + writeJsonFile +} from '@automaker/utils'; + +await ensureDir('/path/to/dir'); +const exists = await fileExists('/path/to/file'); +const data = await readJsonFile('/config.json'); +await writeJsonFile('/config.json', data); +``` + +## Usage Example + +```typescript +import { createLogger, classifyError, buildPromptWithImages } from '@automaker/utils'; + +const logger = createLogger('FeatureExecutor'); + +async function executeWithImages(prompt: string, images: string[]) { + try { + logger.info('Building prompt with images'); + + const result = await buildPromptWithImages({ + basePrompt: prompt, + imagePaths: images, + basePath: process.cwd() + }); + + logger.debug('Prompt built successfully', { imageCount: result.images.length }); + return result; + } catch (error) { + const errorInfo = classifyError(error); + logger.error('Failed to build prompt:', errorInfo.message); + throw error; + } +} +``` + +## Dependencies + +- `@automaker/types` - Type definitions + +## Used By + +- `@automaker/server` +- `@automaker/ui` diff --git a/libs/utils/package.json b/libs/utils/package.json index 3be9294e..5aab0415 100644 --- a/libs/utils/package.json +++ b/libs/utils/package.json @@ -10,7 +10,6 @@ }, "keywords": ["automaker", "utils"], "author": "", - "license": "MIT", "dependencies": { "@automaker/types": "^1.0.0" },