116 lines
3.1 KiB
TypeScript
116 lines
3.1 KiB
TypeScript
/**
|
|
* /add-task command implementation
|
|
*
|
|
* Creates a new task file in .takt/tasks/ with YAML format.
|
|
* Supports worktree and branch options.
|
|
*/
|
|
|
|
import * as fs from 'node:fs';
|
|
import * as path from 'node:path';
|
|
import { stringify as stringifyYaml } from 'yaml';
|
|
import { promptInput, confirm } from '../prompt/index.js';
|
|
import { success, info, error } from '../utils/ui.js';
|
|
import { slugify } from '../utils/slug.js';
|
|
import { createLogger } from '../utils/debug.js';
|
|
import type { TaskFileData } from '../task/schema.js';
|
|
|
|
const log = createLogger('add-task');
|
|
|
|
/**
|
|
* Generate a unique task filename
|
|
*/
|
|
function generateFilename(tasksDir: string, taskContent: string): string {
|
|
const slug = slugify(taskContent);
|
|
const base = slug || 'task';
|
|
let filename = `${base}.yaml`;
|
|
let counter = 1;
|
|
|
|
while (fs.existsSync(path.join(tasksDir, filename))) {
|
|
filename = `${base}-${counter}.yaml`;
|
|
counter++;
|
|
}
|
|
|
|
return filename;
|
|
}
|
|
|
|
/**
|
|
* /add-task command handler
|
|
*
|
|
* Usage:
|
|
* takt /add-task "タスク内容" # Quick add (no worktree)
|
|
* takt /add-task # Interactive mode
|
|
*/
|
|
export async function addTask(cwd: string, args: string[]): Promise<void> {
|
|
const tasksDir = path.join(cwd, '.takt', 'tasks');
|
|
fs.mkdirSync(tasksDir, { recursive: true });
|
|
|
|
let taskContent: string;
|
|
let worktree: boolean | string | undefined;
|
|
let branch: string | undefined;
|
|
let workflow: string | undefined;
|
|
|
|
if (args.length > 0) {
|
|
// Argument mode: task content provided directly
|
|
taskContent = args.join(' ');
|
|
} else {
|
|
// Interactive mode
|
|
const input = await promptInput('Task content');
|
|
if (!input) {
|
|
info('Cancelled.');
|
|
return;
|
|
}
|
|
taskContent = input;
|
|
}
|
|
|
|
// Ask about worktree
|
|
const useWorktree = await confirm('Create worktree?', false);
|
|
if (useWorktree) {
|
|
const customPath = await promptInput('Worktree path (Enter for auto)');
|
|
worktree = customPath || true;
|
|
|
|
// Ask about branch
|
|
const customBranch = await promptInput('Branch name (Enter for auto)');
|
|
if (customBranch) {
|
|
branch = customBranch;
|
|
}
|
|
}
|
|
|
|
// Ask about workflow
|
|
const customWorkflow = await promptInput('Workflow name (Enter for default)');
|
|
if (customWorkflow) {
|
|
workflow = customWorkflow;
|
|
}
|
|
|
|
// Build task data
|
|
const taskData: TaskFileData = { task: taskContent };
|
|
if (worktree !== undefined) {
|
|
taskData.worktree = worktree;
|
|
}
|
|
if (branch) {
|
|
taskData.branch = branch;
|
|
}
|
|
if (workflow) {
|
|
taskData.workflow = workflow;
|
|
}
|
|
|
|
// Write YAML filea
|
|
const filename = generateFilename(tasksDir, taskContent);
|
|
const filePath = path.join(tasksDir, filename);
|
|
const yamlContent = stringifyYaml(taskData);
|
|
fs.writeFileSync(filePath, yamlContent, 'utf-8');
|
|
|
|
log.info('Task created', { filePath, taskData });
|
|
|
|
success(`Task created: ${filename}`);
|
|
info(` Path: ${filePath}`);
|
|
if (worktree) {
|
|
info(` Worktree: ${typeof worktree === 'string' ? worktree : 'auto'}`);
|
|
}
|
|
if (branch) {
|
|
info(` Branch: ${branch}`);
|
|
}
|
|
if (workflow) {
|
|
info(` Workflow: ${workflow}`);
|
|
}
|
|
}
|