Skip to main content
Glama
abort.command.ts3.06 kB
/** * @fileoverview Abort Command - Safely terminate workflow */ import { createTmCore } from '@tm/core'; import { Command } from 'commander'; import inquirer from 'inquirer'; import { getProjectRoot } from '../../utils/project-root.js'; import { AutopilotBaseOptions, OutputFormatter } from './shared.js'; interface AbortOptions extends AutopilotBaseOptions { force?: boolean; } /** * Abort Command - Safely terminate workflow and clean up state */ export class AbortCommand extends Command { constructor() { super('abort'); this.description('Abort the current TDD workflow and clean up state') .option('-f, --force', 'Force abort without confirmation') .action(async (options: AbortOptions) => { await this.execute(options); }); } private async execute(options: AbortOptions): Promise<void> { // Inherit parent options const parentOpts = this.parent?.opts() as AutopilotBaseOptions; // Initialize mergedOptions with defaults (projectRoot will be set in try block) let mergedOptions: AbortOptions = { ...parentOpts, ...options, projectRoot: '' // Will be set in try block }; const formatter = new OutputFormatter( options.json || parentOpts?.json || false ); try { // Resolve project root inside try block to catch any errors const projectRoot = getProjectRoot( options.projectRoot || parentOpts?.projectRoot ); // Update mergedOptions with resolved project root mergedOptions = { ...mergedOptions, projectRoot }; // Initialize TmCore facade const tmCore = await createTmCore({ projectPath: projectRoot }); // Check if workflow exists if (!(await tmCore.workflow.hasWorkflow())) { formatter.warning('No active workflow to abort'); return; } // Resume workflow to get status await tmCore.workflow.resume(); const status = tmCore.workflow.getStatus(); // Confirm abort if not forced or in JSON mode if (!mergedOptions.force && !mergedOptions.json) { const { confirmed } = await inquirer.prompt([ { type: 'confirm', name: 'confirmed', message: `This will abort the workflow for task ${status.taskId}. ` + `Progress: ${status.progress?.completed || 0}/${status.progress?.total || 0} subtasks completed. ` + `Continue?`, default: false } ]); if (!confirmed) { formatter.info('Abort cancelled'); return; } } // Abort workflow (cleans up state internally) await tmCore.workflow.abort(); // Output result formatter.success('Workflow aborted', { taskId: status.taskId, branchName: status.branchName, progress: status.progress, lastSubtask: status.currentSubtask ? { id: status.currentSubtask.id, title: status.currentSubtask.title } : null, note: 'Branch and commits remain. Clean up manually if needed.' }); } catch (error) { formatter.error((error as Error).message); if (mergedOptions.verbose) { console.error((error as Error).stack); } process.exit(1); } } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/eyaltoledano/claude-task-master'

If you have feedback or need assistance with the MCP directory API, please join our Discord server