takt/src/features/tasks/list/taskDeleteActions.ts
nrs e52e1da6bf
takt-list (#271)
* refactor: provider/modelの解決ロジックをAgentRunnerに集約

OptionsBuilderでCLIレベルとstepレベルを事前マージしていたのをやめ、
stepProvider/stepModelとして分離して渡す形に変更。
AgentRunnerが全レイヤーの優先度を一括で解決する。

* takt: takt-list
2026-02-14 11:44:01 +09:00

100 lines
3.3 KiB
TypeScript

/**
* Delete actions for pending and failed tasks.
*
* Provides interactive deletion (with confirm prompt)
* for pending/failed tasks in .takt/tasks.yaml.
*/
import { dirname } from 'node:path';
import type { TaskListItem } from '../../../infra/task/index.js';
import { TaskRunner } from '../../../infra/task/index.js';
import { confirm } from '../../../shared/prompt/index.js';
import { success, error as logError } from '../../../shared/ui/index.js';
import { createLogger, getErrorMessage } from '../../../shared/utils/index.js';
import { deleteBranch } from './taskActions.js';
const log = createLogger('list-tasks');
function getProjectDir(task: TaskListItem): string {
return dirname(dirname(task.filePath));
}
function cleanupBranchIfPresent(task: TaskListItem, projectDir: string): boolean {
if (!task.branch) {
return true;
}
return deleteBranch(projectDir, task);
}
/**
* Delete a pending task file.
* Prompts user for confirmation first.
*/
export async function deletePendingTask(task: TaskListItem): Promise<boolean> {
const confirmed = await confirm(`Delete pending task "${task.name}"?`, false);
if (!confirmed) return false;
try {
const runner = new TaskRunner(getProjectDir(task));
runner.deletePendingTask(task.name);
} catch (err) {
const msg = getErrorMessage(err);
logError(`Failed to delete pending task "${task.name}": ${msg}`);
log.error('Failed to delete pending task', { name: task.name, filePath: task.filePath, error: msg });
return false;
}
success(`Deleted pending task: ${task.name}`);
log.info('Deleted pending task', { name: task.name, filePath: task.filePath });
return true;
}
/**
* Delete a failed task directory.
* Prompts user for confirmation first.
*/
export async function deleteFailedTask(task: TaskListItem): Promise<boolean> {
const confirmed = await confirm(`Delete failed task "${task.name}"?`, false);
if (!confirmed) return false;
const projectDir = getProjectDir(task);
try {
if (!cleanupBranchIfPresent(task, projectDir)) {
return false;
}
const runner = new TaskRunner(projectDir);
runner.deleteFailedTask(task.name);
} catch (err) {
const msg = getErrorMessage(err);
logError(`Failed to delete failed task "${task.name}": ${msg}`);
log.error('Failed to delete failed task', { name: task.name, filePath: task.filePath, error: msg });
return false;
}
success(`Deleted failed task: ${task.name}`);
log.info('Deleted failed task', { name: task.name, filePath: task.filePath });
return true;
}
export async function deleteCompletedTask(task: TaskListItem): Promise<boolean> {
const confirmed = await confirm(`Delete completed task "${task.name}"?`, false);
if (!confirmed) return false;
const projectDir = getProjectDir(task);
try {
if (!cleanupBranchIfPresent(task, projectDir)) {
return false;
}
const runner = new TaskRunner(projectDir);
runner.deleteCompletedTask(task.name);
} catch (err) {
const msg = getErrorMessage(err);
logError(`Failed to delete completed task "${task.name}": ${msg}`);
log.error('Failed to delete completed task', { name: task.name, filePath: task.filePath, error: msg });
return false;
}
success(`Deleted completed task: ${task.name}`);
log.info('Deleted completed task', { name: task.name, filePath: task.filePath });
return true;
}