nothumanallowed 13.5.199 → 14.0.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 +4 -2
- package/src/commands/ui.mjs +13 -6732
- package/src/constants.mjs +1 -1
- package/src/server/index.mjs +299 -0
- package/src/server/routes/agents.mjs +109 -0
- package/src/server/routes/calendar.mjs +115 -0
- package/src/server/routes/chat.mjs +350 -0
- package/src/server/routes/collab.mjs +97 -0
- package/src/server/routes/config.mjs +179 -0
- package/src/server/routes/drive.mjs +184 -0
- package/src/server/routes/email.mjs +428 -0
- package/src/server/routes/google-auth.mjs +58 -0
- package/src/server/routes/integrations.mjs +437 -0
- package/src/server/routes/studio.mjs +287 -0
- package/src/server/routes/tasks.mjs +116 -0
- package/src/server/routes/webcraft.mjs +1092 -0
- package/src/server/ws.mjs +44 -0
- package/src/services/email-db.mjs +32 -15
- package/src/services/tool-executor.mjs +702 -2
- package/src/ui-dist/3rdArmLogo.jpeg +0 -0
- package/src/ui-dist/NHALogo.jpeg +0 -0
- package/src/ui-dist/apple-touch-icon.png +0 -0
- package/src/ui-dist/assets/index-DBDRtTmR.js +423 -0
- package/src/ui-dist/assets/index-DyNVopKq.css +1 -0
- package/src/ui-dist/favicon-16x16.png +0 -0
- package/src/ui-dist/favicon-32x32.png +0 -0
- package/src/ui-dist/favicon.ico +0 -0
- package/src/ui-dist/favicon.svg +6 -0
- package/src/ui-dist/icon-192x192.png +0 -0
- package/src/ui-dist/icons.svg +24 -0
- package/src/ui-dist/index.html +17 -0
- package/src/services/web-ui.mjs +0 -10651
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket handler — broadcasts daemon events to the React UI.
|
|
3
|
+
* Uses the `ws` package already bundled in nha-cli.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { createRequire } from 'module';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
|
|
10
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
// Resolve `ws` from nha-cli's node_modules
|
|
12
|
+
const require = createRequire(import.meta.url);
|
|
13
|
+
// __dirname = packages/nha-cli/src/server/ → ../../ = packages/nha-cli/
|
|
14
|
+
const { WebSocketServer } = require(
|
|
15
|
+
path.resolve(__dirname, '../../node_modules/ws/index.js')
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
let wss = null;
|
|
19
|
+
|
|
20
|
+
export function setupWebSocket(server) {
|
|
21
|
+
wss = new WebSocketServer({ server, path: '/api' });
|
|
22
|
+
|
|
23
|
+
wss.on('connection', (ws) => {
|
|
24
|
+
ws.send(JSON.stringify({ type: 'connected', ts: Date.now() }));
|
|
25
|
+
|
|
26
|
+
ws.on('message', (data) => {
|
|
27
|
+
try {
|
|
28
|
+
const msg = JSON.parse(data.toString());
|
|
29
|
+
// Echo back for now — route-specific handlers can call broadcast()
|
|
30
|
+
broadcast({ type: 'echo', payload: msg });
|
|
31
|
+
} catch { /* ignore malformed */ }
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
ws.on('error', () => {});
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function broadcast(msg) {
|
|
39
|
+
if (!wss) return;
|
|
40
|
+
const data = JSON.stringify(msg);
|
|
41
|
+
for (const client of wss.clients) {
|
|
42
|
+
if (client.readyState === 1) client.send(data);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -424,18 +424,31 @@ export function deleteLabel(id) {
|
|
|
424
424
|
getDb().prepare('DELETE FROM email_labels WHERE id = ? AND is_system = 0').run(id);
|
|
425
425
|
}
|
|
426
426
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
427
|
+
const UPDATE_LABEL_SQL = `
|
|
428
|
+
UPDATE email_labels SET
|
|
429
|
+
total_count = (SELECT COUNT(*) FROM email_message_labels eml
|
|
430
|
+
JOIN email_messages m ON m.id = eml.message_id
|
|
431
|
+
WHERE eml.label_id = ? AND m.permanently_deleted = 0),
|
|
432
|
+
unread_count = (SELECT COUNT(*) FROM email_message_labels eml
|
|
433
|
+
JOIN email_messages m ON m.id = eml.message_id
|
|
434
|
+
LEFT JOIN email_message_state s ON s.message_id = m.id
|
|
435
|
+
WHERE eml.label_id = ? AND m.permanently_deleted = 0 AND (s.is_read IS NULL OR s.is_read = 0))
|
|
436
|
+
WHERE id = ?
|
|
437
|
+
`;
|
|
438
|
+
|
|
439
|
+
// Called from email-imap.mjs after a folder sync — updates all labels for the account
|
|
440
|
+
export function updateLabelCounts(accountId) {
|
|
441
|
+
const db = getDb();
|
|
442
|
+
const labels = db.prepare('SELECT id FROM email_labels WHERE account_id = ?').all(accountId);
|
|
443
|
+
const stmt = db.prepare(UPDATE_LABEL_SQL);
|
|
444
|
+
for (const lbl of labels) {
|
|
445
|
+
stmt.run(lbl.id, lbl.id, lbl.id);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// Called internally after adding/removing a single message from a label
|
|
450
|
+
function updateSingleLabelCount(db, labelId) {
|
|
451
|
+
db.prepare(UPDATE_LABEL_SQL).run(labelId, labelId, labelId);
|
|
439
452
|
}
|
|
440
453
|
|
|
441
454
|
// ── MESSAGE CRUD ───────────────────────────────────────────────────────────
|
|
@@ -494,13 +507,13 @@ export function insertAttachments(messageId, attachments) {
|
|
|
494
507
|
export function addMessageToLabel(messageId, labelId) {
|
|
495
508
|
const db = getDb();
|
|
496
509
|
db.prepare('INSERT OR IGNORE INTO email_message_labels (message_id, label_id) VALUES (?, ?)').run(messageId, labelId);
|
|
497
|
-
|
|
510
|
+
updateSingleLabelCount(db, labelId);
|
|
498
511
|
}
|
|
499
512
|
|
|
500
513
|
export function removeMessageFromLabel(messageId, labelId) {
|
|
501
514
|
const db = getDb();
|
|
502
515
|
db.prepare('DELETE FROM email_message_labels WHERE message_id = ? AND label_id = ?').run(messageId, labelId);
|
|
503
|
-
|
|
516
|
+
updateSingleLabelCount(db, labelId);
|
|
504
517
|
}
|
|
505
518
|
|
|
506
519
|
export function getMessageLabels(messageId) {
|
|
@@ -578,9 +591,13 @@ export function getThread(threadId, accountId) {
|
|
|
578
591
|
// ── STATE MUTATIONS (local only — never touches IMAP) ─────────────────────
|
|
579
592
|
|
|
580
593
|
export function markRead(messageId, isRead) {
|
|
581
|
-
|
|
594
|
+
const db = getDb();
|
|
595
|
+
db.prepare(`INSERT INTO email_message_state (message_id, is_read, is_starred) VALUES (?, ?, 0)
|
|
582
596
|
ON CONFLICT(message_id) DO UPDATE SET is_read = excluded.is_read, updated_at = datetime('now')`)
|
|
583
597
|
.run(messageId, isRead ? 1 : 0);
|
|
598
|
+
// Refresh label unread counts for this message's account
|
|
599
|
+
const msg = db.prepare('SELECT account_id FROM email_messages WHERE id = ?').get(messageId);
|
|
600
|
+
if (msg?.account_id) updateLabelCounts(msg.account_id);
|
|
584
601
|
}
|
|
585
602
|
|
|
586
603
|
export function markStarred(messageId, isStarred) {
|