neoagent 2.4.1-beta.35 → 2.4.1-beta.37
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/flutter_app/lib/main_operations.dart +1246 -691
- package/package.json +1 -1
- package/server/db/ftsQuery.js +27 -0
- package/server/middleware/auth.js +1 -40
- package/server/public/.last_build_id +1 -1
- package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
- package/server/public/flutter_bootstrap.js +1 -1
- package/server/public/main.dart.js +68156 -67730
- package/server/routes/agents.js +1 -1
- package/server/routes/auth.js +3 -1
- package/server/routes/screenHistory.js +14 -8
- package/server/routes/triggers.js +4 -4
- package/server/services/ai/completion.js +44 -0
- package/server/services/ai/engine.js +119 -501
- package/server/services/ai/imageAnalysis.js +9 -5
- package/server/services/ai/logFormat.js +46 -0
- package/server/services/ai/messagingFallback.js +228 -0
- package/server/services/ai/models.js +37 -24
- package/server/services/ai/providerRetry.js +169 -0
- package/server/services/ai/providers/grok.js +5 -67
- package/server/services/ai/providers/nvidia.js +6 -29
- package/server/services/ai/providers/ollama.js +48 -28
- package/server/services/ai/providers/openai.js +2 -27
- package/server/services/ai/providers/openaiCompatible.js +70 -0
- package/server/services/ai/taskAnalysis.js +4 -1
- package/server/services/ai/toolEvidence.js +207 -0
- package/server/services/ai/toolSelector.js +8 -1
- package/server/services/memory/manager.js +1 -7
- package/server/services/websocket.js +8 -2
package/server/routes/agents.js
CHANGED
|
@@ -186,7 +186,7 @@ router.post('/:id/abort', (req, res) => {
|
|
|
186
186
|
const run = db.prepare('SELECT id FROM agent_runs WHERE id = ? AND user_id = ?').get(req.params.id, req.session.userId);
|
|
187
187
|
if (!run) return res.status(404).json({ error: 'Run not found' });
|
|
188
188
|
const engine = req.app.locals.agentEngine;
|
|
189
|
-
engine.abort(req.params.id);
|
|
189
|
+
engine.abort(req.params.id, { userId: req.session.userId });
|
|
190
190
|
res.json({ success: true });
|
|
191
191
|
} catch (err) {
|
|
192
192
|
res.status(500).json({ error: sanitizeError(err) });
|
package/server/routes/auth.js
CHANGED
|
@@ -129,7 +129,9 @@ function readAuthenticatedUser(req) {
|
|
|
129
129
|
if (!user) {
|
|
130
130
|
try {
|
|
131
131
|
req.session.destroy(() => {});
|
|
132
|
-
} catch (
|
|
132
|
+
} catch (destroyError) {
|
|
133
|
+
console.warn('Auth stale-session cleanup failed:', destroyError.message);
|
|
134
|
+
}
|
|
133
135
|
return null;
|
|
134
136
|
}
|
|
135
137
|
return user;
|
|
@@ -2,21 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
const express = require('express');
|
|
4
4
|
const db = require('../db/database');
|
|
5
|
+
const { buildFtsQuery } = require('../db/ftsQuery');
|
|
6
|
+
const { requireAuth } = require('../middleware/auth');
|
|
5
7
|
const { getErrorMessage } = require('../services/bootstrap_helpers');
|
|
6
8
|
|
|
7
9
|
const router = express.Router();
|
|
8
10
|
|
|
11
|
+
router.use(requireAuth);
|
|
12
|
+
|
|
9
13
|
router.get('/search', (req, res) => {
|
|
10
14
|
const { q, limit = 50, offset = 0 } = req.query;
|
|
11
|
-
|
|
12
|
-
if (!req.user || !req.user.id) {
|
|
13
|
-
return res.status(401).json({ error: 'Unauthorized' });
|
|
14
|
-
}
|
|
15
|
+
const userId = req.session.userId;
|
|
15
16
|
|
|
16
17
|
try {
|
|
17
18
|
let results = [];
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
const ftsQuery = q ? buildFtsQuery(q) : null;
|
|
20
|
+
if (ftsQuery) {
|
|
21
|
+
// Full text search. buildFtsQuery sanitizes user input so FTS5 operator
|
|
22
|
+
// characters (hyphens, AND/OR/NOT) don't throw and 500 the request.
|
|
20
23
|
results = db.prepare(`
|
|
21
24
|
SELECT s.id, s.timestamp, s.app_name, s.text_content
|
|
22
25
|
FROM screen_history_fts fts
|
|
@@ -24,7 +27,10 @@ router.get('/search', (req, res) => {
|
|
|
24
27
|
WHERE screen_history_fts MATCH ? AND s.user_id = ?
|
|
25
28
|
ORDER BY s.timestamp DESC
|
|
26
29
|
LIMIT ? OFFSET ?
|
|
27
|
-
`).all(
|
|
30
|
+
`).all(ftsQuery, userId, Number(limit), Number(offset));
|
|
31
|
+
} else if (q) {
|
|
32
|
+
// Query had no usable search tokens — return no matches rather than error.
|
|
33
|
+
results = [];
|
|
28
34
|
} else {
|
|
29
35
|
// Recent history
|
|
30
36
|
results = db.prepare(`
|
|
@@ -33,7 +39,7 @@ router.get('/search', (req, res) => {
|
|
|
33
39
|
WHERE user_id = ?
|
|
34
40
|
ORDER BY timestamp DESC
|
|
35
41
|
LIMIT ? OFFSET ?
|
|
36
|
-
`).all(
|
|
42
|
+
`).all(userId, Number(limit), Number(offset));
|
|
37
43
|
}
|
|
38
44
|
|
|
39
45
|
res.json({ results });
|
|
@@ -13,10 +13,10 @@ router.post('/geofence', async (req, res) => {
|
|
|
13
13
|
const { label, latitude, longitude, radius_meters, action } = req.body;
|
|
14
14
|
|
|
15
15
|
try {
|
|
16
|
-
const userRow = db.prepare('SELECT id FROM users WHERE id = ?').get(req.
|
|
16
|
+
const userRow = db.prepare('SELECT id FROM users WHERE id = ?').get(req.session.userId);
|
|
17
17
|
if (!userRow) return res.status(401).json({ error: 'Unauthorized' });
|
|
18
18
|
|
|
19
|
-
console.log(`[Triggers] Geofence entered: ${label} by user ${req.
|
|
19
|
+
console.log(`[Triggers] Geofence entered: ${label} by user ${req.session.userId}`);
|
|
20
20
|
|
|
21
21
|
res.json({ success: true, message: 'Geofence trigger processed' });
|
|
22
22
|
} catch (err) {
|
|
@@ -29,14 +29,14 @@ router.post('/geofence', async (req, res) => {
|
|
|
29
29
|
Promise.resolve().then(() => {
|
|
30
30
|
const agentEngine = req.app.locals.agentEngine;
|
|
31
31
|
if (!agentEngine) return;
|
|
32
|
-
const defaultAgentId = db.prepare('SELECT id FROM agents WHERE user_id = ? ORDER BY is_default DESC LIMIT 1').get(req.
|
|
32
|
+
const defaultAgentId = db.prepare('SELECT id FROM agents WHERE user_id = ? ORDER BY is_default DESC LIMIT 1').get(req.session.userId)?.id;
|
|
33
33
|
if (!defaultAgentId) return;
|
|
34
34
|
const prompt = [
|
|
35
35
|
`A geofence event was triggered.`,
|
|
36
36
|
`Location label: ${label || 'unknown'}`,
|
|
37
37
|
action ? `Suggested action: ${action}` : 'Check if there are any active reminders or tasks related to this location.',
|
|
38
38
|
].join('\n');
|
|
39
|
-
return agentEngine.run(req.
|
|
39
|
+
return agentEngine.run(req.session.userId, prompt, {
|
|
40
40
|
agentId: defaultAgentId,
|
|
41
41
|
triggerSource: 'tasks',
|
|
42
42
|
context: { source: 'geofence', label, latitude, longitude, radius_meters },
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Decides whether the agent may accept a `task_complete` signal, balancing the
|
|
4
|
+
// model's self-reported confidence against the confidence the run requires.
|
|
5
|
+
|
|
6
|
+
function normalizeCompletionConfidence(value) {
|
|
7
|
+
const normalized = String(value || '').trim().toLowerCase();
|
|
8
|
+
if (normalized === 'high' || normalized === 'medium' || normalized === 'low') return normalized;
|
|
9
|
+
return 'medium';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function completionConfidenceRank(value) {
|
|
13
|
+
const normalized = normalizeCompletionConfidence(value);
|
|
14
|
+
if (normalized === 'high') return 3;
|
|
15
|
+
if (normalized === 'medium') return 2;
|
|
16
|
+
return 1;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function shouldAcceptTaskComplete({ confidence, requiredConfidence, iteration, maxIterations }) {
|
|
20
|
+
const required = normalizeCompletionConfidence(requiredConfidence || 'medium');
|
|
21
|
+
const actual = normalizeCompletionConfidence(confidence || 'medium');
|
|
22
|
+
if (completionConfidenceRank(actual) >= completionConfidenceRank(required)) {
|
|
23
|
+
return { accept: true, reason: '' };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const iterationsRemaining = Math.max(0, Number(maxIterations || 0) - Number(iteration || 0));
|
|
27
|
+
if (iterationsRemaining <= 1) {
|
|
28
|
+
return {
|
|
29
|
+
accept: true,
|
|
30
|
+
reason: `Accepted ${actual}-confidence completion at the iteration limit; final verifier will calibrate the answer.`,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
accept: false,
|
|
36
|
+
reason: `Completion confidence "${actual}" is below required "${required}". Continue with verification, recovery, or a narrower truthful result before completing.`,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = {
|
|
41
|
+
normalizeCompletionConfidence,
|
|
42
|
+
completionConfidenceRank,
|
|
43
|
+
shouldAcceptTaskComplete,
|
|
44
|
+
};
|