UNPKG

scai

Version:

> AI-powered CLI tool for commit messages **and** pull request reviews โ€” using local models.

86 lines (85 loc) โ€ข 3.35 kB
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.'); } }