@gonzui/claude-task-manager
Version:
Task management extension for Claude Code with archiving and history
186 lines (170 loc) • 6.65 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.TaskFileManager = void 0;
const fs = __importStar(require("fs-extra"));
const path = __importStar(require("path"));
const date_fns_1 = require("date-fns");
const types_1 = require("../types");
class TaskFileManager {
constructor(taskFile, archiveDir, i18n) {
this.taskFile = taskFile;
this.archiveDir = archiveDir;
this.i18n = i18n;
}
async createTaskFile(title, description, options, template, config) {
const isJapanese = config.language === 'ja';
const formatArrayToMarkdown = (items, defaultValue) => {
if (Array.isArray(items)) {
if (items.length === 0) {
return defaultValue;
}
const firstItem = items[0];
const isComment = firstItem.startsWith('<!--') && firstItem.endsWith('-->');
let result = isComment ? firstItem : `- ${firstItem}`;
for (let i = 1; i < items.length; i++) {
result += `\n- ${items[i]}`;
}
return result;
}
return items || defaultValue;
};
const defaultPrerequisites = isJapanese ? '<!-- 前提条件を記入してください -->' : '<!-- Add prerequisites here -->';
const defaultRules = isJapanese ? '<!-- ルールを記入してください -->' : '<!-- Add rules here -->';
const defaultTaskItems = isJapanese ? '- タスク 1\n- タスク 2\n- タスク 3' : '- Task 1\n- Task 2\n- Task 3';
const variables = {
TITLE: title,
DESCRIPTION: description,
DATE: new Date().toISOString(),
TIMESTAMP: (0, date_fns_1.format)(new Date(), 'yyyy-MM-dd HH:mm:ss'),
PRIORITY: options.priority || 'medium',
TAGS: options.tags?.join(', ') || '',
PREREQUISITES: options.prerequisites || formatArrayToMarkdown(config.defaultPrerequisites, defaultPrerequisites),
RULES: options.rules || formatArrayToMarkdown(config.defaultRules, defaultRules),
TASKS: options.tasks || formatArrayToMarkdown(config.defaultTasks, defaultTaskItems)
};
let content = template;
Object.entries(variables).forEach(([key, value]) => {
content = content.replace(new RegExp(`{{${key}}}`, 'g'), value);
});
await fs.writeFile(this.taskFile, content);
}
async archiveCurrentTask() {
try {
if (!await fs.pathExists(this.taskFile)) {
return null;
}
const now = new Date();
const timestamp = (0, date_fns_1.format)(now, 'yyyy-MM-dd_HH-mm-ss');
const milliseconds = now.getMilliseconds().toString().padStart(3, '0');
let archiveFileName = `${timestamp}-${milliseconds}_task.md`;
let archivePath = path.join(this.archiveDir, archiveFileName);
let suffix = 1;
while (await fs.pathExists(archivePath)) {
archiveFileName = `${timestamp}-${milliseconds}-${suffix}_task.md`;
archivePath = path.join(this.archiveDir, archiveFileName);
suffix++;
}
const currentContent = await fs.readFile(this.taskFile, 'utf8');
const archivedContent = `<!-- Archived: ${new Date().toISOString()} -->\n\n${currentContent}`;
await fs.writeFile(archivePath, archivedContent);
await fs.remove(this.taskFile);
return archivePath;
}
catch (error) {
throw new types_1.FileSystemError(`Failed to archive current task: ${error instanceof Error ? error.message : 'Unknown error'}`, this.taskFile, 'archive');
}
}
async getTaskContent() {
if (!await fs.pathExists(this.taskFile)) {
throw new types_1.TaskManagerError(this.i18n.t('errors.noTaskFile'), 'NO_TASK_FILE');
}
return await fs.readFile(this.taskFile, 'utf8');
}
async taskFileExists() {
return await fs.pathExists(this.taskFile);
}
async appendToTaskFile(content) {
await fs.appendFile(this.taskFile, content);
}
getTaskFilePath() {
return this.taskFile;
}
getDefaultTaskTemplate() {
try {
const t = this.i18n.getNamespace('taskTemplate');
if (!t || !t.title) {
throw new Error('i18n taskTemplate namespace not loaded');
}
return `${t.title}
${t.created}
${t.priority}
${t.tags}
${t.description}
${t.prerequisites}
${t.rules}
${t.tasks}
${t.context}
${t.notes}
${t.footer}
`;
}
catch {
return `# {{TITLE}}
**Created:** {{DATE}}
**Priority:** {{PRIORITY}}
**Tags:** {{TAGS}}
## Description
{{DESCRIPTION}}
## Prerequisites
{{PREREQUISITES}}
## Rules
{{RULES}}
## Tasks
{{TASKS}}
## Context
<!-- Add context for Claude Code execution -->
## Notes
<!-- Add your notes here -->
---
*Generated by Claude Task Manager*`;
}
}
async getTaskTemplate(config) {
return config.taskTemplate || this.getDefaultTaskTemplate();
}
}
exports.TaskFileManager = TaskFileManager;
//# sourceMappingURL=TaskFileManager.js.map