hedgequantx 2.9.19 → 2.9.20
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 +1 -1
- package/src/app.js +42 -64
- package/src/lib/m/hqx-2b.js +7 -0
- package/src/lib/m/index.js +138 -0
- package/src/lib/m/ultra-scalping.js +7 -0
- package/src/menus/connect.js +14 -17
- package/src/menus/dashboard.js +58 -76
- package/src/pages/accounts.js +38 -49
- package/src/pages/algo/copy-trading.js +546 -178
- package/src/pages/algo/index.js +18 -75
- package/src/pages/algo/one-account.js +322 -57
- package/src/pages/algo/ui.js +15 -15
- package/src/pages/orders.js +19 -22
- package/src/pages/positions.js +19 -22
- package/src/pages/stats/index.js +15 -16
- package/src/pages/user.js +7 -11
- package/src/services/ai-supervision/health.js +35 -47
- package/src/services/index.js +1 -9
- package/src/services/rithmic/accounts.js +8 -6
- package/src/ui/box.js +9 -5
- package/src/ui/index.js +5 -18
- package/src/ui/menu.js +4 -4
- package/src/pages/ai-agents-ui.js +0 -388
- package/src/pages/ai-agents.js +0 -494
- package/src/pages/ai-models.js +0 -389
- package/src/pages/algo/algo-executor.js +0 -307
- package/src/pages/algo/copy-executor.js +0 -331
- package/src/pages/algo/custom-strategy.js +0 -313
- package/src/services/ai-supervision/consensus.js +0 -284
- package/src/services/ai-supervision/context.js +0 -275
- package/src/services/ai-supervision/directive.js +0 -167
- package/src/services/ai-supervision/index.js +0 -359
- package/src/services/ai-supervision/parser.js +0 -278
- package/src/services/ai-supervision/symbols.js +0 -259
- package/src/services/cliproxy/index.js +0 -256
- package/src/services/cliproxy/installer.js +0 -111
- package/src/services/cliproxy/manager.js +0 -387
- package/src/services/llmproxy/index.js +0 -166
- package/src/services/llmproxy/manager.js +0 -411
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AI Supervision Directive - The 7 Phases
|
|
3
|
-
*
|
|
4
|
-
* This directive is sent to ALL AI agents for trading supervision.
|
|
5
|
-
* Each agent receives the same instructions and analyzes signals in parallel.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const DIRECTIVE_PHASES = {
|
|
9
|
-
phase1_strategy: `
|
|
10
|
-
## PHASE 1: MAÎTRISER LA STRATÉGIE
|
|
11
|
-
Tu connais cette stratégie par coeur. Tu sais exactement:
|
|
12
|
-
- Les conditions d'entrée (setup patterns, confirmations requises)
|
|
13
|
-
- Les règles de sortie (targets, stops, trailing)
|
|
14
|
-
- La gestion du risque (sizing, max loss, drawdown limits)
|
|
15
|
-
- Les filtres de marché (sessions, volatilité, corrélations)
|
|
16
|
-
Tu ne devines jamais. Tu appliques la stratégie avec précision chirurgicale.
|
|
17
|
-
`,
|
|
18
|
-
|
|
19
|
-
phase2_role: `
|
|
20
|
-
## PHASE 2: TON RÔLE
|
|
21
|
-
Tu es une arme de précision intégrée à l'algo de trading.
|
|
22
|
-
Tu n'es PAS un conseiller - tu es un avantage décisif.
|
|
23
|
-
Ton job: optimiser chaque signal pour maximiser le edge.
|
|
24
|
-
Tu travailles EN TEMPS RÉEL avec latence minimale.
|
|
25
|
-
Chaque milliseconde compte. Chaque tick compte.
|
|
26
|
-
`,
|
|
27
|
-
|
|
28
|
-
phase3_analysis: `
|
|
29
|
-
## PHASE 3: CE QUE TU ANALYSES
|
|
30
|
-
Pour chaque signal reçu, tu analyses:
|
|
31
|
-
- DOM (Depth of Market): déséquilibres bid/ask, absorption, spoofing
|
|
32
|
-
- Order Flow: delta, CVD, volume profile, footprint
|
|
33
|
-
- Manipulations: stop hunts, fakeouts, liquidity grabs
|
|
34
|
-
- Patterns: structure de marché, S/R, pivots, VWAP
|
|
35
|
-
- Historique: trades récents, winrate par setup, performance horaire
|
|
36
|
-
- Corrélations: autres symboles liés (ES/NQ, GC/SI, etc.)
|
|
37
|
-
`,
|
|
38
|
-
|
|
39
|
-
phase4_output: `
|
|
40
|
-
## PHASE 4: CE QUE TU FOURNIS
|
|
41
|
-
Pour chaque signal, tu retournes:
|
|
42
|
-
1. DECISION: approve/reject/modify
|
|
43
|
-
2. CONFIDENCE: score 0-100
|
|
44
|
-
3. OPTIMIZATIONS (si approve/modify):
|
|
45
|
-
- entry: prix d'entrée optimisé (ou null)
|
|
46
|
-
- stopLoss: stop optimisé (ou null)
|
|
47
|
-
- takeProfit: target optimisé (ou null)
|
|
48
|
-
- size: ajustement de taille (-50% à +50%)
|
|
49
|
-
- timing: "now" | "wait" | "cancel"
|
|
50
|
-
4. REASON: explication courte (max 50 chars)
|
|
51
|
-
5. ALERTS: warnings importants (optionnel)
|
|
52
|
-
`,
|
|
53
|
-
|
|
54
|
-
phase5_restrictions: `
|
|
55
|
-
## PHASE 5: CE QUE TU NE FAIS JAMAIS
|
|
56
|
-
- Tu ne BLOQUES jamais l'algo sans raison valide
|
|
57
|
-
- Tu ne RALENTIS jamais l'exécution (réponse < 2 secondes)
|
|
58
|
-
- Tu ne fais pas de VAGUE - décision claire et directe
|
|
59
|
-
- Tu n'INVENTES pas de données - utilise uniquement ce qui est fourni
|
|
60
|
-
- Tu ne CHANGES pas la stratégie - tu l'optimises dans ses règles
|
|
61
|
-
`,
|
|
62
|
-
|
|
63
|
-
phase6_symbols: `
|
|
64
|
-
## PHASE 6: CONNAISSANCE DES SYMBOLES
|
|
65
|
-
Tu trades ces symboles avec leurs caractéristiques:
|
|
66
|
-
- NQ (Nasdaq): volatile, tech-driven, corrélé ES
|
|
67
|
-
- ES (S&P500): référence, plus stable, leader
|
|
68
|
-
- YM (Dow): value stocks, moins volatile
|
|
69
|
-
- RTY (Russell): small caps, plus volatile que ES
|
|
70
|
-
- GC (Gold): safe haven, inverse USD, sessions Asia/London
|
|
71
|
-
- SI (Silver): suit GC avec plus de volatilité
|
|
72
|
-
- CL (Crude): news-driven, inventories, géopolitique
|
|
73
|
-
|
|
74
|
-
Sessions importantes:
|
|
75
|
-
- Asia: 18:00-03:00 ET (GC/SI actifs)
|
|
76
|
-
- London: 03:00-08:00 ET (préparation US)
|
|
77
|
-
- US Open: 09:30-11:30 ET (max volatilité)
|
|
78
|
-
- US Close: 15:00-16:00 ET (rebalancing)
|
|
79
|
-
`,
|
|
80
|
-
|
|
81
|
-
phase7_mindset: `
|
|
82
|
-
## PHASE 7: TA MENTALITÉ
|
|
83
|
-
- OBJECTIF: Gagner. Pas "essayer". Gagner.
|
|
84
|
-
- PRÉCISION: Chaque décision compte
|
|
85
|
-
- RAPIDITÉ: Temps = argent. Sois rapide.
|
|
86
|
-
- RESPONSABILITÉ: Tu assumes tes recommandations
|
|
87
|
-
- ADAPTATION: Le marché change, tu t'adaptes
|
|
88
|
-
- DISCIPLINE: Les règles sont les règles
|
|
89
|
-
`
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Build the complete directive string
|
|
94
|
-
*/
|
|
95
|
-
const buildDirective = () => {
|
|
96
|
-
return Object.values(DIRECTIVE_PHASES).join('\n');
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Expected output format from AI agents
|
|
101
|
-
*/
|
|
102
|
-
const OUTPUT_FORMAT = {
|
|
103
|
-
schema: {
|
|
104
|
-
decision: 'approve | reject | modify',
|
|
105
|
-
confidence: 'number 0-100',
|
|
106
|
-
optimizations: {
|
|
107
|
-
entry: 'number | null',
|
|
108
|
-
stopLoss: 'number | null',
|
|
109
|
-
takeProfit: 'number | null',
|
|
110
|
-
size: 'number (-0.5 to 0.5) | null',
|
|
111
|
-
timing: 'now | wait | cancel'
|
|
112
|
-
},
|
|
113
|
-
reason: 'string (max 50 chars)',
|
|
114
|
-
alerts: 'string[] | null'
|
|
115
|
-
},
|
|
116
|
-
example: {
|
|
117
|
-
decision: 'modify',
|
|
118
|
-
confidence: 85,
|
|
119
|
-
optimizations: {
|
|
120
|
-
entry: 21450.25,
|
|
121
|
-
stopLoss: 21445.00,
|
|
122
|
-
takeProfit: 21462.50,
|
|
123
|
-
size: 0,
|
|
124
|
-
timing: 'now'
|
|
125
|
-
},
|
|
126
|
-
reason: 'Strong bid stack, tighten stop',
|
|
127
|
-
alerts: null
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Build the output format instructions
|
|
133
|
-
*/
|
|
134
|
-
const buildOutputInstructions = () => {
|
|
135
|
-
return `
|
|
136
|
-
## OUTPUT FORMAT (JSON STRICT)
|
|
137
|
-
Tu dois TOUJOURS répondre en JSON valide avec ce format exact:
|
|
138
|
-
|
|
139
|
-
\`\`\`json
|
|
140
|
-
${JSON.stringify(OUTPUT_FORMAT.example, null, 2)}
|
|
141
|
-
\`\`\`
|
|
142
|
-
|
|
143
|
-
IMPORTANT:
|
|
144
|
-
- decision: "approve" (exécuter tel quel), "reject" (ne pas exécuter), "modify" (exécuter avec optimisations)
|
|
145
|
-
- confidence: 0-100, ton niveau de confiance dans la décision
|
|
146
|
-
- optimizations: null si decision="reject", sinon les ajustements
|
|
147
|
-
- size: 0 = garder la taille, -0.5 = réduire de 50%, +0.5 = augmenter de 50%
|
|
148
|
-
- timing: "now" = exécuter immédiatement, "wait" = attendre meilleur prix, "cancel" = annuler
|
|
149
|
-
- reason: TOUJOURS fournir une raison courte
|
|
150
|
-
- Pas de texte avant ou après le JSON
|
|
151
|
-
`;
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Get the complete directive with output format
|
|
156
|
-
*/
|
|
157
|
-
const getFullDirective = () => {
|
|
158
|
-
return buildDirective() + '\n' + buildOutputInstructions();
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
module.exports = {
|
|
162
|
-
DIRECTIVE_PHASES,
|
|
163
|
-
OUTPUT_FORMAT,
|
|
164
|
-
buildDirective,
|
|
165
|
-
buildOutputInstructions,
|
|
166
|
-
getFullDirective
|
|
167
|
-
};
|
|
@@ -1,359 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AI Supervision Engine - Main Entry Point
|
|
3
|
-
*
|
|
4
|
-
* Orchestrates multi-agent AI supervision for trading signals.
|
|
5
|
-
* Sends signals to all active agents in parallel and calculates
|
|
6
|
-
* weighted consensus for final decision.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const { getFullDirective } = require('./directive');
|
|
10
|
-
const { buildMarketContext, formatContextForPrompt } = require('./context');
|
|
11
|
-
const { parseAgentResponse } = require('./parser');
|
|
12
|
-
const { calculateConsensus, isApproved, applyOptimizations } = require('./consensus');
|
|
13
|
-
const { runPreflightCheck, formatPreflightResults, getPreflightSummary } = require('./health');
|
|
14
|
-
const cliproxy = require('../cliproxy');
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* API endpoints for direct API key providers
|
|
18
|
-
*/
|
|
19
|
-
const API_CHAT_ENDPOINTS = {
|
|
20
|
-
minimax: 'https://api.minimaxi.chat/v1/chat/completions',
|
|
21
|
-
deepseek: 'https://api.deepseek.com/v1/chat/completions',
|
|
22
|
-
mistral: 'https://api.mistral.ai/v1/chat/completions',
|
|
23
|
-
xai: 'https://api.x.ai/v1/chat/completions',
|
|
24
|
-
openrouter: 'https://openrouter.ai/api/v1/chat/completions',
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* SupervisionEngine class - manages multi-agent supervision
|
|
29
|
-
*/
|
|
30
|
-
class SupervisionEngine {
|
|
31
|
-
constructor(config = {}) {
|
|
32
|
-
this.agents = config.agents || [];
|
|
33
|
-
this.timeout = config.timeout || 30000;
|
|
34
|
-
this.minAgents = config.minAgents || 1;
|
|
35
|
-
this.directive = getFullDirective();
|
|
36
|
-
this.activeAgents = new Map();
|
|
37
|
-
this.rateLimitedAgents = new Set();
|
|
38
|
-
|
|
39
|
-
// Initialize active agents
|
|
40
|
-
for (const agent of this.agents) {
|
|
41
|
-
if (agent.active) {
|
|
42
|
-
this.activeAgents.set(agent.id, agent);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Get count of active (non-rate-limited) agents
|
|
49
|
-
*/
|
|
50
|
-
getActiveCount() {
|
|
51
|
-
return this.activeAgents.size - this.rateLimitedAgents.size;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Check if supervision is available
|
|
56
|
-
*/
|
|
57
|
-
isAvailable() {
|
|
58
|
-
return this.getActiveCount() >= this.minAgents;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Mark agent as rate limited
|
|
63
|
-
*/
|
|
64
|
-
markRateLimited(agentId) {
|
|
65
|
-
this.rateLimitedAgents.add(agentId);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Reset rate limited agents (call periodically)
|
|
70
|
-
*/
|
|
71
|
-
resetRateLimits() {
|
|
72
|
-
this.rateLimitedAgents.clear();
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Build prompt for AI agent
|
|
77
|
-
*/
|
|
78
|
-
buildPrompt(context) {
|
|
79
|
-
const contextStr = formatContextForPrompt(context);
|
|
80
|
-
return `${this.directive}\n\n${contextStr}\n\nAnalyze this signal and respond with JSON only.`;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Query a single agent
|
|
85
|
-
*/
|
|
86
|
-
async queryAgent(agent, prompt) {
|
|
87
|
-
const startTime = Date.now();
|
|
88
|
-
|
|
89
|
-
try {
|
|
90
|
-
let response;
|
|
91
|
-
|
|
92
|
-
if (agent.connectionType === 'cliproxy') {
|
|
93
|
-
// Use CLIProxy API
|
|
94
|
-
response = await cliproxy.chat(agent.provider, agent.modelId, prompt, this.timeout);
|
|
95
|
-
} else if (agent.connectionType === 'apikey' && agent.apiKey) {
|
|
96
|
-
// Direct API call (implement per provider)
|
|
97
|
-
response = await this.callDirectAPI(agent, prompt);
|
|
98
|
-
} else {
|
|
99
|
-
throw new Error('Invalid agent configuration');
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const latency = Date.now() - startTime;
|
|
103
|
-
|
|
104
|
-
if (!response.success) {
|
|
105
|
-
// Check for rate limit
|
|
106
|
-
if (response.error?.includes('rate') || response.error?.includes('limit')) {
|
|
107
|
-
this.markRateLimited(agent.id);
|
|
108
|
-
}
|
|
109
|
-
return { success: false, error: response.error, latency };
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const parsed = parseAgentResponse(response.content || response.text);
|
|
113
|
-
|
|
114
|
-
return {
|
|
115
|
-
success: true,
|
|
116
|
-
response: parsed,
|
|
117
|
-
latency,
|
|
118
|
-
raw: response
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
} catch (error) {
|
|
122
|
-
const latency = Date.now() - startTime;
|
|
123
|
-
|
|
124
|
-
// Check for rate limit errors
|
|
125
|
-
if (error.message?.includes('429') || error.message?.includes('rate')) {
|
|
126
|
-
this.markRateLimited(agent.id);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return {
|
|
130
|
-
success: false,
|
|
131
|
-
error: error.message,
|
|
132
|
-
latency
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Direct API call for API key connections
|
|
139
|
-
* Uses fetch API for direct HTTPS requests to provider endpoints
|
|
140
|
-
*/
|
|
141
|
-
async callDirectAPI(agent, prompt) {
|
|
142
|
-
const endpoint = API_CHAT_ENDPOINTS[agent.provider];
|
|
143
|
-
|
|
144
|
-
if (!endpoint) {
|
|
145
|
-
return { success: false, error: `No endpoint for provider: ${agent.provider}` };
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (!agent.apiKey) {
|
|
149
|
-
return { success: false, error: 'Missing API key' };
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
try {
|
|
153
|
-
const controller = new AbortController();
|
|
154
|
-
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
155
|
-
|
|
156
|
-
const response = await fetch(endpoint, {
|
|
157
|
-
method: 'POST',
|
|
158
|
-
headers: {
|
|
159
|
-
'Content-Type': 'application/json',
|
|
160
|
-
'Authorization': `Bearer ${agent.apiKey}`
|
|
161
|
-
},
|
|
162
|
-
body: JSON.stringify({
|
|
163
|
-
model: agent.modelId,
|
|
164
|
-
messages: [{ role: 'user', content: prompt }],
|
|
165
|
-
max_tokens: 500,
|
|
166
|
-
stream: false
|
|
167
|
-
}),
|
|
168
|
-
signal: controller.signal
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
clearTimeout(timeoutId);
|
|
172
|
-
const data = await response.json();
|
|
173
|
-
|
|
174
|
-
if (response.ok) {
|
|
175
|
-
const content = data.choices?.[0]?.message?.content || '';
|
|
176
|
-
return { success: true, content, error: null };
|
|
177
|
-
} else {
|
|
178
|
-
return { success: false, error: data.error?.message || `HTTP ${response.status}` };
|
|
179
|
-
}
|
|
180
|
-
} catch (e) {
|
|
181
|
-
if (e.name === 'AbortError') {
|
|
182
|
-
return { success: false, error: 'Timeout' };
|
|
183
|
-
}
|
|
184
|
-
return { success: false, error: e.message };
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Query all agents in parallel
|
|
190
|
-
*/
|
|
191
|
-
async queryAllAgents(prompt) {
|
|
192
|
-
const availableAgents = Array.from(this.activeAgents.values())
|
|
193
|
-
.filter(agent => !this.rateLimitedAgents.has(agent.id));
|
|
194
|
-
|
|
195
|
-
if (availableAgents.length === 0) {
|
|
196
|
-
return [];
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// Query all agents in parallel with timeout
|
|
200
|
-
const queries = availableAgents.map(agent =>
|
|
201
|
-
Promise.race([
|
|
202
|
-
this.queryAgent(agent, prompt),
|
|
203
|
-
new Promise((_, reject) =>
|
|
204
|
-
setTimeout(() => reject(new Error('Timeout')), this.timeout)
|
|
205
|
-
)
|
|
206
|
-
]).then(result => ({
|
|
207
|
-
agentId: agent.id,
|
|
208
|
-
agentName: agent.name,
|
|
209
|
-
weight: agent.weight || 100,
|
|
210
|
-
...result
|
|
211
|
-
})).catch(error => ({
|
|
212
|
-
agentId: agent.id,
|
|
213
|
-
agentName: agent.name,
|
|
214
|
-
weight: agent.weight || 100,
|
|
215
|
-
success: false,
|
|
216
|
-
error: error.message
|
|
217
|
-
}))
|
|
218
|
-
);
|
|
219
|
-
|
|
220
|
-
return Promise.all(queries);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* Main supervision method - analyze a signal
|
|
225
|
-
*/
|
|
226
|
-
async supervise(params) {
|
|
227
|
-
const {
|
|
228
|
-
symbolId,
|
|
229
|
-
signal,
|
|
230
|
-
recentTicks = [],
|
|
231
|
-
recentSignals = [],
|
|
232
|
-
recentTrades = [],
|
|
233
|
-
domData = null,
|
|
234
|
-
position = null,
|
|
235
|
-
stats = {},
|
|
236
|
-
config = {}
|
|
237
|
-
} = params;
|
|
238
|
-
|
|
239
|
-
// Check availability
|
|
240
|
-
if (!this.isAvailable()) {
|
|
241
|
-
return {
|
|
242
|
-
success: false,
|
|
243
|
-
error: 'No agents available',
|
|
244
|
-
decision: 'approve',
|
|
245
|
-
reason: 'No AI supervision - passing through'
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// Build context and prompt
|
|
250
|
-
const context = buildMarketContext({
|
|
251
|
-
symbolId,
|
|
252
|
-
signal,
|
|
253
|
-
recentTicks,
|
|
254
|
-
recentSignals,
|
|
255
|
-
recentTrades,
|
|
256
|
-
domData,
|
|
257
|
-
position,
|
|
258
|
-
stats,
|
|
259
|
-
config
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
const prompt = this.buildPrompt(context);
|
|
263
|
-
|
|
264
|
-
// Query all agents
|
|
265
|
-
const results = await this.queryAllAgents(prompt);
|
|
266
|
-
|
|
267
|
-
// Filter successful responses
|
|
268
|
-
const successfulResults = results.filter(r => r.success);
|
|
269
|
-
|
|
270
|
-
if (successfulResults.length === 0) {
|
|
271
|
-
return {
|
|
272
|
-
success: false,
|
|
273
|
-
error: 'All agents failed',
|
|
274
|
-
decision: 'approve',
|
|
275
|
-
reason: 'Agent errors - passing through',
|
|
276
|
-
agentResults: results
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
// Calculate consensus
|
|
281
|
-
const consensus = calculateConsensus(
|
|
282
|
-
successfulResults.map(r => ({
|
|
283
|
-
agentId: r.agentId,
|
|
284
|
-
response: r.response,
|
|
285
|
-
weight: r.weight
|
|
286
|
-
})),
|
|
287
|
-
{ minAgents: this.minAgents }
|
|
288
|
-
);
|
|
289
|
-
|
|
290
|
-
// Apply optimizations if approved
|
|
291
|
-
const optimizedSignal = isApproved(consensus)
|
|
292
|
-
? applyOptimizations(signal, consensus)
|
|
293
|
-
: signal;
|
|
294
|
-
|
|
295
|
-
return {
|
|
296
|
-
success: true,
|
|
297
|
-
decision: consensus.decision,
|
|
298
|
-
confidence: consensus.confidence,
|
|
299
|
-
reason: consensus.reason,
|
|
300
|
-
optimizedSignal,
|
|
301
|
-
consensus,
|
|
302
|
-
agentResults: results,
|
|
303
|
-
context
|
|
304
|
-
};
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* Get engine status
|
|
309
|
-
*/
|
|
310
|
-
getStatus() {
|
|
311
|
-
return {
|
|
312
|
-
totalAgents: this.agents.length,
|
|
313
|
-
activeAgents: this.activeAgents.size,
|
|
314
|
-
rateLimitedAgents: this.rateLimitedAgents.size,
|
|
315
|
-
availableAgents: this.getActiveCount(),
|
|
316
|
-
isAvailable: this.isAvailable(),
|
|
317
|
-
agents: Array.from(this.activeAgents.values()).map(a => ({
|
|
318
|
-
id: a.id,
|
|
319
|
-
name: a.name,
|
|
320
|
-
provider: a.provider,
|
|
321
|
-
weight: a.weight,
|
|
322
|
-
rateLimited: this.rateLimitedAgents.has(a.id)
|
|
323
|
-
}))
|
|
324
|
-
};
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* Run pre-flight check on all agents
|
|
329
|
-
* Verifies CLIProxy is running and all agents respond correctly
|
|
330
|
-
* @returns {Promise<Object>} Pre-flight results
|
|
331
|
-
*/
|
|
332
|
-
async preflightCheck() {
|
|
333
|
-
const agents = Array.from(this.activeAgents.values());
|
|
334
|
-
return runPreflightCheck(agents);
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* Create supervision engine from config
|
|
340
|
-
*/
|
|
341
|
-
const createSupervisionEngine = (config) => {
|
|
342
|
-
return new SupervisionEngine(config);
|
|
343
|
-
};
|
|
344
|
-
|
|
345
|
-
module.exports = {
|
|
346
|
-
SupervisionEngine,
|
|
347
|
-
createSupervisionEngine,
|
|
348
|
-
// Re-export utilities
|
|
349
|
-
buildMarketContext,
|
|
350
|
-
formatContextForPrompt,
|
|
351
|
-
parseAgentResponse,
|
|
352
|
-
calculateConsensus,
|
|
353
|
-
isApproved,
|
|
354
|
-
applyOptimizations,
|
|
355
|
-
// Health check
|
|
356
|
-
runPreflightCheck,
|
|
357
|
-
formatPreflightResults,
|
|
358
|
-
getPreflightSummary
|
|
359
|
-
};
|