nothumanallowed 6.1.2 → 6.2.1
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/chat.mjs +38 -1
- package/src/commands/ui.mjs +30 -0
- package/src/commands/voice.mjs +34 -3
- package/src/constants.mjs +1 -1
- package/src/services/web-ui.mjs +7 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "6.1
|
|
3
|
+
"version": "6.2.1",
|
|
4
4
|
"description": "NotHumanAllowed — 38 AI agents for security, code, DevOps, data & daily ops. Per-agent memory, Telegram + Discord auto-responder, proactive intelligence daemon, voice chat, plugin system.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/commands/chat.mjs
CHANGED
|
@@ -125,9 +125,18 @@ TOOLS:
|
|
|
125
125
|
18. schedule_draft_email(clientName: string, subject: string, location: string, durationMinutes: number, dateFrom: string, dateTo: string)
|
|
126
126
|
Same as schedule_meeting but also generates a professional email proposing the top 3 slots to the client.
|
|
127
127
|
|
|
128
|
+
19. calendar_update(eventId: string, summary?: string, location?: string, description?: string, start?: string, end?: string)
|
|
129
|
+
Update ANY field of an existing calendar event: title, location, description, start time, end time.
|
|
130
|
+
Use this to modify existing events. You must provide the eventId (from calendar_today or calendar_week).
|
|
131
|
+
Only include fields that need to change. ALWAYS confirm with the user before updating.
|
|
132
|
+
|
|
133
|
+
20. maps_directions(from: string, to: string)
|
|
134
|
+
Generate a Google Maps directions link between two locations. Returns a clickable URL.
|
|
135
|
+
Use this when the user asks for directions, route, or "how to get to" somewhere.
|
|
136
|
+
|
|
128
137
|
RULES:
|
|
129
138
|
- For search/read operations, execute immediately and present results conversationally.
|
|
130
|
-
- For write/send/delete operations (gmail_send, gmail_reply, calendar_create, calendar_move, task_done, notify_remind), DESCRIBE what you're about to do and include the JSON block so the system can ask the user for confirmation.
|
|
139
|
+
- For write/send/delete operations (gmail_send, gmail_reply, calendar_create, calendar_move, calendar_update, task_done, notify_remind), DESCRIBE what you're about to do and include the JSON block so the system can ask the user for confirmation.
|
|
131
140
|
- For schedule_meeting and schedule_draft_email, execute immediately — these are read operations that suggest slots.
|
|
132
141
|
- When presenting email results, show From, Subject, Date, and a brief snippet. Never dump raw JSON.
|
|
133
142
|
- When presenting calendar events, show Time, Title, Location/Link. Format times in a human-readable way.
|
|
@@ -351,6 +360,34 @@ async function executeTool(action, params, config) {
|
|
|
351
360
|
return `${proposal}\n\n--- DRAFT EMAIL ---\n\n${email}`;
|
|
352
361
|
}
|
|
353
362
|
|
|
363
|
+
// ── Calendar Update (modify any field of existing event) ──────────────
|
|
364
|
+
case 'calendar_update': {
|
|
365
|
+
const { updateEvent: updateCal } = await import('../services/mail-router.mjs');
|
|
366
|
+
const patch = {};
|
|
367
|
+
if (params.summary) patch.summary = params.summary;
|
|
368
|
+
if (params.location) patch.location = params.location;
|
|
369
|
+
if (params.description) patch.description = params.description;
|
|
370
|
+
if (params.start) {
|
|
371
|
+
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
372
|
+
patch.start = { dateTime: new Date(params.start).toISOString(), timeZone: tz };
|
|
373
|
+
}
|
|
374
|
+
if (params.end) {
|
|
375
|
+
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
376
|
+
patch.end = { dateTime: new Date(params.end).toISOString(), timeZone: tz };
|
|
377
|
+
}
|
|
378
|
+
await updateCal(config, 'primary', params.eventId, patch);
|
|
379
|
+
const changes = Object.keys(patch).join(', ');
|
|
380
|
+
return `Event updated (${changes}). ${params.location ? `New location: ${params.location}` : ''}`;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// ── Maps Directions (free Google Maps link) ──────────────────────────
|
|
384
|
+
case 'maps_directions': {
|
|
385
|
+
const from = encodeURIComponent(params.from || '');
|
|
386
|
+
const to = encodeURIComponent(params.to || '');
|
|
387
|
+
if (!from || !to) return 'Both "from" and "to" locations are required.';
|
|
388
|
+
return `Google Maps directions:\nhttps://www.google.com/maps/dir/${from}/${to}`;
|
|
389
|
+
}
|
|
390
|
+
|
|
354
391
|
default:
|
|
355
392
|
return `Unknown action: ${action}`;
|
|
356
393
|
}
|
package/src/commands/ui.mjs
CHANGED
|
@@ -90,6 +90,12 @@ TOOLS:
|
|
|
90
90
|
14. schedule_draft_email(clientName: string, subject: string, location: string, durationMinutes: number, dateFrom: string, dateTo: string)
|
|
91
91
|
Same as schedule_meeting but also generates a professional email proposing the top 3 slots.
|
|
92
92
|
|
|
93
|
+
15. calendar_update(eventId: string, summary?: string, location?: string, description?: string, start?: string, end?: string)
|
|
94
|
+
Update ANY field of an existing calendar event. Only include fields that need to change. Confirm with the user first.
|
|
95
|
+
|
|
96
|
+
16. maps_directions(from: string, to: string)
|
|
97
|
+
Generate a Google Maps directions link between two locations.
|
|
98
|
+
|
|
93
99
|
RULES:
|
|
94
100
|
- For search/read operations, execute immediately and present results conversationally.
|
|
95
101
|
- For write/send/delete operations, describe what you're about to do and include the JSON block.
|
|
@@ -299,6 +305,30 @@ async function executeTool(action, params, config) {
|
|
|
299
305
|
return `${proposal}\n\n--- DRAFT EMAIL ---\n\n${email}`;
|
|
300
306
|
}
|
|
301
307
|
|
|
308
|
+
case 'calendar_update': {
|
|
309
|
+
const { updateEvent: updateCal } = await import('../services/mail-router.mjs');
|
|
310
|
+
const patch = {};
|
|
311
|
+
if (params.summary) patch.summary = params.summary;
|
|
312
|
+
if (params.location) patch.location = params.location;
|
|
313
|
+
if (params.description) patch.description = params.description;
|
|
314
|
+
if (params.start) {
|
|
315
|
+
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
316
|
+
patch.start = { dateTime: new Date(params.start).toISOString(), timeZone: tz };
|
|
317
|
+
}
|
|
318
|
+
if (params.end) {
|
|
319
|
+
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
320
|
+
patch.end = { dateTime: new Date(params.end).toISOString(), timeZone: tz };
|
|
321
|
+
}
|
|
322
|
+
await updateCal(config, 'primary', params.eventId, patch);
|
|
323
|
+
const changes = Object.keys(patch).join(', ');
|
|
324
|
+
return `Event updated (${changes}). ${params.location ? 'New location: ' + params.location : ''}`;
|
|
325
|
+
}
|
|
326
|
+
case 'maps_directions': {
|
|
327
|
+
const from = encodeURIComponent(params.from || '');
|
|
328
|
+
const to = encodeURIComponent(params.to || '');
|
|
329
|
+
if (!from || !to) return 'Both "from" and "to" locations are required.';
|
|
330
|
+
return `Google Maps directions:\nhttps://www.google.com/maps/dir/${from}/${to}`;
|
|
331
|
+
}
|
|
302
332
|
default:
|
|
303
333
|
return `Unknown action: ${action}`;
|
|
304
334
|
}
|
package/src/commands/voice.mjs
CHANGED
|
@@ -77,6 +77,12 @@ TOOLS:
|
|
|
77
77
|
12. schedule_meeting(clientName: string, subject: string, location: string, durationMinutes: number, dateFrom: string, dateTo: string)
|
|
78
78
|
Find optimal meeting slots considering calendar, locations, and travel time.
|
|
79
79
|
|
|
80
|
+
13. calendar_update(eventId: string, summary?: string, location?: string, description?: string, start?: string, end?: string)
|
|
81
|
+
Update any field of an existing calendar event. Confirm first.
|
|
82
|
+
|
|
83
|
+
14. maps_directions(from: string, to: string)
|
|
84
|
+
Generate a Google Maps directions link.
|
|
85
|
+
|
|
80
86
|
RULES:
|
|
81
87
|
- For search/read operations, execute immediately and present results conversationally.
|
|
82
88
|
- For write/send/delete operations, describe what you're about to do and include the JSON block.
|
|
@@ -212,6 +218,30 @@ async function executeTool(action, params, config) {
|
|
|
212
218
|
});
|
|
213
219
|
return formatSlotProposal(slots, params.clientName || 'the client', params.subject || 'meeting', params.location || '');
|
|
214
220
|
}
|
|
221
|
+
case 'calendar_update': {
|
|
222
|
+
const { updateEvent: updateCal } = await import('../services/mail-router.mjs');
|
|
223
|
+
const patch = {};
|
|
224
|
+
if (params.summary) patch.summary = params.summary;
|
|
225
|
+
if (params.location) patch.location = params.location;
|
|
226
|
+
if (params.description) patch.description = params.description;
|
|
227
|
+
if (params.start) {
|
|
228
|
+
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
229
|
+
patch.start = { dateTime: new Date(params.start).toISOString(), timeZone: tz };
|
|
230
|
+
}
|
|
231
|
+
if (params.end) {
|
|
232
|
+
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
233
|
+
patch.end = { dateTime: new Date(params.end).toISOString(), timeZone: tz };
|
|
234
|
+
}
|
|
235
|
+
await updateCal(config, 'primary', params.eventId, patch);
|
|
236
|
+
const changes = Object.keys(patch).join(', ');
|
|
237
|
+
return `Event updated (${changes}). ${params.location ? 'New location: ' + params.location : ''}`;
|
|
238
|
+
}
|
|
239
|
+
case 'maps_directions': {
|
|
240
|
+
const from = encodeURIComponent(params.from || '');
|
|
241
|
+
const to = encodeURIComponent(params.to || '');
|
|
242
|
+
if (!from || !to) return 'Both "from" and "to" locations are required.';
|
|
243
|
+
return `Google Maps directions:\nhttps://www.google.com/maps/dir/${from}/${to}`;
|
|
244
|
+
}
|
|
215
245
|
default:
|
|
216
246
|
return `Unknown action: ${action}`;
|
|
217
247
|
}
|
|
@@ -324,7 +354,8 @@ html,body{height:100%;background:var(--bg);color:var(--text);font-family:var(--f
|
|
|
324
354
|
|
|
325
355
|
const JS = `
|
|
326
356
|
var API = '';
|
|
327
|
-
var chatHistory = [];
|
|
357
|
+
var chatHistory = (function(){try{var s=localStorage.getItem('nha_voice_history');return s?JSON.parse(s):[];}catch(e){return [];}})();
|
|
358
|
+
function saveVoiceToStorage(){try{localStorage.setItem('nha_voice_history',JSON.stringify(chatHistory.slice(-20)));}catch(e){}}
|
|
328
359
|
var isRecording = false;
|
|
329
360
|
var recognition = null;
|
|
330
361
|
var mediaRecorder = null;
|
|
@@ -493,7 +524,7 @@ function speak(text) {
|
|
|
493
524
|
// ---- PROCESS MESSAGE ----
|
|
494
525
|
function processMessage(text) {
|
|
495
526
|
chatHistory.push({ role: 'user', content: text });
|
|
496
|
-
renderMessages();
|
|
527
|
+
saveVoiceToStorage();renderMessages();
|
|
497
528
|
|
|
498
529
|
chatHistory.push({ role: 'assistant', content: 'Thinking...' });
|
|
499
530
|
renderMessages();
|
|
@@ -513,7 +544,7 @@ function processMessage(text) {
|
|
|
513
544
|
response = 'No response from server.';
|
|
514
545
|
chatHistory.push({ role: 'assistant', content: response });
|
|
515
546
|
}
|
|
516
|
-
renderMessages();
|
|
547
|
+
saveVoiceToStorage();renderMessages();
|
|
517
548
|
setStatus('');
|
|
518
549
|
|
|
519
550
|
// Speak the response
|
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 = '6.1
|
|
8
|
+
export const VERSION = '6.2.1';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
package/src/services/web-ui.mjs
CHANGED
|
@@ -180,8 +180,11 @@ input:focus,textarea:focus{border-color:var(--green3)}
|
|
|
180
180
|
const JS = `
|
|
181
181
|
var API = '';
|
|
182
182
|
var currentView = 'dashboard';
|
|
183
|
-
var chatHistory = [];
|
|
183
|
+
var chatHistory = (function(){try{var s=localStorage.getItem('nha_chat_history');return s?JSON.parse(s):[];}catch(e){return [];}})();
|
|
184
184
|
var dash = {emails:[],events:[],tasks:[],plan:null,status:null};
|
|
185
|
+
|
|
186
|
+
function saveChatToStorage(){try{localStorage.setItem('nha_chat_history',JSON.stringify(chatHistory.slice(-40)));}catch(e){}}
|
|
187
|
+
function clearChatHistory(){chatHistory=[];saveChatToStorage();renderMessages();}
|
|
185
188
|
var agentsList = [];
|
|
186
189
|
var selectedAgent = null;
|
|
187
190
|
|
|
@@ -279,7 +282,7 @@ function renderDash(el){
|
|
|
279
282
|
var chatReady=false;
|
|
280
283
|
function renderChat(el){
|
|
281
284
|
if(!chatReady||!document.getElementById('chatMessages')){
|
|
282
|
-
el.innerHTML='<div class="chat"><div class="chat__messages" id="chatMessages"></div><div class="chat__bar"><button class="chat__mic" id="chatMic" onclick="toggleVoiceInput()" title="Voice input">🎤</button><textarea class="chat__input" id="chatInput" placeholder="Ask anything..." rows="1"></textarea><button class="chat__send" id="chatSend">Send</button></div></div>';
|
|
285
|
+
el.innerHTML='<div class="chat"><div class="chat__messages" id="chatMessages"></div><div class="chat__bar"><button class="chat__mic" id="chatMic" onclick="toggleVoiceInput()" title="Voice input">🎤</button><textarea class="chat__input" id="chatInput" placeholder="Ask anything..." rows="1"></textarea><button class="chat__send" id="chatSend">Send</button><button onclick="clearChatHistory()" style="background:none;color:var(--dim);font-size:10px;padding:4px 8px" title="Clear chat history">Clear</button></div></div>';
|
|
283
286
|
chatReady=true;
|
|
284
287
|
document.getElementById('chatSend').onclick=sendChat;
|
|
285
288
|
document.getElementById('chatInput').onkeydown=function(e){if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();sendChat()}};
|
|
@@ -302,14 +305,14 @@ function sendChat(){
|
|
|
302
305
|
var inp=document.getElementById('chatInput');if(!inp)return;
|
|
303
306
|
var msg=inp.value.trim();if(!msg)return;
|
|
304
307
|
chatHistory.push({role:'user',content:msg});
|
|
305
|
-
inp.value='';renderMessages();
|
|
308
|
+
inp.value='';saveChatToStorage();renderMessages();
|
|
306
309
|
chatHistory.push({role:'assistant',content:'Thinking...'});renderMessages();
|
|
307
310
|
apiPost('/api/chat',{message:msg,history:chatHistory.slice(0,-1)}).then(function(r){
|
|
308
311
|
chatHistory.pop();
|
|
309
312
|
if(r&&r.response){chatHistory.push({role:'assistant',content:r.response})}
|
|
310
313
|
else if(r&&r.error){chatHistory.push({role:'assistant',content:'Error: '+r.error})}
|
|
311
314
|
else{chatHistory.push({role:'assistant',content:'Error: no response from server'})}
|
|
312
|
-
renderMessages();
|
|
315
|
+
saveChatToStorage();renderMessages();
|
|
313
316
|
// Refresh data if an action was executed
|
|
314
317
|
if(r&&r.actions&&r.actions.length>0){
|
|
315
318
|
// Clear calendar cache so new events show up
|