diff --git a/src/cli.ts b/src/cli.ts index ab5abbc..d2b059f 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -47,7 +47,36 @@ import { debugResponse, debugValidation, } from "./debug.js"; -import type { Config, BackendType } from "./types.js"; +import type { Config, BackendType, DiffResult } from "./types.js"; + +function buildDiffContext(diffResult: DiffResult): string { + const parts: string[] = []; + + if (diffResult.filesAdded.length > 0) { + parts.push(`Files added:\n${diffResult.filesAdded.slice(0, 5).join("\n")}`); + if (diffResult.filesAdded.length > 5) { + parts.push(` ... and ${diffResult.filesAdded.length - 5} more added`); + } + } + + if (diffResult.filesDeleted.length > 0) { + parts.push(`Files deleted:\n${diffResult.filesDeleted.slice(0, 5).join("\n")}`); + if (diffResult.filesDeleted.length > 5) { + parts.push(` ... and ${diffResult.filesDeleted.length - 5} more deleted`); + } + } + + if (diffResult.filesModified.length > 0) { + parts.push(`Files modified:\n${diffResult.filesModified.slice(0, 5).join("\n")}`); + if (diffResult.filesModified.length > 5) { + parts.push(` ... and ${diffResult.filesModified.length - 5} more modified`); + } + } + + parts.push(`Stats: ${diffResult.stats}`); + + return parts.join("\n"); +} async function promptUser(question: string, choices: string[]): Promise { const rl = createInterface({ @@ -235,7 +264,7 @@ async function handleSingleCommit( } debugDiff(diff, diffResult.files); - const context = `Files changed:\n${diffResult.files.slice(0, 5).join("\n")}\nStats: ${diffResult.stats}`; + const context = buildDiffContext(diffResult); let message = await runCommitFlow(backend, cfg, diff, context, options.skipConfirm, options.constraints); @@ -322,7 +351,7 @@ async function handleIndividualCommits( console.log(chalk.bold(`\nProcessing: ${filePath}`)); - const context = `File: ${filePath}\nStats: ${diffResult.stats}`; + const context = buildDiffContext(diffResult); let message = await runCommitFlow(backend, cfg, diffResult.diff, context, options.skipConfirm, options.constraints); if (message === null) { @@ -487,7 +516,7 @@ export function createProgram(): Command { diff = filterDiffByPatterns(diff, cfg.ignore_patterns); } - const context = `Files changed:\n${diffResult.files.slice(0, 5).join("\n")}\nStats: ${diffResult.stats}`; + const context = buildDiffContext(diffResult); const temperatures = [cfg.temperature, ...cfg.retry_temperatures]; const message = await generateMessage(backend, diff, context, temperatures, constraints); @@ -658,7 +687,7 @@ export function createProgram(): Command { console.log(` ... and ${diffResult.files.length - 10} more`); } - const context = `Files changed: ${diffResult.files.slice(0, 5).join(", ")}\nStats: ${diffResult.stats}`; + const context = buildDiffContext(diffResult); const prompt = buildSummarizePrompt(diffResult.diff, context); debugPrompt(prompt); diff --git a/src/git.ts b/src/git.ts index cf1aad4..354bfdf 100644 --- a/src/git.ts +++ b/src/git.ts @@ -86,10 +86,31 @@ export function getStagedDiff(): DiffResult { const filesOutput = runGitSafe("diff", "--cached", "--name-only"); const files = filesOutput.split("\n").filter((f) => f); + // Get file status (A=added, D=deleted, M=modified, R=renamed) + const statusOutput = runGitSafe("diff", "--cached", "--name-status"); + const filesAdded: string[] = []; + const filesDeleted: string[] = []; + const filesModified: string[] = []; + + statusOutput.split("\n").filter((f) => f).forEach((line) => { + const [status, ...pathParts] = line.split("\t"); + const filePath = pathParts.join("\t"); // Handle filenames with tabs + if (status.startsWith("A")) { + filesAdded.push(filePath); + } else if (status.startsWith("D")) { + filesDeleted.push(filePath); + } else if (status.startsWith("M") || status.startsWith("R")) { + filesModified.push(filePath); + } + }); + return { diff, stats, files, + filesAdded, + filesDeleted, + filesModified, isEmpty: !diff.trim(), }; } @@ -99,10 +120,30 @@ export function getFileDiff(filePath: string): DiffResult { const stats = runGitSafe("diff", "--cached", "--stat", "--", filePath); const files = diff ? [filePath] : []; + // Get file status for this specific file + const statusOutput = runGitSafe("diff", "--cached", "--name-status", "--", filePath); + const filesAdded: string[] = []; + const filesDeleted: string[] = []; + const filesModified: string[] = []; + + if (statusOutput) { + const [status] = statusOutput.split("\t"); + if (status.startsWith("A")) { + filesAdded.push(filePath); + } else if (status.startsWith("D")) { + filesDeleted.push(filePath); + } else if (status.startsWith("M") || status.startsWith("R")) { + filesModified.push(filePath); + } + } + return { diff, stats, files, + filesAdded, + filesDeleted, + filesModified, isEmpty: !diff.trim(), }; } @@ -185,10 +226,31 @@ export function getLastCommitDiff(): DiffResult { const filesOutput = runGitSafe("diff", "HEAD~1", "HEAD", "--name-only"); const files = filesOutput.split("\n").filter((f) => f); + // Get file status for the last commit + const statusOutput = runGitSafe("diff", "HEAD~1", "HEAD", "--name-status"); + const filesAdded: string[] = []; + const filesDeleted: string[] = []; + const filesModified: string[] = []; + + statusOutput.split("\n").filter((f) => f).forEach((line) => { + const [status, ...pathParts] = line.split("\t"); + const filePath = pathParts.join("\t"); + if (status.startsWith("A")) { + filesAdded.push(filePath); + } else if (status.startsWith("D")) { + filesDeleted.push(filePath); + } else if (status.startsWith("M") || status.startsWith("R")) { + filesModified.push(filePath); + } + }); + return { diff, stats, files, + filesAdded, + filesDeleted, + filesModified, isEmpty: !diff.trim(), }; } diff --git a/src/types.ts b/src/types.ts index f047d04..3d42cae 100644 --- a/src/types.ts +++ b/src/types.ts @@ -17,6 +17,9 @@ export interface DiffResult { diff: string; stats: string; files: string[]; + filesAdded: string[]; + filesDeleted: string[]; + filesModified: string[]; isEmpty: boolean; }