This commit is contained in:
@@ -1,141 +1,59 @@
|
|||||||
import * as path from 'path';
|
|
||||||
import { Command } from 'commander';
|
import { Command } from 'commander';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import {
|
import { getWorkspacePath, loadWorkspaceConfig, sanitizeAgentName } from '../utils/file-utils';
|
||||||
getWorkspacePath,
|
import { generateDiff, createGit, getCurrentBranch } from '../utils/git-utils';
|
||||||
loadWorkspaceConfig,
|
import { formatDiffAsMarkdown, generateShortDiffSummary } from '../utils/diff-utils';
|
||||||
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 { GitAgentSyncError, WorkspaceNotFoundError } from '../utils/errors';
|
import { GitAgentSyncError, WorkspaceNotFoundError } from '../utils/errors';
|
||||||
|
|
||||||
export function createDiffCommand(): Command {
|
export function createDiffCommand(): Command {
|
||||||
const cmd = new Command('diff')
|
const cmd = new Command('diff').description('Generate unified diffs for code review').argument('[agent-name]', 'Agent name').option('-o, --output <file>', 'Export diff to file').option('--short', 'Show short summary only').option('--json', 'Output as JSON').option('--compare <branch>', 'Compare to a specific branch').action(async (agentName, options) => {
|
||||||
.description('Generate unified diffs for code review')
|
try {
|
||||||
.argument('[agent-name]', 'Agent name (defaults to current workspace)')
|
const currentPath = process.cwd();
|
||||||
.option('-o, --output <file>', 'Export diff to file')
|
let workspacePath: string;
|
||||||
.option('--short', 'Show short summary only')
|
let targetAgentName: string;
|
||||||
.option('--json', 'Output as JSON')
|
if (agentName) {
|
||||||
.option('--text', 'Output as plain text')
|
targetAgentName = sanitizeAgentName(agentName);
|
||||||
.option('--compare <branch>', 'Compare to a specific branch (default: main)')
|
workspacePath = getWorkspacePath(currentPath, targetAgentName);
|
||||||
.action(async (agentName, options) => {
|
} else {
|
||||||
try {
|
const result = await detectCurrentWorkspace(currentPath);
|
||||||
const currentPath = process.cwd();
|
workspacePath = result.path;
|
||||||
let workspacePath: string;
|
targetAgentName = result.agentName;
|
||||||
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 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;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function detectCurrentWorkspace(currentPath: string): Promise<{ path: string; agentName: string }> {
|
async function detectCurrentWorkspace(currentPath: string): Promise<{ path: string; agentName: string }> {
|
||||||
const git = createGit(currentPath);
|
const git = createGit(currentPath);
|
||||||
const branch = await getCurrentBranch(git);
|
const branch = await getCurrentBranch(git);
|
||||||
|
|
||||||
if (branch.startsWith('agent-')) {
|
if (branch.startsWith('agent-')) {
|
||||||
const agentName = branch.replace(/^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.');
|
||||||
throw new GitAgentSyncError('Not in an agent workspace. Please specify an agent name.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function exportDiffToFile(diffResult: any, outputPath: string): Promise<void> {
|
||||||
|
const { exportDiffToFile: exportFn } = require('../utils/diff-utils');
|
||||||
|
await exportFn(diffResult, outputPath, 'markdown');
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user