import * as path from 'path'; import { Command } from 'commander'; import chalk from 'chalk'; import { getWorkspacePath, loadWorkspaceConfig, sanitizeAgentName } from '../utils/file-utils'; import { getWorktreeStatus, createGit, getCurrentBranch } from '../utils/git-utils'; import { formatChangesForReview, generateShortDiffSummary } from '../utils/diff-utils'; import { DiffResult } from '../types/index'; import { GitAgentSyncError, WorkspaceNotFoundError } from '../utils/errors'; export function createStatusCommand(): Command { const cmd = new Command('status') .alias('st') .description('Show detailed changes for a specific agent workspace') .argument('[agent-name]', 'Agent name (defaults to current workspace if in one)') .option('--short', 'Show short summary only') .option('--output ', 'Export to file') .action(async (agentName, options) => { try { const currentPath = process.cwd(); let workspacePath: string; if (agentName) { const sanitizedName = sanitizeAgentName(agentName); workspacePath = getWorkspacePath(currentPath, sanitizedName); } else { workspacePath = await detectCurrentWorkspace(currentPath); } const config = await loadWorkspaceConfig(workspacePath); if (!config) { throw new WorkspaceNotFoundError(agentName || 'current'); } const status = await getWorktreeStatus(workspacePath); if (options.short) { const diffResult: DiffResult = { agentName: config.agentName, branch: status.branch, comparedBranch: '', files: [], summary: { filesChanged: status.changes.length, additions: 0, deletions: 0 } }; const summary = generateShortDiffSummary(diffResult); console.log(chalk.white(`${config.agentName}: ${summary}`)); return; } const reviewContent = formatChangesForReview(workspacePath, status.changes, config.agentName); if (options.output) { const fs = await import('fs-extra'); await fs.writeFile(options.output, reviewContent, 'utf-8'); console.log(chalk.green(`\nāœ“ Status exported to ${options.output}`)); } else { console.log(chalk.cyan(`\nšŸ“Š Agent: ${config.agentName}`)); console.log(chalk.gray('─'.repeat(60))); console.log(` Branch: ${chalk.white(status.branch)}`); console.log(` Path: ${chalk.white(workspacePath)}`); console.log(` Changes: ${chalk.white(status.uncommittedCount.toString())}`); console.log(` Last Updated: ${chalk.white(new Date(status.lastUpdated).toLocaleString())}`); console.log(chalk.gray('─'.repeat(60))); if (status.changes.length === 0) { console.log(chalk.yellow('\n No changes detected.')); } else { console.log(chalk.cyan('\nšŸ“ Changed Files:')); for (const change of status.changes) { const statusIcon = getStatusIcon(change.status); const stagedBadge = change.staged ? chalk.green('[staged]') : ''; console.log(` ${statusIcon} ${chalk.white(change.file)} ${stagedBadge}`); } } } } 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 { const git = createGit(currentPath); const branch = await getCurrentBranch(git); if (branch.startsWith('agent-')) { const agentName = branch.replace(/^agent-/, ''); return getWorkspacePath(currentPath, agentName); } throw new GitAgentSyncError('Not in an agent workspace. Please specify an agent name.'); } function getStatusIcon(status: string): string { switch (status) { case 'added': return chalk.green('✚'); case 'modified': return chalk.yellow('āœŽ'); case 'deleted': return chalk.red('āœ–'); case 'renamed': return chalk.cyan('↔'); default: return chalk.gray('?'); } }