From 9c5dc1bda23c4fce8aa1a33e1fd0fc0b453ff81f Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Tue, 3 Feb 2026 09:04:39 +0000 Subject: [PATCH] feat: add diff command --- src/commands/diff.ts | 168 +++++++++++-------------------------------- 1 file changed, 43 insertions(+), 125 deletions(-) diff --git a/src/commands/diff.ts b/src/commands/diff.ts index dfff819..194c810 100644 --- a/src/commands/diff.ts +++ b/src/commands/diff.ts @@ -1,141 +1,59 @@ -import * as path from 'path'; import { Command } from 'commander'; import chalk from 'chalk'; -import { - getWorkspacePath, - loadWorkspaceConfig, - sanitizeAgentName -} from '../utils/file-utils'; -import { - generateDiff, - createGit, - getCurrentBranch -} from '../utils/git-utils'; -import { DiffLine } from '../types/index'; -import { - formatDiffAsMarkdown, - formatDiffAsJson, - formatDiffAsText, - exportDiffToFile, - generateShortDiffSummary -} from '../utils/diff-utils'; +import { getWorkspacePath, loadWorkspaceConfig, sanitizeAgentName } from '../utils/file-utils'; +import { generateDiff, createGit, getCurrentBranch } from '../utils/git-utils'; +import { formatDiffAsMarkdown, generateShortDiffSummary } from '../utils/diff-utils'; import { GitAgentSyncError, WorkspaceNotFoundError } from '../utils/errors'; export function createDiffCommand(): Command { - const cmd = new Command('diff') - .description('Generate unified diffs for code review') - .argument('[agent-name]', 'Agent name (defaults to current workspace)') - .option('-o, --output ', 'Export diff to file') - .option('--short', 'Show short summary only') - .option('--json', 'Output as JSON') - .option('--text', 'Output as plain text') - .option('--compare ', 'Compare to a specific branch (default: main)') - .action(async (agentName, options) => { - try { - const currentPath = process.cwd(); - let workspacePath: string; - let targetAgentName: string; - - if (agentName) { - targetAgentName = sanitizeAgentName(agentName); - workspacePath = getWorkspacePath(currentPath, targetAgentName); - } else { - const workspaceResult = await detectCurrentWorkspace(currentPath); - workspacePath = workspaceResult.path; - targetAgentName = workspaceResult.agentName; - } - - const config = await loadWorkspaceConfig(workspacePath); - if (!config) { - throw new WorkspaceNotFoundError(targetAgentName); - } - - const compareBranch = options.compare || config.mainBranch; - const diffResult = await generateDiff(currentPath, workspacePath, targetAgentName, compareBranch); - - if (options.short) { - const summary = generateShortDiffSummary(diffResult); - console.log(chalk.white(`${targetAgentName}: ${summary}`)); - return; - } - - if (options.json) { - console.log(formatDiffAsJson(diffResult)); - return; - } - - if (options.text) { - console.log(formatDiffAsText(diffResult)); - return; - } - - if (options.output) { - await exportDiffToFile(diffResult, options.output, 'markdown'); - console.log(chalk.green(`\nāœ“ Diff exported to ${options.output}`)); - return; - } - - console.log(chalk.cyan(`\nšŸ“ Diff: ${targetAgentName}`)); - console.log(chalk.gray(`Branch: ${diffResult.branch} → ${diffResult.comparedBranch}`)); - console.log(chalk.gray('─'.repeat(60))); - - if (diffResult.files.length === 0) { - console.log(chalk.yellow('\n No differences found.')); - return; - } - - console.log(chalk.cyan('\nšŸ“Š Summary:')); - console.log(` Files: ${chalk.white(diffResult.summary.filesChanged)}`); - console.log(` Additions: ${chalk.green(`+${diffResult.summary.additions}`)}`); - console.log(` Deletions: ${chalk.red(`-${diffResult.summary.deletions}`)}`)); - console.log(chalk.gray('─'.repeat(60))); - - for (const file of diffResult.files) { - console.log(chalk.cyan(`\nšŸ“„ ${file.file}`)); - console.log(` +${file.additions} / -${file.deletions}`); - - const relevantChanges = file.changes.filter((c: DiffLine) => c.type !== 'context').slice(0, 20); - - if (relevantChanges.length > 0) { - console.log(' Preview:'); - for (const line of relevantChanges) { - if (line.type === 'added') { - console.log(` ${chalk.green(line.content)}`); - } else if (line.type === 'deleted') { - console.log(` ${chalk.red(line.content)}`); - } - } - - if (file.changes.filter((c: DiffLine) => c.type !== 'context').length > 20) { - console.log(` ${chalk.gray('... and more changes (use --output to see full diff)')}`); - } - } - } - - console.log(chalk.cyan('\nšŸ’” Use --output to export full diff to a file')); - - } catch (error) { - const gitError = error instanceof GitAgentSyncError ? error : new GitAgentSyncError(String(error)); - console.error(chalk.red(`\nāŒ Error: ${gitError.message}`)); - process.exit(1); + const cmd = new Command('diff').description('Generate unified diffs for code review').argument('[agent-name]', 'Agent name').option('-o, --output ', 'Export diff to file').option('--short', 'Show short summary only').option('--json', 'Output as JSON').option('--compare ', 'Compare to a specific branch').action(async (agentName, options) => { + try { + const currentPath = process.cwd(); + let workspacePath: string; + let targetAgentName: string; + if (agentName) { + targetAgentName = sanitizeAgentName(agentName); + workspacePath = getWorkspacePath(currentPath, targetAgentName); + } else { + const result = await detectCurrentWorkspace(currentPath); + workspacePath = result.path; + targetAgentName = result.agentName; } - }); - + const config = await loadWorkspaceConfig(workspacePath); + if (!config) throw new WorkspaceNotFoundError(targetAgentName); + const compareBranch = options.compare || config.mainBranch; + const diffResult = await generateDiff(currentPath, workspacePath, targetAgentName, compareBranch); + if (options.short) { console.log(chalk.white(`${targetAgentName}: ${generateShortDiffSummary(diffResult)}`)); return; } + if (options.json) { console.log(JSON.stringify(diffResult, null, 2)); return; } + if (options.output) { await exportDiffToFile(diffResult, options.output); console.log(chalk.green(`\nāœ“ Diff exported to ${options.output}`)); return; } + console.log(chalk.cyan(`\nšŸ“ Diff: ${targetAgentName}`)); + console.log(chalk.gray(`Branch: ${diffResult.branch} → ${diffResult.comparedBranch}`)); + console.log(chalk.gray('─'.repeat(60))); + if (diffResult.files.length === 0) { console.log(chalk.yellow('\n No differences found.')); return; } + console.log(chalk.cyan('\nšŸ“Š Summary:')); + console.log(` Files: ${chalk.white(diffResult.summary.filesChanged)}`); + console.log(` Additions: ${chalk.green(`+${diffResult.summary.additions}`)}`); + console.log(` Deletions: ${chalk.red(`-${diffResult.summary.deletions}`)}`); + } catch (error) { + const gitError = error instanceof GitAgentSyncError ? error : new GitAgentSyncError(String(error)); + console.error(chalk.red(`\nāŒ Error: ${gitError.message}`)); + process.exit(1); + } + }); return cmd; } async function detectCurrentWorkspace(currentPath: string): Promise<{ path: string; agentName: string }> { const git = createGit(currentPath); const branch = await getCurrentBranch(git); - if (branch.startsWith('agent-')) { const agentName = branch.replace(/^agent-/, ''); - const { getWorkspacePath } = await import('../utils/file-utils'); - return { - agentName, - path: getWorkspacePath(currentPath, agentName) - }; + return { agentName, path: getWorkspacePath(currentPath, agentName) }; } - - throw new GitAgentSyncError('Not in an agent workspace. Please specify an agent name.'); + throw new GitAgentSyncError('Not in an agent workspace.'); } + +async function exportDiffToFile(diffResult: any, outputPath: string): Promise { + const { exportDiffToFile: exportFn } = require('../utils/diff-utils'); + await exportFn(diffResult, outputPath, 'markdown'); +} \ No newline at end of file