-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathrecommend-scoring.js
More file actions
110 lines (95 loc) · 4.25 KB
/
Copy pathrecommend-scoring.js
File metadata and controls
110 lines (95 loc) · 4.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/**
* Agent Connect — Node Scoring Algorithms
*
* Weight calculations, protocol preference logic, and node ranking
* for the autonomous agent recommendation engine.
*/
import { formatP2P } from 'blue-js-sdk';
// ─── Node Scoring ───────────────────────────────────────────────────────────
/**
* Score a single node based on protocol, country match, pricing, quality, and load.
*
* @param {object} node - Node data
* @param {boolean} isExactCountry - Whether this node is in the exact requested country
* @param {boolean} isNearby - Whether this node is in a nearby country
* @param {string} priority - Scoring priority: 'reliability', 'cost', 'speed', or 'location'
* @returns {object} Node with _score, _price, _isWG fields attached
*/
export function scoreNode(node, isExactCountry, isNearby, priority) {
let score = 50; // base
// Protocol bonus
const isWG = (node.service_type || node.serviceType) === 2;
if (isWG) score += 15; // WireGuard more reliable
// Country bonus
if (isExactCountry) score += 30;
else if (isNearby) score += 15;
// Pricing bonus (cheaper = better if priority is cost)
const gbPrices = node.gigabyte_prices || [];
const udvpnPrice = gbPrices.find(p => p.denom === 'udvpn');
const price = parseInt(udvpnPrice?.quote_value || udvpnPrice?.amount || '999999999', 10);
if (priority === 'cost') {
score += Math.max(0, 20 - (price / 50000)); // cheaper gets more points
}
// Quality score from SDK (if enriched)
if (node.qualityScore) score += node.qualityScore * 0.2;
// Peer count: fewer peers = less loaded
if (node.peers !== undefined) {
if (node.peers < 5) score += 10;
else if (node.peers < 20) score += 5;
else score -= 5;
}
return { ...node, _score: Math.round(score), _price: price, _isWG: isWG };
}
// ─── Ranking ────────────────────────────────────────────────────────────────
/**
* Build a ranked list of nodes from exact-country, nearby, and remaining pools.
*
* @param {object[]} exactCountryNodes - Nodes in the exact requested country
* @param {object[]} nearbyNodes - Nodes in nearby countries
* @param {object[]} allCandidates - All candidate nodes (superset)
* @param {string} priority - Scoring priority
* @param {number} maxNodes - Maximum nodes to return
* @returns {object[]} Ranked nodes with scoring metadata, sorted by _score descending
*/
export function rankNodes(exactCountryNodes, nearbyNodes, allCandidates, priority, maxNodes) {
const ranked = [];
for (const n of exactCountryNodes) {
ranked.push(scoreNode(n, true, false, priority));
}
for (const n of nearbyNodes) {
ranked.push(scoreNode(n, false, true, priority));
}
// Fill rest from any nodes (not already included)
const included = new Set(ranked.map(n => n.address || n.acc_address));
for (const n of allCandidates) {
const addr = n.address || n.acc_address;
if (!included.has(addr)) {
ranked.push(scoreNode(n, false, false, priority));
}
}
// Sort by score descending
ranked.sort((a, b) => b._score - a._score);
return ranked.slice(0, maxNodes);
}
// ─── Node Formatting ────────────────────────────────────────────────────────
/**
* Format a node for the recommendation response.
*
* @param {object} node - Scored node with _score, _price, _isWG, _fallbackCountry
* @returns {object} Clean recommendation object for the agent
*/
export function formatNode(node) {
return {
address: node.address || node.acc_address,
country: node.country || node._fallbackCountry || null,
protocol: node._isWG ? 'wireguard' : 'v2ray',
score: node._score || 0,
pricePerGb: node._price ? { udvpn: node._price, p2p: formatP2P(node._price) } : null,
peers: node.peers ?? null,
reason: node._fallbackCountry
? `Fallback from requested country (nearest: ${node._fallbackCountry})`
: node._score >= 80 ? 'High reliability score'
: node._score >= 60 ? 'Good match'
: 'Available',
};
}