UNPKG

sourcesailor

Version:

A CLI tool for analyzing and documenting codebases

101 lines (100 loc) 4.01 kB
import path from 'path'; import { getAnalysis, readConfig, writeAnalysis } from '../utils.mjs'; import ModelUtils from "../modelUtils.mjs"; import ora from "ora"; import chalk from "chalk"; import { confirm } from '@inquirer/prompts'; import { handler as setExpertiseHandler } from './setExpertise.mjs'; export const command = 'prepareReport <path|p> [verbose|v] [streaming|s]'; export const describe = 'Prepare a report based on the analysis'; export function builder(yargs) { yargs.positional('path', { alias: 'p', describe: 'Path to the analysis', type: 'string', }); yargs.option('verbose', { alias: 'v', describe: 'Verbose output', type: 'boolean', }); yargs.option('streaming', { alias: 's', describe: 'Stream the output to a file', type: 'boolean', }); yargs.option('model', { alias: 'm', describe: 'Specify the AI model to use for report generation', type: 'string' }); return yargs; } export async function handler(argv) { const isVerbose = argv.verbose || argv.v || false; const allowStreaming = argv.streaming || argv.s || false; const projectDir = argv.path || argv.p; const modelName = argv.model || argv.m; const config = readConfig(); const modelUtils = ModelUtils.getInstance(); await modelUtils.initializeModels(); const llmInterface = modelUtils.getLlmInterface(modelName || config.DEFAULT_OPENAI_MODEL); const rootDir = config.ANALYSIS_DIR; const selectedModelName = modelName || config.DEFAULT_OPENAI_MODEL; const userExpertise = JSON.stringify(config.userExpertise); if (isVerbose) { console.log(`Using model: ${selectedModelName}`); } // Handle current directory case const isCurrentDir = projectDir === '.'; const projectName = isCurrentDir ? process.cwd().split('/').pop() ?? "" : projectDir; const isProjectRoot = rootDir === 'p'; const dirPath = isProjectRoot ? projectDir : path.join(rootDir, '.SourceSailor', projectName); if (isVerbose) { console.log({ dirPath, isProjectRoot, projectDir }); } const spinner = ora('Preparing report').start(); const analysis = getAnalysis(dirPath, isProjectRoot); if (isVerbose) { console.log({ analysis: Object.keys(analysis) }); } if (!analysis || Object.keys(analysis).length === 0) { spinner.fail('No analysis found, Please run analyse command first'); return; } const directoryStructure = analysis.directoryStructure; const dependencyInference = analysis.dependencyInference; const codeInference = analysis.codeInferrence; if (isVerbose) { console.log({ directoryStructure, dependencyInference, codeInference }); } const report = await llmInterface.generateReadme(directoryStructure, dependencyInference, codeInference, allowStreaming, isVerbose, userExpertise, selectedModelName); if (report) { let readmeResponse = ""; if (allowStreaming) { spinner.stop().clear(); for await (const chunk of report) { process.stdout.write(chunk); readmeResponse += chunk; } process.stdout.write("\n"); } else { const reportAsText = report; spinner.stopAndPersist({ symbol: '✔️', text: reportAsText }); readmeResponse = reportAsText; } writeAnalysis(dirPath, "inferredReadme", readmeResponse, isProjectRoot); } if (!config.userExpertise) { console.log(chalk.yellow("User expertise is not set. Setting your expertise level will help us provide more tailored reports.")); const setExpertise = await confirm({ message: "Would you like to set your expertise now?", default: true }); if (setExpertise) { await setExpertiseHandler(); } } } export const usage = '$0 <cmd> [args]'; export const aliases = ['h', 'help'];