From efa9a3eeeb6dc16df3cd2254f129e3046e99f95b Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Tue, 3 Feb 2026 07:57:01 +0000 Subject: [PATCH] Add CLI commands (create, list, status, merge, destroy, diff) --- .src/commands/status.ts | 126 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 .src/commands/status.ts diff --git a/.src/commands/status.ts b/.src/commands/status.ts new file mode 100644 index 0000000..03f3d94 --- /dev/null +++ b/.src/commands/status.ts @@ -0,0 +1,126 @@ +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('?'); + } +}