neoagent 2.1.17-beta.17 → 2.1.17-beta.18
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
CHANGED
|
@@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"425cfb54d01a9472b3e81d9e76fd63a4a44cfb
|
|
|
37
37
|
|
|
38
38
|
_flutter.loader.load({
|
|
39
39
|
serviceWorkerSettings: {
|
|
40
|
-
serviceWorkerVersion: "
|
|
40
|
+
serviceWorkerVersion: "2696186693" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
|
|
41
41
|
}
|
|
42
42
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
+
const crypto = require('crypto');
|
|
3
4
|
const db = require('../../db/database');
|
|
4
5
|
const { DATA_DIR } = require('../../../runtime/paths');
|
|
5
6
|
|
|
@@ -71,6 +72,17 @@ function compactToolDefinition(tool, options = {}) {
|
|
|
71
72
|
return compact;
|
|
72
73
|
}
|
|
73
74
|
|
|
75
|
+
function normalizeNotifyMessage(content) {
|
|
76
|
+
return String(content || '')
|
|
77
|
+
.replace(/\s+/g, ' ')
|
|
78
|
+
.trim()
|
|
79
|
+
.toLowerCase();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function hashNotifyMessage(content) {
|
|
83
|
+
return crypto.createHash('sha256').update(String(content || '')).digest('hex');
|
|
84
|
+
}
|
|
85
|
+
|
|
74
86
|
/**
|
|
75
87
|
* Returns the list of available tools for the agent.
|
|
76
88
|
* @param {object} app - Express app instance.
|
|
@@ -1564,6 +1576,15 @@ async function executeTool(toolName, args, context, engine) {
|
|
|
1564
1576
|
throw new Error('Messaging manager not available');
|
|
1565
1577
|
}
|
|
1566
1578
|
|
|
1579
|
+
const runState = runId ? engine.activeRuns.get(runId) : null;
|
|
1580
|
+
if (runState?.messagingSent) {
|
|
1581
|
+
return {
|
|
1582
|
+
sent: false,
|
|
1583
|
+
skipped: true,
|
|
1584
|
+
reason: 'A notification was already sent in this run; duplicate scheduler/heartbeat message was suppressed.'
|
|
1585
|
+
};
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1567
1588
|
const loadDefaultTarget = () => ({
|
|
1568
1589
|
platform: db.prepare('SELECT value FROM user_settings WHERE user_id = ? AND key = ?')
|
|
1569
1590
|
.get(userId, 'last_platform')?.value || null,
|
|
@@ -1587,6 +1608,22 @@ async function executeTool(toolName, args, context, engine) {
|
|
|
1587
1608
|
}
|
|
1588
1609
|
}
|
|
1589
1610
|
|
|
1611
|
+
if (triggerSource === 'scheduler' && taskId && taskConfig) {
|
|
1612
|
+
const normalized = normalizeNotifyMessage(message);
|
|
1613
|
+
const newHash = hashNotifyMessage(normalized);
|
|
1614
|
+
const previousHash = typeof taskConfig.lastNotifyHash === 'string' ? taskConfig.lastNotifyHash : null;
|
|
1615
|
+
const previousAt = Number(taskConfig.lastNotifyAtMs || 0);
|
|
1616
|
+
const dedupeWindowMs = 2 * 60 * 60 * 1000;
|
|
1617
|
+
if (normalized && previousHash && previousHash === newHash && previousAt > 0 && (Date.now() - previousAt) < dedupeWindowMs) {
|
|
1618
|
+
return {
|
|
1619
|
+
sent: false,
|
|
1620
|
+
skipped: true,
|
|
1621
|
+
deduped: true,
|
|
1622
|
+
reason: 'Duplicate scheduler notification suppressed (same content within 2 hours).'
|
|
1623
|
+
};
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1590
1627
|
const fallbackTarget = loadDefaultTarget();
|
|
1591
1628
|
const candidateTargets = [];
|
|
1592
1629
|
const seenTargets = new Set();
|
|
@@ -1626,7 +1663,16 @@ async function executeTool(toolName, args, context, engine) {
|
|
|
1626
1663
|
.run(JSON.stringify(taskConfig), taskId, userId);
|
|
1627
1664
|
}
|
|
1628
1665
|
|
|
1629
|
-
|
|
1666
|
+
if (taskId && taskConfig && triggerSource === 'scheduler') {
|
|
1667
|
+
const normalized = normalizeNotifyMessage(message);
|
|
1668
|
+
if (normalized) {
|
|
1669
|
+
taskConfig.lastNotifyHash = hashNotifyMessage(normalized);
|
|
1670
|
+
taskConfig.lastNotifyAtMs = Date.now();
|
|
1671
|
+
db.prepare('UPDATE scheduled_tasks SET task_config = ? WHERE id = ? AND user_id = ?')
|
|
1672
|
+
.run(JSON.stringify(taskConfig), taskId, userId);
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1630
1676
|
if (runState) {
|
|
1631
1677
|
runState.messagingSent = true;
|
|
1632
1678
|
runState.lastSentMessage = message;
|
|
@@ -291,6 +291,15 @@ class Scheduler {
|
|
|
291
291
|
: '';
|
|
292
292
|
}
|
|
293
293
|
|
|
294
|
+
notifyHint += [
|
|
295
|
+
'',
|
|
296
|
+
'Critical reliability rules for scheduled notifications:',
|
|
297
|
+
'- For time-sensitive external-world claims (for example: mission status, launch timeline, incidents, markets, weather, sports, or wording like "today/now/yesterday"), do not rely on memory alone.',
|
|
298
|
+
'- Verify with at least one fresh source tool in this run before notifying (for example browser_navigate, http_request, search_files where applicable).',
|
|
299
|
+
'- If you cannot verify current status, send a short uncertainty notice and ask whether to retry later. Do not invent timeline details.',
|
|
300
|
+
'- Send at most one proactive user notification per run unless the task explicitly requires multi-part output.'
|
|
301
|
+
].join('\n');
|
|
302
|
+
|
|
294
303
|
const taskContext = `[SYSTEM: Executing Scheduled Task]\nTask Name: ${taskName}\nSchedule: ${scheduleInfo}\n\n`;
|
|
295
304
|
const userPrompt = config.prompt || `You have been triggered by the scheduler to run the background task "${taskName}". Please execute any necessary checks or actions associated with this task.`;
|
|
296
305
|
const basePrompt = taskContext + userPrompt + notifyHint;
|