scai
Version:
> **AI-powered CLI for local code analysis, commit message suggestions, and natural-language queries.** 100% local, private, GDPR-friendly, made in Denmark/EU with โค๏ธ.
89 lines (88 loc) โข 3.34 kB
JavaScript
import fs from 'fs/promises';
import path from 'path';
import readline from 'readline';
import { queryFiles } from '../db/fileIndex.js';
import { summaryModule } from '../pipeline/modules/summaryModule.js';
import { detectFileType } from '../fileRules/detectFileType.js';
import { sanitizeQueryForFts } from '../utils/sanitizeQuery.js';
import { styleText } from '../utils/outputFormatter.js';
import { indexFile } from '../daemon/runIndexingBatch.js';
export async function summarizeFile(filepath) {
let content = '';
let filePathResolved;
// ๐ Resolve file path from index or local disk
if (filepath) {
const sanitizedQuery = sanitizeQueryForFts(filepath);
const matches = queryFiles(sanitizedQuery);
if (matches.length > 0) {
const topMatch = matches[0];
filePathResolved = path.resolve(process.cwd(), topMatch.path);
console.log(`๐ Matched file from index: ${path.relative(process.cwd(), filePathResolved)}`);
}
else {
const localPath = path.resolve(process.cwd(), filepath);
try {
await fs.access(localPath);
filePathResolved = localPath;
console.log(`๐ Using local file: ${path.relative(process.cwd(), localPath)}`);
}
catch {
console.error(`โ Could not find or resolve file: "${filepath}"`);
return;
}
}
}
// ๐ Load file content (from path or stdin)
if (filePathResolved) {
const matches = queryFiles(`"${filePathResolved}"`);
const match = matches.find(row => path.resolve(row.path) === filePathResolved);
if (match?.summary) {
console.log(`๐ง Cached summary for ${filepath}:\n`);
console.log(styleText(match.summary));
return;
}
try {
content = await fs.readFile(filePathResolved, 'utf-8');
}
catch (err) {
console.error(`โ Could not read file: ${filePathResolved}\n${err.message}`);
return;
}
}
else if (!process.stdin.isTTY) {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false,
});
for await (const line of rl) {
content += line + '\n';
}
}
else {
console.error('โ No file provided and no piped input.\n๐ Usage: scai summ <file> or cat file | scai summ');
return;
}
// ๐ง Generate summary and save
if (content.trim()) {
console.log('๐งช Generating summary...\n');
const response = await summaryModule.run({
query: `Summarize file: ${filepath ?? 'stdin'}`,
content,
});
const summary = response.data?.summary;
if (!summary) {
console.warn('โ ๏ธ No summary generated.');
return;
}
console.log(styleText(summary));
if (filePathResolved) {
const fileType = detectFileType(filePathResolved);
indexFile(filePathResolved, summary, fileType);
console.log('๐พ Summary saved to local database.');
}
}
else {
console.error('โ No content provided to summarize.');
}
}