UNPKG

@justinechang39/maki

Version:

AI-powered CLI agent for file operations, CSV manipulation, todo management, and web content fetching using OpenRouter

131 lines (130 loc) 5.23 kB
import * as fs from 'fs/promises'; import { getSafeWorkspacePath } from '../core/utils.js'; export const todoTools = [ { type: 'function', function: { name: 'readTodo', description: `TASK TRACKING: View current todo list and task status. Essential for understanding what work needs to be done, checking progress, and planning next steps. Shows all tasks with their current status markers.`, parameters: { type: 'object', properties: {}, required: [] } } }, { type: 'function', function: { name: 'writeTodo', description: `TASK MANAGEMENT: Create or completely rewrite the todo list. Use for initial task planning, major reorganization, or starting fresh. WARNING: This replaces the entire todo.md file. Use updateTodoItem for individual changes.`, parameters: { type: 'object', properties: { content: { type: 'string', description: "Complete todo list content in Markdown format. Use '- [ ]' for pending, '- [x]' for completed, '- [/]' for in-progress tasks." } }, required: ['content'] } } }, { type: 'function', function: { name: 'updateTodoItem', description: `PROGRESS TRACKING: Update individual task status or description. Use this to mark tasks as completed, in-progress, or modify task descriptions. More precise than rewriting entire todo list.`, parameters: { type: 'object', properties: { itemIndex: { type: 'number', description: 'Line number (1-based) of the task to update. Use readTodo first to see current line numbers.' }, newStatus: { type: 'string', description: 'Task status: "pending" ([ ]), "in_progress" ([/]), "completed" ([x]), "cancelled" ([~])', enum: ['pending', 'in_progress', 'completed', 'cancelled'] }, newText: { type: 'string', description: 'Optional: Update task description. Leave blank to keep current text and only change status.' } }, required: ['itemIndex', 'newStatus'] } } } ]; export const todoToolImplementations = { readTodo: async () => { try { const todoPath = getSafeWorkspacePath('todo.md'); try { await fs.access(todoPath); const content = await fs.readFile(todoPath, 'utf-8'); return { success: true, content, exists: true }; } catch { return { success: true, content: '', exists: false, message: "No 'todo.md' found. Use writeTodo to create one." }; } } catch (error) { return { error: error.message }; } }, writeTodo: async (args) => { try { const todoPath = getSafeWorkspacePath('todo.md'); await fs.writeFile(todoPath, args.content, 'utf-8'); return { success: true, message: "'todo.md' created/updated." }; } catch (error) { return { error: error.message }; } }, updateTodoItem: async (args) => { try { const todoPath = getSafeWorkspacePath('todo.md'); let content; try { content = await fs.readFile(todoPath, 'utf-8'); } catch { return { error: "'todo.md' not found. Use writeTodo first." }; } const lines = content.split('\n'); if (args.itemIndex < 1 || args.itemIndex > lines.length) { return { error: `Invalid itemIndex. 'todo.md' has ${lines.length} lines.` }; } const lineIndex = args.itemIndex - 1; const currentLine = lines[lineIndex]; const statusMarkers = { pending: '[ ]', in_progress: '[/]', completed: '[x]', cancelled: '[~]' }; const marker = statusMarkers[args.newStatus]; if (!marker) return { error: `Invalid newStatus: ${args.newStatus}` }; const textContent = args.newText !== undefined ? args.newText : currentLine.replace(/^\s*-\s*\[[ x/~]\]\s*/, '').trim(); lines[lineIndex] = `- ${marker} ${textContent}`; await fs.writeFile(todoPath, lines.join('\n'), 'utf-8'); return { success: true, message: `Todo item ${args.itemIndex} updated.`, updatedLine: lines[lineIndex] }; } catch (error) { return { error: error.message }; } } };