scai
Version:
> AI-powered CLI tool for commit messages **and** pull request reviews โ using local models.
86 lines (85 loc) โข 3.35 kB
JavaScript
import fs from 'fs/promises';
import path from 'path';
import readline from 'readline';
import { queryFiles, indexFile } from '../db/fileIndex.js';
import { summaryModule } from '../pipeline/modules/summaryModule.js';
import { styleOutput } from '../utils/summarizer.js';
import { detectFileType } from '../fileRules/detectFileType.js';
import { generateEmbedding } from '../lib/generateEmbedding.js';
import { sanitizeQueryForFts } from '../utils/sanitizeQuery.js';
import { getDbForRepo } from '../db/client.js';
export async function summarizeFile(filepath) {
let content = '';
let filePathResolved;
// ๐ Resolve path like `scai find`
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: ${path.relative(process.cwd(), filePathResolved)}`);
}
else {
console.error(`โ Could not resolve file from query: "${filepath}"`);
return;
}
}
// ๐ Load file content from resolved path
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(styleOutput(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({ content, filepath });
if (!response.summary) {
console.warn('โ ๏ธ No summary generated.');
return;
}
console.log(styleOutput(response.summary));
if (filePathResolved) {
const fileType = detectFileType(filePathResolved);
indexFile(filePathResolved, response.summary, fileType);
console.log('๐พ Summary saved to local database.');
const embedding = await generateEmbedding(response.summary);
if (embedding) {
const db = getDbForRepo();
db.prepare(`
UPDATE files SET embedding = ? WHERE path = ?
`).run(JSON.stringify(embedding), filePathResolved.replace(/\\/g, '/'));
console.log('๐ Embedding saved to database.');
}
}
}
else {
console.error('โ No content provided to summarize.');
}
}