const fs = require('fs'); const path = require('path'); // 1. Get arguments const args = process.argv.slice(2); if (args.length < 2) { console.error("Usage:"); console.error(" node sync_vikunja.js # Update existing task"); console.error(" node sync_vikunja.js create \"\" \"<message>\" # Create new task"); process.exit(1); } const commandOrId = args[0]; const message = args[1]; // 2. Load configuration from .env.agent const envPath = path.join(__dirname, '../../.env.agent'); const fallbackEnvPath = path.join(__dirname, '../config/.env.agent'); let envContent = ''; if (fs.existsSync(envPath)) { envContent = fs.readFileSync(envPath, 'utf8'); } else if (fs.existsSync(fallbackEnvPath)) { envContent = fs.readFileSync(fallbackEnvPath, 'utf8'); } else { console.error("Error: .env.agent file not found."); process.exit(1); } const env = {}; envContent.split('\n').forEach(line => { const match = line.match(/^([^#=]+)="?(.*?)"?$/); if (match) { env[match[1].trim()] = match[2].trim(); } }); const apiUrl = env.VIKUNJA_API_URL; const apiToken = env.VIKUNJA_API_TOKEN; const projectId = env.VIKUNJA_PROJECT_ID || 14; if (!apiUrl || !apiToken || apiUrl.includes('[YOUR_')) { console.error("Error: VIKUNJA_API_URL or VIKUNJA_API_TOKEN is not configured correctly in .env.agent."); process.exit(1); } if (env.AGENT_OPERATING_MODE === "TEST") { console.log("⚠️ TEST Mode Active: Skipping Vikunja Webhook connection."); process.exit(0); } const FETCH_OPTS = { headers: { 'Authorization': `Bearer ${apiToken}`, 'Content-Type': 'application/json' } }; async function createTaskAndComment(title, message) { try { console.log(`Creating new task in Project ${projectId}...`); const createRes = await fetch(`${apiUrl}/projects/${projectId}/tasks`, { method: 'PUT', ...FETCH_OPTS, body: JSON.stringify({ title: title, description: message, done: true }) }); if (!createRes.ok) throw new Error(`Create failed: ${createRes.statusText}`); const task = await createRes.json(); console.log(`✅ Task created and marked Done! ID: #${task.id}`); } catch (e) { console.error("❌ Failed:", e.message); process.exit(1); } } async function markTaskDoneAndComment(taskId, message) { try { console.log(`Updating Task ${taskId}...`); const patchRes = await fetch(`${apiUrl}/tasks/${taskId}`, { method: 'POST', ...FETCH_OPTS, body: JSON.stringify({ done: true }) }); if (!patchRes.ok) throw new Error(`Update failed: ${patchRes.statusText}`); console.log(`✅ Task ${taskId} marked as Done.`); await fetch(`${apiUrl}/tasks/${taskId}/comments`, { method: 'PUT', ...FETCH_OPTS, body: JSON.stringify({ text: `[Agent Automator] Phase completed.\nReason/Hash: ${message}` }) }); console.log("✅ Comment attached."); } catch (e) { console.error("❌ Failed:", e.message); process.exit(1); } } if (commandOrId === "create") { createTaskAndComment(message, args[2] || "Task fully completed."); } else { markTaskDoneAndComment(commandOrId, message); }