nothumanallowed 8.0.3 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/commands/ui.mjs +22 -0
- package/src/constants.mjs +1 -1
- package/src/services/task-store.mjs +49 -0
- package/src/services/tool-executor.mjs +45 -0
- package/src/services/web-ui.mjs +15 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "8.0
|
|
3
|
+
"version": "8.1.0",
|
|
4
4
|
"description": "NotHumanAllowed — 38 AI agents + unified productivity suite. Gmail, Calendar, Drive, Contacts, Tasks, GitHub, Notion, Slack, voice chat, smart scheduler. Zero-dependency CLI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/commands/ui.mjs
CHANGED
|
@@ -575,6 +575,28 @@ export async function cmdUI(args) {
|
|
|
575
575
|
return;
|
|
576
576
|
}
|
|
577
577
|
|
|
578
|
+
// POST /api/tasks/:id/delete
|
|
579
|
+
const taskDeleteMatch = pathname.match(/^\/api\/tasks\/(\d+)\/delete$/);
|
|
580
|
+
if (method === 'POST' && taskDeleteMatch) {
|
|
581
|
+
const { deleteTask } = await import('../services/task-store.mjs');
|
|
582
|
+
const taskId = parseInt(taskDeleteMatch[1], 10);
|
|
583
|
+
const success = deleteTask(taskId);
|
|
584
|
+
sendJSON(res, 200, { ok: success, id: taskId });
|
|
585
|
+
logRequest(method, pathname, 200, Date.now() - start);
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// POST /api/tasks/clear
|
|
590
|
+
if (method === 'POST' && pathname === '/api/tasks/clear') {
|
|
591
|
+
const { clearTasks } = await import('../services/task-store.mjs');
|
|
592
|
+
const body = await parseBody(req);
|
|
593
|
+
const mode = body.mode || 'all';
|
|
594
|
+
const count = clearTasks(mode);
|
|
595
|
+
sendJSON(res, 200, { ok: true, removed: count });
|
|
596
|
+
logRequest(method, pathname, 200, Date.now() - start);
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
|
|
578
600
|
// GET /api/plan
|
|
579
601
|
if (method === 'GET' && pathname === '/api/plan') {
|
|
580
602
|
const plan = loadTodayPlan();
|
package/src/constants.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { fileURLToPath } from 'url';
|
|
|
5
5
|
const __filename = fileURLToPath(import.meta.url);
|
|
6
6
|
const __dirname = path.dirname(__filename);
|
|
7
7
|
|
|
8
|
-
export const VERSION = '8.0
|
|
8
|
+
export const VERSION = '8.1.0';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
|
@@ -113,6 +113,55 @@ export function moveTask(taskId, fromDate, toDate) {
|
|
|
113
113
|
return true;
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Delete a single task by ID.
|
|
118
|
+
* @param {number} taskId
|
|
119
|
+
* @param {string} [date]
|
|
120
|
+
* @returns {boolean} success
|
|
121
|
+
*/
|
|
122
|
+
export function deleteTask(taskId, date) {
|
|
123
|
+
const data = loadDay(date);
|
|
124
|
+
const idx = data.tasks.findIndex(t => t.id === taskId);
|
|
125
|
+
if (idx === -1) return false;
|
|
126
|
+
data.tasks.splice(idx, 1);
|
|
127
|
+
saveDay(date, data);
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Clear all tasks for a date (delete completed, or all).
|
|
133
|
+
* @param {'done'|'all'} mode — 'done' removes only completed, 'all' removes everything
|
|
134
|
+
* @param {string} [date]
|
|
135
|
+
* @returns {number} count of removed tasks
|
|
136
|
+
*/
|
|
137
|
+
export function clearTasks(mode = 'all', date) {
|
|
138
|
+
const data = loadDay(date);
|
|
139
|
+
const before = data.tasks.length;
|
|
140
|
+
if (mode === 'done') {
|
|
141
|
+
data.tasks = data.tasks.filter(t => t.status !== 'done');
|
|
142
|
+
} else {
|
|
143
|
+
data.tasks = [];
|
|
144
|
+
}
|
|
145
|
+
saveDay(date, data);
|
|
146
|
+
return before - data.tasks.length;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Edit task priority.
|
|
151
|
+
* @param {number} taskId
|
|
152
|
+
* @param {string} priority
|
|
153
|
+
* @param {string} [date]
|
|
154
|
+
* @returns {boolean}
|
|
155
|
+
*/
|
|
156
|
+
export function editTaskPriority(taskId, priority, date) {
|
|
157
|
+
const data = loadDay(date);
|
|
158
|
+
const task = data.tasks.find(t => t.id === taskId);
|
|
159
|
+
if (!task) return false;
|
|
160
|
+
task.priority = priority;
|
|
161
|
+
saveDay(date, data);
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
|
|
116
165
|
/**
|
|
117
166
|
* Get tasks for the week (Mon-Sun).
|
|
118
167
|
*/
|
|
@@ -36,6 +36,10 @@ import {
|
|
|
36
36
|
addTask,
|
|
37
37
|
completeTask,
|
|
38
38
|
moveTask,
|
|
39
|
+
deleteTask,
|
|
40
|
+
clearTasks,
|
|
41
|
+
editTask,
|
|
42
|
+
editTaskPriority,
|
|
39
43
|
} from './task-store.mjs';
|
|
40
44
|
|
|
41
45
|
import { notify } from './notification.mjs';
|
|
@@ -53,6 +57,8 @@ export const DESTRUCTIVE_ACTIONS = new Set([
|
|
|
53
57
|
'calendar_update',
|
|
54
58
|
'contact_delete',
|
|
55
59
|
'task_done',
|
|
60
|
+
'task_delete',
|
|
61
|
+
'task_clear',
|
|
56
62
|
'notify_remind',
|
|
57
63
|
'slack_send',
|
|
58
64
|
'github_create_issue',
|
|
@@ -157,6 +163,15 @@ TOOLS:
|
|
|
157
163
|
23. task_move(id: number, toDate: string)
|
|
158
164
|
Move a task to another date (YYYY-MM-DD).
|
|
159
165
|
|
|
166
|
+
24. task_delete(id: number)
|
|
167
|
+
Delete a specific task permanently. ALWAYS confirm before deleting.
|
|
168
|
+
|
|
169
|
+
25. task_clear(mode?: "all"|"done")
|
|
170
|
+
Clear tasks. mode="done" removes only completed tasks. mode="all" removes ALL tasks. Default: "all". ALWAYS confirm before clearing.
|
|
171
|
+
|
|
172
|
+
26. task_edit(id: number, description?: string, priority?: "low"|"medium"|"high"|"critical")
|
|
173
|
+
Edit a task's description and/or priority.
|
|
174
|
+
|
|
160
175
|
--- CONTACTS ---
|
|
161
176
|
|
|
162
177
|
24. contact_search(query: string)
|
|
@@ -381,6 +396,10 @@ export function describeAction(action, params) {
|
|
|
381
396
|
return `Delete contact "${params.query}"`;
|
|
382
397
|
case 'task_done':
|
|
383
398
|
return `Mark task #${params.id} as completed`;
|
|
399
|
+
case 'task_delete':
|
|
400
|
+
return `Delete task #${params.id} permanently`;
|
|
401
|
+
case 'task_clear':
|
|
402
|
+
return `Clear ${params.mode === 'done' ? 'completed' : 'ALL'} tasks`;
|
|
384
403
|
case 'notify_remind':
|
|
385
404
|
return `Set reminder: "${params.message}" at ${params.atTime}`;
|
|
386
405
|
case 'slack_send':
|
|
@@ -759,6 +778,32 @@ export async function executeTool(action, params, config) {
|
|
|
759
778
|
return success ? `Task #${params.id} moved to ${toDate}.` : `Task #${params.id} not found.`;
|
|
760
779
|
}
|
|
761
780
|
|
|
781
|
+
case 'task_delete': {
|
|
782
|
+
const success = deleteTask(params.id);
|
|
783
|
+
return success ? `Task #${params.id} deleted.` : `Task #${params.id} not found.`;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
case 'task_clear': {
|
|
787
|
+
const mode = params.mode || 'all';
|
|
788
|
+
const count = clearTasks(mode);
|
|
789
|
+
return count > 0
|
|
790
|
+
? `${count} task${count !== 1 ? 's' : ''} ${mode === 'done' ? 'completed' : ''} removed.`
|
|
791
|
+
: 'No tasks to remove.';
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
case 'task_edit': {
|
|
795
|
+
if (params.description) {
|
|
796
|
+
editTask(params.id, params.description);
|
|
797
|
+
}
|
|
798
|
+
if (params.priority) {
|
|
799
|
+
editTaskPriority(params.id, params.priority);
|
|
800
|
+
}
|
|
801
|
+
const parts = [];
|
|
802
|
+
if (params.description) parts.push(`description updated`);
|
|
803
|
+
if (params.priority) parts.push(`priority set to ${params.priority}`);
|
|
804
|
+
return parts.length > 0 ? `Task #${params.id}: ${parts.join(', ')}.` : `No changes specified for task #${params.id}.`;
|
|
805
|
+
}
|
|
806
|
+
|
|
762
807
|
// ── Notifications ─────────────────────────────────────────────────────
|
|
763
808
|
case 'notify_remind': {
|
|
764
809
|
const atTime = resolveTime(params.atTime);
|
package/src/services/web-ui.mjs
CHANGED
|
@@ -360,10 +360,13 @@ function sendChat(){
|
|
|
360
360
|
function renderTasks(el){
|
|
361
361
|
var t=dash.tasks;
|
|
362
362
|
var h='<div class="task-bar"><input id="taskInput" placeholder="Add a new task..."><select id="taskPriority"><option value="medium">Medium</option><option value="high">High</option><option value="critical">Critical</option><option value="low">Low</option></select><button onclick="addTaskUI()">Add</button></div>';
|
|
363
|
+
if(t.length>0){
|
|
364
|
+
h+='<div style="display:flex;gap:8px;margin-bottom:12px"><button onclick="clearTasksUI(\\x27done\\x27)" style="background:var(--bg3);color:var(--dim);border:1px solid var(--border);padding:6px 12px;border-radius:var(--r);font-size:11px;cursor:pointer">Clear completed</button><button onclick="clearTasksUI(\\x27all\\x27)" style="background:var(--bg3);color:var(--red);border:1px solid var(--border);padding:6px 12px;border-radius:var(--r);font-size:11px;cursor:pointer">Clear all</button></div>';
|
|
365
|
+
}
|
|
363
366
|
t.sort(function(a,b){if(a.status==='done'&&b.status!=='done')return 1;if(a.status!=='done'&&b.status==='done')return -1;return 0});
|
|
364
367
|
t.forEach(function(x){
|
|
365
368
|
var isDone=x.status==='done';
|
|
366
|
-
h+='<div class="card task'+(isDone?' task--done':'')+'"
|
|
369
|
+
h+='<div class="card task'+(isDone?' task--done':'')+'"><span class="task__check'+(isDone?' task__check--done':'')+'" onclick="toggleTask('+x.id+')">'+(isDone?'\\u2713':'')+'</span><span class="task__desc" onclick="toggleTask('+x.id+')">'+esc(x.description)+'</span><span class="task__priority task__priority--'+esc(x.priority)+'">'+esc(x.priority)+'</span><span onclick="deleteTaskUI('+x.id+')" style="color:var(--dim);cursor:pointer;padding:4px 8px;font-size:14px;opacity:0.5" title="Delete task">×</span></div>';
|
|
367
370
|
});
|
|
368
371
|
el.innerHTML=h;
|
|
369
372
|
var inp=document.getElementById('taskInput');
|
|
@@ -377,7 +380,16 @@ function addTaskUI(){
|
|
|
377
380
|
});
|
|
378
381
|
}
|
|
379
382
|
function toggleTask(id){
|
|
380
|
-
apiPatch('/api/tasks/'+id+'/done').then(function(){loadDash().then(function(){if(currentView==='tasks')render()})});
|
|
383
|
+
apiPatch('/api/tasks/'+id+'/done').then(function(){loadDash().then(function(){if(currentView==='tasks'||currentView==='dashboard')render()})});
|
|
384
|
+
}
|
|
385
|
+
function deleteTaskUI(id){
|
|
386
|
+
if(!confirm('Delete task #'+id+'?'))return;
|
|
387
|
+
apiPost('/api/tasks/'+id+'/delete',{}).then(function(){loadDash().then(function(){render()})});
|
|
388
|
+
}
|
|
389
|
+
function clearTasksUI(mode){
|
|
390
|
+
var msg=mode==='all'?'Delete ALL tasks? This cannot be undone.':'Remove all completed tasks?';
|
|
391
|
+
if(!confirm(msg))return;
|
|
392
|
+
apiPost('/api/tasks/clear',{mode:mode}).then(function(){loadDash().then(function(){render()})});
|
|
381
393
|
}
|
|
382
394
|
|
|
383
395
|
// ---- PLAN ----
|
|
@@ -1403,7 +1415,7 @@ init();
|
|
|
1403
1415
|
</div>
|
|
1404
1416
|
<div class="sidebar__section">
|
|
1405
1417
|
<div class="sidebar__label">Google</div>
|
|
1406
|
-
<div class="nav-item" data-view="emails" onclick="switchView('emails')"><span class="nav-item__icon">&#
|
|
1418
|
+
<div class="nav-item" data-view="emails" onclick="switchView('emails')"><span class="nav-item__icon">📧</span> Emails <span class="nav-item__badge" id="emailBadge" style="display:none">0</span></div>
|
|
1407
1419
|
<div class="nav-item" data-view="calendar" onclick="switchView('calendar')"><span class="nav-item__icon">📅</span> Calendar <span class="nav-item__badge" id="calBadge" style="display:none;background:var(--amber)">0</span></div>
|
|
1408
1420
|
<div class="nav-item" data-view="drive" onclick="switchView('drive')"><span class="nav-item__icon">📁</span> Drive</div>
|
|
1409
1421
|
<div class="nav-item" data-view="contacts" onclick="switchView('contacts')"><span class="nav-item__icon">👥</span> Contacts</div>
|