mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-03 08:53:36 +00:00
docs: add comprehensive documentation for shared packages
- 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 <noreply@anthropic.com>
This commit is contained in:
388
docs/llm-shared-packages.md
Normal file
388
docs/llm-shared-packages.md
Normal file
@@ -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.
|
||||||
178
libs/dependency-resolver/README.md
Normal file
178
libs/dependency-resolver/README.md
Normal file
@@ -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
|
||||||
@@ -11,7 +11,6 @@
|
|||||||
},
|
},
|
||||||
"keywords": ["automaker", "dependency", "resolver"],
|
"keywords": ["automaker", "dependency", "resolver"],
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@automaker/types": "^1.0.0"
|
"@automaker/types": "^1.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
204
libs/git-utils/README.md
Normal file
204
libs/git-utils/README.md
Normal file
@@ -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<string, string[]>);
|
||||||
|
|
||||||
|
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
|
||||||
@@ -10,7 +10,6 @@
|
|||||||
},
|
},
|
||||||
"keywords": ["automaker", "git", "utils"],
|
"keywords": ["automaker", "git", "utils"],
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@automaker/types": "^1.0.0",
|
"@automaker/types": "^1.0.0",
|
||||||
"@automaker/utils": "^1.0.0"
|
"@automaker/utils": "^1.0.0"
|
||||||
|
|||||||
133
libs/model-resolver/README.md
Normal file
133
libs/model-resolver/README.md
Normal file
@@ -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
|
||||||
@@ -10,7 +10,6 @@
|
|||||||
},
|
},
|
||||||
"keywords": ["automaker", "model", "resolver"],
|
"keywords": ["automaker", "model", "resolver"],
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@automaker/types": "^1.0.0"
|
"@automaker/types": "^1.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
165
libs/platform/README.md
Normal file
165
libs/platform/README.md
Normal file
@@ -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`
|
||||||
@@ -10,7 +10,6 @@
|
|||||||
},
|
},
|
||||||
"keywords": ["automaker", "platform"],
|
"keywords": ["automaker", "platform"],
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@automaker/types": "^1.0.0"
|
"@automaker/types": "^1.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
129
libs/types/README.md
Normal file
129
libs/types/README.md
Normal file
@@ -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`
|
||||||
@@ -10,7 +10,6 @@
|
|||||||
},
|
},
|
||||||
"keywords": ["automaker", "types"],
|
"keywords": ["automaker", "types"],
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "MIT",
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^22.10.5",
|
"@types/node": "^22.10.5",
|
||||||
"typescript": "^5.7.3"
|
"typescript": "^5.7.3"
|
||||||
|
|||||||
154
libs/utils/README.md
Normal file
154
libs/utils/README.md
Normal file
@@ -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`
|
||||||
@@ -10,7 +10,6 @@
|
|||||||
},
|
},
|
||||||
"keywords": ["automaker", "utils"],
|
"keywords": ["automaker", "utils"],
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@automaker/types": "^1.0.0"
|
"@automaker/types": "^1.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user