mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-03 08:53:36 +00:00
refactor: extract auto-mode-service into modular services
Reduce auto-mode-service.ts from 1308 to 516 lines (60% reduction) by extracting reusable functionality into shared packages and services: - Add feature prompt builders to @automaker/prompts (buildFeaturePrompt, buildFollowUpPrompt, buildContinuationPrompt, extractTitleFromDescription) - Add planning prompts and task parsing to @automaker/prompts - Add stream processor utilities to @automaker/utils (sleep, processStream) - Add git commit utilities to @automaker/git-utils (commitAll, hasUncommittedChanges) - Create ProjectAnalyzer service for project analysis - Create FeatureVerificationService for verify/commit operations - Extend FeatureLoader with updateStatus, updatePlanSpec, getPending methods - Expand FeatureStatus type to include all used statuses - Add PlanSpec and ParsedTask types to @automaker/types 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,92 +1,5 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
|
||||
/**
|
||||
* Test the task parsing logic by reimplementing the parsing functions
|
||||
* These mirror the logic in auto-mode-service.ts parseTasksFromSpec and parseTaskLine
|
||||
*/
|
||||
|
||||
interface ParsedTask {
|
||||
id: string;
|
||||
description: string;
|
||||
filePath?: string;
|
||||
phase?: string;
|
||||
status: 'pending' | 'in_progress' | 'completed';
|
||||
}
|
||||
|
||||
function parseTaskLine(line: string, currentPhase?: string): ParsedTask | null {
|
||||
// Match pattern: - [ ] T###: Description | File: path
|
||||
const taskMatch = line.match(/- \[ \] (T\d{3}):\s*([^|]+)(?:\|\s*File:\s*(.+))?$/);
|
||||
if (!taskMatch) {
|
||||
// Try simpler pattern without file
|
||||
const simpleMatch = line.match(/- \[ \] (T\d{3}):\s*(.+)$/);
|
||||
if (simpleMatch) {
|
||||
return {
|
||||
id: simpleMatch[1],
|
||||
description: simpleMatch[2].trim(),
|
||||
phase: currentPhase,
|
||||
status: 'pending',
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
id: taskMatch[1],
|
||||
description: taskMatch[2].trim(),
|
||||
filePath: taskMatch[3]?.trim(),
|
||||
phase: currentPhase,
|
||||
status: 'pending',
|
||||
};
|
||||
}
|
||||
|
||||
function parseTasksFromSpec(specContent: string): ParsedTask[] {
|
||||
const tasks: ParsedTask[] = [];
|
||||
|
||||
// Extract content within ```tasks ... ``` block
|
||||
const tasksBlockMatch = specContent.match(/```tasks\s*([\s\S]*?)```/);
|
||||
if (!tasksBlockMatch) {
|
||||
// Try fallback: look for task lines anywhere in content
|
||||
const taskLines = specContent.match(/- \[ \] T\d{3}:.*$/gm);
|
||||
if (!taskLines) {
|
||||
return tasks;
|
||||
}
|
||||
// Parse fallback task lines
|
||||
let currentPhase: string | undefined;
|
||||
for (const line of taskLines) {
|
||||
const parsed = parseTaskLine(line, currentPhase);
|
||||
if (parsed) {
|
||||
tasks.push(parsed);
|
||||
}
|
||||
}
|
||||
return tasks;
|
||||
}
|
||||
|
||||
const tasksContent = tasksBlockMatch[1];
|
||||
const lines = tasksContent.split('\n');
|
||||
|
||||
let currentPhase: string | undefined;
|
||||
|
||||
for (const line of lines) {
|
||||
const trimmedLine = line.trim();
|
||||
|
||||
// Check for phase header (e.g., "## Phase 1: Foundation")
|
||||
const phaseMatch = trimmedLine.match(/^##\s*(.+)$/);
|
||||
if (phaseMatch) {
|
||||
currentPhase = phaseMatch[1].trim();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for task line
|
||||
if (trimmedLine.startsWith('- [ ]')) {
|
||||
const parsed = parseTaskLine(trimmedLine, currentPhase);
|
||||
if (parsed) {
|
||||
tasks.push(parsed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tasks;
|
||||
}
|
||||
import { parseTaskLine, parseTasksFromSpec } from '@automaker/prompts';
|
||||
|
||||
describe('Task Parsing', () => {
|
||||
describe('parseTaskLine', () => {
|
||||
|
||||
Reference in New Issue
Block a user