mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-04 09:13:08 +00:00
Changes from feat/improve-ai-suggestions
This commit is contained in:
@@ -6,9 +6,87 @@ import { query } from '@anthropic-ai/claude-agent-sdk';
|
|||||||
import type { EventEmitter } from '../../lib/events.js';
|
import type { EventEmitter } from '../../lib/events.js';
|
||||||
import { createLogger } from '@automaker/utils';
|
import { createLogger } from '@automaker/utils';
|
||||||
import { createSuggestionsOptions } from '../../lib/sdk-options.js';
|
import { createSuggestionsOptions } from '../../lib/sdk-options.js';
|
||||||
|
import { FeatureLoader } from '../../services/feature-loader.js';
|
||||||
|
import { getAppSpecPath } from '@automaker/platform';
|
||||||
|
import * as secureFs from '../../lib/secure-fs.js';
|
||||||
|
|
||||||
const logger = createLogger('Suggestions');
|
const logger = createLogger('Suggestions');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract implemented features from app_spec.txt XML content
|
||||||
|
*/
|
||||||
|
function extractImplementedFeatures(specContent: string): string[] {
|
||||||
|
const features: string[] = [];
|
||||||
|
|
||||||
|
// Match <implemented_features>...</implemented_features> section
|
||||||
|
const implementedMatch = specContent.match(
|
||||||
|
/<implemented_features>([\s\S]*?)<\/implemented_features>/
|
||||||
|
);
|
||||||
|
|
||||||
|
if (implementedMatch) {
|
||||||
|
const implementedSection = implementedMatch[1];
|
||||||
|
|
||||||
|
// Extract feature names from <name>...</name> tags
|
||||||
|
const nameRegex = /<name>(.*?)<\/name>/g;
|
||||||
|
let match;
|
||||||
|
|
||||||
|
while ((match = nameRegex.exec(implementedSection)) !== null) {
|
||||||
|
features.push(match[1].trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load existing context (app spec and backlog features) to avoid duplicates
|
||||||
|
*/
|
||||||
|
async function loadExistingContext(projectPath: string): Promise<string> {
|
||||||
|
let context = '';
|
||||||
|
|
||||||
|
// 1. Read app_spec.txt for implemented features
|
||||||
|
try {
|
||||||
|
const appSpecPath = getAppSpecPath(projectPath);
|
||||||
|
const specContent = (await secureFs.readFile(appSpecPath, 'utf-8')) as string;
|
||||||
|
|
||||||
|
if (specContent && specContent.trim().length > 0) {
|
||||||
|
const implementedFeatures = extractImplementedFeatures(specContent);
|
||||||
|
|
||||||
|
if (implementedFeatures.length > 0) {
|
||||||
|
context += '\n\n=== ALREADY IMPLEMENTED FEATURES ===\n';
|
||||||
|
context += 'These features are already implemented in the codebase:\n';
|
||||||
|
implementedFeatures.forEach((feature) => {
|
||||||
|
context += `- ${feature}\n`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// app_spec.txt doesn't exist or can't be read - that's okay
|
||||||
|
logger.debug('No app_spec.txt found or error reading it:', error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Load existing features from backlog
|
||||||
|
try {
|
||||||
|
const featureLoader = new FeatureLoader();
|
||||||
|
const features = await featureLoader.getAll(projectPath);
|
||||||
|
|
||||||
|
if (features.length > 0) {
|
||||||
|
context += '\n\n=== EXISTING FEATURES IN BACKLOG ===\n';
|
||||||
|
context += 'These features are already planned or in progress:\n';
|
||||||
|
features.forEach((feature) => {
|
||||||
|
const status = feature.status || 'pending';
|
||||||
|
const title = feature.title || feature.description.substring(0, 50);
|
||||||
|
context += `- ${title} (${status})\n`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// Features directory doesn't exist or can't be read - that's okay
|
||||||
|
logger.debug('No features found or error loading them:', error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JSON Schema for suggestions output
|
* JSON Schema for suggestions output
|
||||||
*/
|
*/
|
||||||
@@ -51,8 +129,13 @@ export async function generateSuggestions(
|
|||||||
performance: 'Analyze this project for performance issues and suggest optimizations.',
|
performance: 'Analyze this project for performance issues and suggest optimizations.',
|
||||||
};
|
};
|
||||||
|
|
||||||
const prompt = `${typePrompts[suggestionType] || typePrompts.features}
|
// Load existing context to avoid duplicates
|
||||||
|
const existingContext = await loadExistingContext(projectPath);
|
||||||
|
|
||||||
|
const prompt = `${typePrompts[suggestionType] || typePrompts.features}
|
||||||
|
${existingContext}
|
||||||
|
|
||||||
|
${existingContext ? '\nIMPORTANT: Do NOT suggest features that are already implemented or already in the backlog above. Focus on NEW ideas that complement what already exists.\n' : ''}
|
||||||
Look at the codebase and provide 3-5 concrete suggestions.
|
Look at the codebase and provide 3-5 concrete suggestions.
|
||||||
|
|
||||||
For each suggestion, provide:
|
For each suggestion, provide:
|
||||||
|
|||||||
Reference in New Issue
Block a user