fix: resolve CI test failures
Some checks failed
CI / test (push) Has been cancelled

This commit is contained in:
2026-02-01 01:36:32 +00:00
parent b7ea702c75
commit 3a345b72e2

View File

@@ -0,0 +1,192 @@
import * as fs from 'fs';
import * as path from 'path';
import yaml from 'js-yaml';
import {
ContextOutput,
TemplateContext,
OutputFormat,
TemplateType,
ConfigOptions
} from '../types';
import { getProjectInfo } from '../analyzers/projectTypeDetector';
import { analyzeDependencies } from '../analyzers/dependencyAnalyzer';
import { extractConventions } from '../analyzers/conventionExtractor';
import { getAllFiles } from '../utils/fileUtils';
import { formatContextForAI } from '../templates/templateLoader';
import { loadConfig } from '../config/configLoader';
const SOURCE_DIR_PATTERNS = ['src/', 'lib/', 'app/', 'packages/', 'internal/'];
const TEST_DIR_PATTERNS = ['test/', 'tests/', '__tests__/', 'spec/', 'specs/'];
export async function generateContext(
directory: string,
options?: Partial<ConfigOptions>
): Promise<ContextOutput> {
const config = loadConfig(undefined, directory);
const mergedOptions = { ...config, ...options };
const projectInfo = await getProjectInfo(directory);
const dependencyAnalysis = await analyzeDependencies(directory, projectInfo.type);
const conventions = await extractConventions(directory, projectInfo.type);
const fileStructure = await analyzeFileStructure(directory, mergedOptions);
const context: ContextOutput = {
version: '1.0.0',
generatedAt: new Date().toISOString(),
project: projectInfo,
dependencies: dependencyAnalysis,
conventions,
structure: fileStructure,
config: mergedOptions
};
return context;
}
export async function generateFormattedContext(
directory: string,
format: OutputFormat = 'yaml',
_templateType: TemplateType = 'generic',
options?: Partial<ConfigOptions>
): Promise<string> {
const context = await generateContext(directory, options);
if (format === 'yaml') {
return yaml.dump(context, { indent: 2, lineWidth: -1, noRefs: true });
}
return JSON.stringify(context, null, 2);
}
export async function generateAIContext(
directory: string,
templateType: TemplateType = 'generic',
options?: Partial<ConfigOptions>
): Promise<string> {
const context = await generateContext(directory, options);
const templateContext: TemplateContext = {
projectInfo: context.project,
dependencyAnalysis: context.dependencies,
conventions: context.conventions,
fileStructure: context.structure
};
return formatContextForAI(templateContext, templateType);
}
export function saveContext(
output: string,
content: string,
format: OutputFormat
): boolean {
try {
if (output === '-' || output === 'stdout') {
console.log(content);
return true;
}
let finalContent = content;
if (format === 'yaml' && !output.endsWith('.yaml') && !output.endsWith('.yml')) {
finalContent = '# YAML format context\n' + content;
}
fs.writeFileSync(output, finalContent, 'utf-8');
return true;
} catch {
return false;
}
}
async function analyzeFileStructure(
directory: string,
options: ConfigOptions
) {
const allFiles = getAllFiles(directory, 5);
const directories = new Set<string>();
const sourceDirectories = new Set<string>();
const testDirectories = new Set<string>();
const keyFiles: string[] = [];
for (const file of allFiles) {
if (file.endsWith('/')) {
const relativePath = path.relative(directory, file);
if (relativePath) {
directories.add(relativePath);
for (const pattern of SOURCE_DIR_PATTERNS) {
if (relativePath.startsWith(pattern)) {
sourceDirectories.add(relativePath);
break;
}
}
for (const pattern of TEST_DIR_PATTERNS) {
if (relativePath.startsWith(pattern)) {
testDirectories.add(relativePath);
break;
}
}
}
} else {
const shouldInclude = options.includes.some(pattern => {
if (pattern.startsWith('**')) return true;
if (pattern.startsWith('*')) return pattern.endsWith(path.extname(file));
return true;
});
const shouldExclude = options.excludes.some(pattern => {
if (pattern.endsWith('**')) {
return file.includes(pattern.slice(0, -3));
}
return file.endsWith(pattern.replace('*', ''));
});
if (shouldInclude && !shouldExclude) {
const relativePath = path.relative(directory, file);
keyFiles.push(relativePath);
}
}
}
const sortedKeyFiles = keyFiles
.sort((a, b) => {
const aDepth = a.split('/').length;
const bDepth = b.split('/').length;
if (aDepth !== bDepth) return aDepth - bDepth;
return a.localeCompare(b);
})
.slice(0, 50);
return {
totalFiles: allFiles.filter(f => !f.endsWith('/')).length,
directories: Array.from(directories).sort(),
keyFiles: sortedKeyFiles,
sourceDirectories: Array.from(sourceDirectories).sort(),
testDirectories: Array.from(testDirectories).sort()
};
}
export async function validateContext(context: ContextOutput): Promise<boolean> {
if (!context.version) {
console.error('Error: Context missing version');
return false;
}
if (!context.project) {
console.error('Error: Context missing project info');
return false;
}
if (!context.generatedAt) {
console.error('Error: Context missing generatedAt timestamp');
return false;
}
return true;
}