Monorepo for Aesthetic.Computer
aesthetic.computer
1#!/usr/bin/env node
2/**
3 * 🎯 Task State Manager - Bridge between Emacs MCP and VS Code status bar
4 *
5 * Usage:
6 * node task-state.mjs set working "Processing files..."
7 * node task-state.mjs set done "Completed!"
8 * node task-state.mjs set error "Something went wrong"
9 * node task-state.mjs set idle
10 * node task-state.mjs get
11 * node task-state.mjs clear
12 *
13 * The task state file is at /tmp/aesthetic-task-state.json
14 * VS Code extension watches this file and updates the status bar accordingly.
15 *
16 * Status colors:
17 * - idle: default (gray)
18 * - working: yellow (warning background)
19 * - done: green (prominent background) + flash effect
20 * - error: red (error background)
21 */
22
23import { readFileSync, writeFileSync, unlinkSync, existsSync } from 'fs';
24
25const TASK_STATE_FILE = '/tmp/aesthetic-task-state.json';
26
27const validStatuses = ['idle', 'working', 'done', 'error'];
28
29function readState() {
30 try {
31 if (existsSync(TASK_STATE_FILE)) {
32 return JSON.parse(readFileSync(TASK_STATE_FILE, 'utf-8'));
33 }
34 } catch {}
35 return { status: 'idle', label: '', progress: 0 };
36}
37
38function writeState(state) {
39 state.timestamp = Date.now();
40 writeFileSync(TASK_STATE_FILE, JSON.stringify(state, null, 2));
41 console.log('✅ Task state updated:', JSON.stringify(state));
42}
43
44function printUsage() {
45 console.log(`
46🎯 Task State Manager
47
48Usage:
49 node task-state.mjs set <status> [label] [progress]
50 node task-state.mjs get
51 node task-state.mjs clear
52
53Status values:
54 idle - Default state (gray)
55 working - Task in progress (yellow, spinning icon)
56 done - Task completed (green, flashing)
57 error - Task failed (red)
58
59Examples:
60 node task-state.mjs set working "Building project..."
61 node task-state.mjs set working "Processing" 50
62 node task-state.mjs set done "Build complete!"
63 node task-state.mjs set error "Build failed"
64 node task-state.mjs set idle
65 node task-state.mjs clear
66`);
67}
68
69const [,, command, ...args] = process.argv;
70
71switch (command) {
72 case 'set': {
73 const [status, label, progress] = args;
74 if (!status || !validStatuses.includes(status)) {
75 console.error(`❌ Invalid status. Must be one of: ${validStatuses.join(', ')}`);
76 process.exit(1);
77 }
78 writeState({
79 status,
80 label: label || status,
81 progress: progress ? parseInt(progress, 10) : (status === 'done' ? 100 : 0),
82 });
83 break;
84 }
85
86 case 'get': {
87 const state = readState();
88 console.log(JSON.stringify(state, null, 2));
89 break;
90 }
91
92 case 'clear': {
93 try {
94 if (existsSync(TASK_STATE_FILE)) {
95 unlinkSync(TASK_STATE_FILE);
96 console.log('✅ Task state cleared');
97 } else {
98 console.log('ℹ️ No task state file to clear');
99 }
100 } catch (err) {
101 console.error('❌ Failed to clear task state:', err.message);
102 }
103 break;
104 }
105
106 default:
107 printUsage();
108 break;
109}