neoagent 2.2.1-beta.5 → 2.2.1-beta.7

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.
Files changed (49) hide show
  1. package/docs/automation.md +2 -2
  2. package/docs/capabilities.md +7 -10
  3. package/docs/hardware.md +4 -7
  4. package/docs/index.md +6 -7
  5. package/docs/integrations.md +1 -1
  6. package/docs/operations.md +1 -1
  7. package/docs/why-neoagent.md +2 -2
  8. package/package.json +1 -1
  9. package/server/db/database.js +76 -61
  10. package/server/http/routes.js +1 -2
  11. package/server/public/assets/AssetManifest.json +1 -1
  12. package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
  13. package/server/public/flutter_bootstrap.js +1 -1
  14. package/server/public/main.dart.js +65118 -64805
  15. package/server/routes/{scheduler.js → tasks.js} +31 -29
  16. package/server/routes/widgets.js +7 -7
  17. package/server/services/ai/capabilityHealth.js +4 -4
  18. package/server/services/ai/engine.js +31 -12
  19. package/server/services/ai/systemPrompt.js +7 -7
  20. package/server/services/ai/taskAnalysis.js +3 -3
  21. package/server/services/ai/toolResult.js +6 -8
  22. package/server/services/ai/tools.js +62 -95
  23. package/server/services/commands/router.js +14 -6
  24. package/server/services/integrations/whatsapp/provider.js +23 -1
  25. package/server/services/manager.js +14 -14
  26. package/server/services/memory/manager.js +7 -7
  27. package/server/services/memory/policy.js +1 -1
  28. package/server/services/messaging/formatting_guides.js +0 -4
  29. package/server/services/messaging/manager.js +0 -2
  30. package/server/services/tasks/adapters/gmail_message_received.js +36 -0
  31. package/server/services/tasks/adapters/index.js +10 -0
  32. package/server/services/tasks/adapters/outlook_email_received.js +38 -0
  33. package/server/services/tasks/adapters/schedule.js +57 -0
  34. package/server/services/tasks/adapters/slack_message_received.js +39 -0
  35. package/server/services/tasks/adapters/teams_message_received.js +39 -0
  36. package/server/services/tasks/adapters/whatsapp_personal_message_received.js +42 -0
  37. package/server/services/tasks/integration_runtime.js +260 -0
  38. package/server/services/tasks/runtime.js +539 -0
  39. package/server/services/{scheduler/cron_utils.js → tasks/schedule_utils.js} +2 -0
  40. package/server/services/tasks/security.js +60 -0
  41. package/server/services/tasks/task_repository.js +162 -0
  42. package/server/services/tasks/trigger_registry.js +29 -0
  43. package/server/services/tasks/utils.js +45 -0
  44. package/server/services/websocket.js +1 -1
  45. package/server/services/widgets/service.js +38 -25
  46. package/server/routes/wearable_device.js +0 -147
  47. package/server/services/messaging/waveshare_wearable.js +0 -40
  48. package/server/services/scheduler/cron.js +0 -580
  49. package/server/services/wearables/device_auth.js +0 -228
@@ -1,228 +0,0 @@
1
- const crypto = require('crypto');
2
- const db = require('../../db/database');
3
-
4
- const DEFAULT_PAIRING_TTL_MINUTES = 10;
5
-
6
- function sha256(value) {
7
- return crypto.createHash('sha256').update(String(value || '')).digest('hex');
8
- }
9
-
10
- function randomToken(prefix = 'nwd_', bytes = 36) {
11
- return `${prefix}${crypto.randomBytes(bytes).toString('base64url')}`;
12
- }
13
-
14
- function randomDigits(length = 6) {
15
- const min = 10 ** (length - 1);
16
- const max = (10 ** length) - 1;
17
- return String(Math.floor(Math.random() * (max - min + 1)) + min);
18
- }
19
-
20
- function isoDate(offsetMs = 0) {
21
- return new Date(Date.now() + offsetMs).toISOString();
22
- }
23
-
24
- function safeJson(value) {
25
- try {
26
- return JSON.stringify(value || {});
27
- } catch {
28
- return '{}';
29
- }
30
- }
31
-
32
- class WearableDeviceAuth {
33
- createPairingCode(userId, options = {}) {
34
- const ttlMinutes = Math.max(1, Math.min(30, Number(options.ttlMinutes || DEFAULT_PAIRING_TTL_MINUTES)));
35
- const code = randomDigits(6);
36
- const pairingId = crypto.randomUUID();
37
- const expiresAt = isoDate(ttlMinutes * 60 * 1000);
38
-
39
- db.prepare(
40
- `INSERT INTO wearable_pairing_codes (
41
- id, user_id, agent_id, code_hash, status, metadata_json, expires_at
42
- ) VALUES (?, ?, ?, ?, 'active', ?, ?)`
43
- ).run(
44
- pairingId,
45
- userId,
46
- options.agentId || null,
47
- sha256(code),
48
- safeJson({
49
- source: options.source || 'app',
50
- deviceHint: options.deviceHint || null,
51
- }),
52
- expiresAt,
53
- );
54
-
55
- return {
56
- id: pairingId,
57
- code,
58
- expiresAt,
59
- ttlMinutes,
60
- };
61
- }
62
-
63
- claimPairingCode(code, payload = {}) {
64
- const row = db.prepare(
65
- `SELECT * FROM wearable_pairing_codes
66
- WHERE code_hash = ? AND status = 'active'
67
- ORDER BY datetime(created_at) DESC
68
- LIMIT 1`
69
- ).get(sha256(code));
70
-
71
- if (!row) {
72
- const error = new Error('Pairing code is invalid.');
73
- error.status = 404;
74
- throw error;
75
- }
76
-
77
- if (Date.parse(row.expires_at) <= Date.now()) {
78
- db.prepare(`UPDATE wearable_pairing_codes SET status = 'expired' WHERE id = ?`).run(row.id);
79
- const error = new Error('Pairing code expired.');
80
- error.status = 410;
81
- throw error;
82
- }
83
-
84
- const token = randomToken();
85
- const tokenId = crypto.randomUUID();
86
- const deviceId = String(payload.deviceId || '').trim().slice(0, 120) || crypto.randomUUID();
87
- const deviceName = String(payload.deviceName || 'NeoOS Wearable').trim().slice(0, 120);
88
- const macAddress = String(payload.macAddress || '').trim().slice(0, 64) || null;
89
- const protocol = String(payload.protocol || 'waveshare_amoled_1_8').trim().slice(0, 80);
90
- const firmwareVersion = String(payload.firmwareVersion || '').trim().slice(0, 80) || null;
91
-
92
- const tx = db.transaction(() => {
93
- db.prepare(
94
- `UPDATE wearable_pairing_codes
95
- SET status = 'claimed', claimed_at = datetime('now')
96
- WHERE id = ?`
97
- ).run(row.id);
98
-
99
- db.prepare(
100
- `INSERT INTO wearable_device_tokens (
101
- id, user_id, agent_id, token_hash, device_id, device_name,
102
- mac_address, protocol, firmware_version, status,
103
- last_seen_at, last_connected_at, metadata_json
104
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'active', datetime('now'), datetime('now'), ?)`
105
- ).run(
106
- tokenId,
107
- row.user_id,
108
- row.agent_id || null,
109
- sha256(token),
110
- deviceId,
111
- deviceName,
112
- macAddress,
113
- protocol,
114
- firmwareVersion,
115
- safeJson({
116
- pairingCodeId: row.id,
117
- claimedAt: new Date().toISOString(),
118
- }),
119
- );
120
- });
121
-
122
- tx();
123
-
124
- return {
125
- token,
126
- tokenId,
127
- userId: row.user_id,
128
- agentId: row.agent_id || null,
129
- deviceId,
130
- deviceName,
131
- protocol,
132
- };
133
- }
134
-
135
- validateBearerToken(token) {
136
- if (!token) return null;
137
- const row = db.prepare(
138
- `SELECT * FROM wearable_device_tokens
139
- WHERE token_hash = ? AND status = 'active' AND revoked_at IS NULL
140
- LIMIT 1`
141
- ).get(sha256(token));
142
- if (!row) return null;
143
- return row;
144
- }
145
-
146
- touchToken(tokenId) {
147
- db.prepare(
148
- `UPDATE wearable_device_tokens
149
- SET last_seen_at = datetime('now')
150
- WHERE id = ?`
151
- ).run(tokenId);
152
- }
153
-
154
- getLastCursor(tokenId) {
155
- const row = db.prepare(
156
- `SELECT last_message_id AS lastMessageId
157
- FROM wearable_device_message_cursors
158
- WHERE token_id = ?`
159
- ).get(tokenId);
160
- return Number(row?.lastMessageId || 0);
161
- }
162
-
163
- setLastCursor(tokenId, lastMessageId) {
164
- db.prepare(
165
- `INSERT INTO wearable_device_message_cursors (token_id, last_message_id, updated_at)
166
- VALUES (?, ?, datetime('now'))
167
- ON CONFLICT(token_id) DO UPDATE
168
- SET last_message_id = excluded.last_message_id,
169
- updated_at = datetime('now')`
170
- ).run(tokenId, Number(lastMessageId || 0));
171
- }
172
-
173
- getPendingResponses(tokenRow, limit = 5) {
174
- const lastId = this.getLastCursor(tokenRow.id);
175
- return db.prepare(
176
- `SELECT id, content, created_at AS createdAt, metadata
177
- FROM messages
178
- WHERE user_id = ?
179
- AND role = 'assistant'
180
- AND platform = 'waveshare_wearable'
181
- AND id > ?
182
- ORDER BY id ASC
183
- LIMIT ?`
184
- ).all(tokenRow.user_id, lastId, Math.max(1, Math.min(20, Number(limit || 5))));
185
- }
186
-
187
- listDevicesForUser(userId, options = {}) {
188
- const rows = db.prepare(
189
- `SELECT
190
- t.id,
191
- t.device_id AS deviceId,
192
- t.device_name AS name,
193
- t.mac_address AS macAddress,
194
- t.protocol,
195
- t.firmware_version AS firmwareVersion,
196
- t.status,
197
- t.last_seen_at AS lastSeenAt,
198
- t.last_connected_at AS lastConnectedAt,
199
- t.created_at AS createdAt,
200
- d.battery_level AS batteryLevel,
201
- d.updated_at AS deviceUpdatedAt,
202
- d.status AS runtimeStatus
203
- FROM wearable_device_tokens t
204
- LEFT JOIN wearable_devices d
205
- ON d.user_id = t.user_id
206
- AND d.mac_address = t.mac_address
207
- WHERE t.user_id = ?
208
- AND (? IS NULL OR t.agent_id = ?)
209
- AND t.status = 'active'
210
- AND t.revoked_at IS NULL
211
- ORDER BY datetime(t.last_seen_at) DESC, datetime(t.created_at) DESC`
212
- ).all(userId, options.agentId || null, options.agentId || null);
213
-
214
- const now = Date.now();
215
- return rows.map((row) => {
216
- const seenMs = row.lastSeenAt ? Date.parse(row.lastSeenAt) : 0;
217
- const isConnected = seenMs > 0 && (now - seenMs) <= 90_000;
218
- return {
219
- ...row,
220
- connected: isConnected,
221
- };
222
- });
223
- }
224
- }
225
-
226
- module.exports = {
227
- wearableDeviceAuth: new WearableDeviceAuth(),
228
- };