UNPKG

alnilam-cli

Version:

Git-native AI career coach that converts multi-year ambitions into weekly execution

239 lines (238 loc) • 9.79 kB
"use strict"; 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.nudgeCommand = exports.planReviewCommand = void 0; const commander_1 = require("commander"); const api_js_1 = require("../lib/api.js"); const readline = __importStar(require("readline")); const planReviewCommand = new commander_1.Command('review'); exports.planReviewCommand = planReviewCommand; planReviewCommand .description('Interactive plan approval workflow') .option('--auto-approve', 'Auto-approve all pending plans') .option('--json', 'Output as JSON') .action(async (options) => { try { console.log('šŸ“‹ Plan Review Dashboard'); console.log('═'.repeat(50)); // Fetch pending nudges const response = await api_js_1.restClient.get('/nudges', { params: { select: '*', 'requires_approval': 'eq.true', 'approved': 'eq.false', order: 'created_at.desc' } }); const pendingNudges = response.data || []; if (pendingNudges.length === 0) { console.log('āœ… No pending approvals! All plans are up to date.'); console.log('šŸ’” Generate a new plan with: alnl plan'); return; } if (options.json) { console.log(JSON.stringify(pendingNudges, null, 2)); return; } console.log(`šŸ“Š Found ${pendingNudges.length} pending approval(s)\n`); for (let i = 0; i < pendingNudges.length; i++) { const nudge = pendingNudges[i]; const isWeeklyPlan = nudge.type === 'weekly_plan'; console.log(`šŸ” Reviewing ${i + 1}/${pendingNudges.length}`); console.log('─'.repeat(40)); // Display plan details console.log(`šŸ“‹ Type: ${nudge.type}`); console.log(`šŸ“… Created: ${new Date(nudge.created_at).toLocaleString()}`); console.log(`šŸ“ Content: ${nudge.content}\n`); if (isWeeklyPlan && nudge.metadata) { // Show weekly plan details const metadata = nudge.metadata; if (metadata.target_week) { console.log(`šŸ—“ļø Target Week: ${metadata.target_week}`); } if (metadata.estimated_cost) { console.log(`šŸ’° Estimated Cost: $${metadata.estimated_cost}`); } if (metadata.proposed_goals && metadata.proposed_goals.length > 0) { console.log('\nšŸŽÆ Proposed Goals:'); metadata.proposed_goals.forEach((goal, index) => { const priority = goal.priority === 'high' ? 'šŸ”“' : goal.priority === 'medium' ? '🟔' : '🟢'; console.log(` ${index + 1}. ${goal.title} ${priority}`); console.log(` ${goal.description.substring(0, 60)}...`); console.log(` ā±ļø ${goal.estimated_hours}h | šŸ’” ${goal.rationale.substring(0, 40)}...`); }); } if (metadata.focus_areas && metadata.focus_areas.length > 0) { console.log('\nšŸŽÆ Focus Areas:'); metadata.focus_areas.forEach((area) => { console.log(` • ${area}`); }); } if (metadata.risk_mitigations && metadata.risk_mitigations.length > 0) { console.log('\nšŸ›”ļø Risk Mitigations:'); metadata.risk_mitigations.forEach((mitigation) => { console.log(` • ${mitigation}`); }); } } // Auto-approve if requested if (options.autoApprove || options['auto-approve']) { await approveNudge(nudge.id); console.log('āœ… Auto-approved!'); continue; } // Interactive approval const approved = await promptForApproval(); if (approved) { await approveNudge(nudge.id); console.log('āœ… Approved!'); } else { console.log('āŒ Rejected (nudge remains pending)'); } console.log(''); // Add spacing between reviews } console.log('═'.repeat(50)); console.log('šŸŽ‰ Plan review complete!'); console.log('šŸ“Š Check updated status with: alnl plan list'); } catch (error) { console.error('āŒ Plan review error:', error.message); process.exit(1); } }); // Helper function to approve a nudge async function approveNudge(nudgeId) { const now = new Date().toISOString(); await api_js_1.restClient.patch(`/nudges?id=eq.${nudgeId}`, { approved: true, approved_at: now }); } // Helper function to prompt for approval function promptForApproval() { return new Promise((resolve) => { const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); const prompt = () => { rl.question('\nšŸ¤” Approve this plan? (y/n/s=skip): ', (answer) => { const response = answer.toLowerCase().trim(); if (response === 'y' || response === 'yes') { rl.close(); resolve(true); } else if (response === 'n' || response === 'no') { rl.close(); resolve(false); } else if (response === 's' || response === 'skip') { rl.close(); resolve(false); } else { console.log('Please enter y(es), n(o), or s(kip)'); prompt(); } }); }; prompt(); }); } // Nudge management command const nudgeCommand = new commander_1.Command('nudges'); exports.nudgeCommand = nudgeCommand; nudgeCommand .description('Manage AI-generated nudges and proposals') .option('--pending', 'Show only pending nudges') .option('--approved', 'Show only approved nudges') .option('--json', 'Output as JSON') .action(async (options) => { try { console.log('šŸ’” Nudge Management'); console.log('═'.repeat(40)); let queryParams = { select: '*', order: 'created_at.desc' }; if (options.pending) { queryParams['requires_approval'] = 'eq.true'; queryParams['approved'] = 'eq.false'; } else if (options.approved) { queryParams['approved'] = 'eq.true'; } const response = await api_js_1.restClient.get('/nudges', { params: queryParams }); const nudges = response.data || []; if (options.json) { console.log(JSON.stringify(nudges, null, 2)); return; } if (nudges.length === 0) { console.log('šŸ“­ No nudges found.'); return; } nudges.forEach((nudge, index) => { const status = nudge.approved ? 'āœ…' : 'ā³'; const age = getTimeAgo(nudge.created_at); console.log(`${index + 1}. ${status} ${nudge.type} (${age})`); console.log(` ${nudge.content}`); if (nudge.type === 'weekly_plan' && nudge.metadata?.proposed_goals) { console.log(` šŸŽÆ ${nudge.metadata.proposed_goals.length} goals proposed`); } console.log(''); }); const pending = nudges.filter(n => !n.approved).length; if (pending > 0) { console.log(`šŸ’” Review pending items with: alnl plan review`); } } catch (error) { console.error('āŒ Nudge management error:', error.message); process.exit(1); } }); // Helper function for relative time function getTimeAgo(dateString) { const date = new Date(dateString); const now = new Date(); const diffMs = now.getTime() - date.getTime(); const diffHours = Math.floor(diffMs / (1000 * 60 * 60)); const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24)); if (diffHours < 1) return 'just now'; if (diffHours < 24) return `${diffHours}h ago`; return `${diffDays}d ago`; }