beast-agent 2.38.3 → 2.39.0
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/agent/bots.js +66 -0
- package/src/agent/customtools.js +1 -1
- package/src/agent/engine.js +222 -45
- package/src/agent/financetools.js +52 -0
- package/src/agent/mt5/BeastFinance.mq5 +290 -0
- package/src/agent/mt5setup.js +520 -0
- package/src/agent/scripts/mt5_bridge.py +112 -0
- package/src/agent/seeds/mql5/SKILL.md +25 -2
- package/src/agent/seeds/tool-yazma/SKILL.md +6 -4
- package/src/main.js +232 -12
- package/src/preload.js +1 -0
- package/src/renderer/index.html +20 -4
- package/src/renderer/renderer.js +178 -35
- package/src/renderer/style.css +30 -3
|
@@ -62,12 +62,14 @@ try { args = JSON.parse(fs.readFileSync(0, 'utf8') || '{}'); } catch {}
|
|
|
62
62
|
|
|
63
63
|
Slug kuralları: a-z, 0-9, alt çizgi, tire — 2-24 karakter (örn: gold_emir, haber_ozet). Hazır taslak: %APPDATA%\beast\tools\ornek_echo klasörünü referans al; yeni tool'u o biçimle yaz.
|
|
64
64
|
|
|
65
|
-
##
|
|
65
|
+
## TEST DÖNGÜSÜ / YAYIN (zorunlu)
|
|
66
66
|
|
|
67
67
|
1. Mevcut toolu değiştirme: `edit_file` ile tool.json / run.js düzenle — ASLA tüm klasörü silip baştan yazma.
|
|
68
|
-
2.
|
|
69
|
-
3.
|
|
70
|
-
4.
|
|
68
|
+
2. TEST: `run_command` ile `echo "{\"mesaj\":\"test\"}" | node "%APPDATA%\beast\tools\<slug>\run.js"` çalıştır (çalışma klasörü tool'un kendi klasörüdür) — çıktı SADECE JSON olmalı ve `ok` alanı içermeli.
|
|
69
|
+
3. DÖNGÜ: test `ok:true` DEĞİLSE stderr'i/hatayı oku → `edit_file` ile düzelt → YENİDEN test et. En fazla 5 deneme; her denemenin sonucunu not et.
|
|
70
|
+
4. YAYIN: yalnız test GEÇİNCE yayınla (dosyalar anında aktifleşir; `tool__<slug>` sonraki turda çağrılır) ve "YAYINDA" diye raporla. Test geçmeyen aracı yayınlama.
|
|
71
|
+
5. BAŞARISIZLIK: 5 denemede geçmezse yayınlama; rapora `ok:false + error` kök nedenini ve ne denediğini yaz — çıplak stack yasak.
|
|
72
|
+
6. ADIM RAPORU: final raporda adımları yaz (yazıldı → test → düzeltmeler → YAYINDA/BAŞARISIZ). `tool_request` ile gelen isteklerde bu rapor bağlı entegrasyonlara (WhatsApp/Telegram/Discord) otomatik bildirilir.
|
|
71
73
|
|
|
72
74
|
## GÜVENLİK + STİL
|
|
73
75
|
|
package/src/main.js
CHANGED
|
@@ -2257,10 +2257,11 @@ function botToolSet(cfg) {
|
|
|
2257
2257
|
'run_background', 'run_background_many', 'delegate_task',
|
|
2258
2258
|
'event_list', 'event_subscribe', 'event_unsubscribe',
|
|
2259
2259
|
'watcher_add', 'watcher_list', 'watcher_remove',
|
|
2260
|
+
'tool_request', /* CEPHANE: eksik aracı TOOL botuna yazdırma hakkı HER botta */
|
|
2260
2261
|
]);
|
|
2261
2262
|
if (s.web_search) { set.add('web_search'); set.add('http_fetch'); set.add('webfetch'); set.add('deep_search'); }
|
|
2262
2263
|
if (s.browser) {
|
|
2263
|
-
for (const t of ['browser_open', 'browser_read', 'browser_screenshot', 'browser_snapshot', 'browser_click', 'browser_type', 'browser_press', 'browser_scroll', 'browser_select', 'ocr_read']) set.add(t);
|
|
2264
|
+
for (const t of ['browser_open', 'browser_read', 'browser_screenshot', 'browser_snapshot', 'browser_click', 'browser_type', 'browser_press', 'browser_scroll', 'browser_select', 'ocr_read', 'computer_look']) set.add(t);
|
|
2264
2265
|
}
|
|
2265
2266
|
if (s.email) { set.add('email_list'); set.add('email_read'); set.add('email_send'); }
|
|
2266
2267
|
if (s.run_command) {
|
|
@@ -3210,6 +3211,8 @@ function reloadBackend() {
|
|
|
3210
3211
|
supermemory: settings.supermemory || { enabled: true, baseUrl: 'http://localhost:6767', apiKey: '', containerTag: 'beast' },
|
|
3211
3212
|
crashFile: FALLOUT_CRASH_FILE,
|
|
3212
3213
|
notifyOwnerFail: settings.notifyOwnerFail !== false,
|
|
3214
|
+
/* tool yazım/doğrulama adımları → bağlı entegrasyonlara (WA/TG/Discord) */
|
|
3215
|
+
integrationNotify: integrationBroadcast,
|
|
3213
3216
|
fileSend: deliverFile,
|
|
3214
3217
|
reminders: { add: scheduleReminder },
|
|
3215
3218
|
watchers: {
|
|
@@ -5976,7 +5979,18 @@ ipcMain.handle('agent-dms:delete-thread', (_e, key) => (engine ? engine.agentDmD
|
|
|
5976
5979
|
|
|
5977
5980
|
/* ---------- KİŞİSEL TOOLLAR (%APPDATA%\beast\tools\) ---------- */
|
|
5978
5981
|
ipcMain.handle('tools:list', () => customtools.list());
|
|
5979
|
-
ipcMain.handle('tools:save', (_e, tool) =>
|
|
5982
|
+
ipcMain.handle('tools:save', (_e, tool) => {
|
|
5983
|
+
const r = customtools.save(tool || {});
|
|
5984
|
+
/* panelden yayınlanan araç da entegrasyonlara duyurulur */
|
|
5985
|
+
if (r && r.ok) {
|
|
5986
|
+
try {
|
|
5987
|
+
integrationBroadcast(
|
|
5988
|
+
'🛠️ Araç yayında: tool__' + r.id + ' — ' + String((tool && tool.name) || r.id).slice(0, 60) + '\n(Beast TOOLS panelinden kaydedildi)'
|
|
5989
|
+
);
|
|
5990
|
+
} catch {}
|
|
5991
|
+
}
|
|
5992
|
+
return r;
|
|
5993
|
+
});
|
|
5980
5994
|
ipcMain.handle('tools:delete', (_e, id) => customtools.remove(id));
|
|
5981
5995
|
ipcMain.handle('tools:run', async (_e, payload) => {
|
|
5982
5996
|
const id = String((payload && payload.id) || '');
|
|
@@ -8436,6 +8450,7 @@ function studioWatchStop() {
|
|
|
8436
8450
|
sohbet finance bayrağıyla mt5_* araçlarını görür; (2) TRADER — gizli engine
|
|
8437
8451
|
oturumu, tur tur piyasa tarayıp (farklı API/model seçilebilir) işlem kovalar. */
|
|
8438
8452
|
const mt5bridge = require('./mt5bridge');
|
|
8453
|
+
const mt5setup = require('./agent/mt5setup');
|
|
8439
8454
|
const financetools = require('./agent/financetools');
|
|
8440
8455
|
const finrisk = require('./agent/finrisk');
|
|
8441
8456
|
const customtools = require('./agent/customtools');
|
|
@@ -8487,12 +8502,13 @@ function finCfg() {
|
|
|
8487
8502
|
/* OTOMATİK İŞLEM hep açık — kullanıcı onay kutusu KALDIRILDI: trade ajanının
|
|
8488
8503
|
amacı zaten işlem açmak; onay sorulmaz, limitler (max lot/pozisyon) korur */
|
|
8489
8504
|
f.allowTrading = true;
|
|
8490
|
-
/* ANALİZ
|
|
8491
|
-
|
|
8492
|
-
|
|
8493
|
-
f.analysisAuto = true;
|
|
8505
|
+
/* ANALİZ EKİBİ: çoklu seçim (analysisTeam) VEYA sayı modu (analysisAuto).
|
|
8506
|
+
Varsayılan: oto sayı 2 (Teknik → Risk → Haber → Görsel). Kullanıcı
|
|
8507
|
+
picker'dan rol seçince analysisAuto=false + analysisTeam yazılır. */
|
|
8508
|
+
if (typeof f.analysisAuto !== 'boolean') f.analysisAuto = true;
|
|
8494
8509
|
if (!Number.isFinite(Number(f.analysisCount))) f.analysisCount = 2;
|
|
8495
8510
|
f.analysisCount = Math.max(0, Math.min(FIN_ROLES_AUTO.length, Math.round(Number(f.analysisCount) || 0)));
|
|
8511
|
+
if (!f.analysisAuto) f.analysisTeam = finRolesValid(f.analysisTeam);
|
|
8496
8512
|
/* ROL → SKILL eşleştirmesi: rol başına TEK skill — modalda zorunlu tek
|
|
8497
8513
|
seçim yapılır. Eski çoklu seçimlerden yalnız İLKİ korunur (göç). Skill
|
|
8498
8514
|
adları kurulu katalogdan gelir. */
|
|
@@ -8552,6 +8568,12 @@ function finCfg() {
|
|
|
8552
8568
|
if (!Number.isFinite(Number(f.maxPerSymbol))) f.maxPerSymbol = 2;
|
|
8553
8569
|
if (!Number.isFinite(Number(f.maxSameSide))) f.maxSameSide = 3;
|
|
8554
8570
|
if (!Number.isFinite(Number(f.minMarginLevel))) f.minMarginLevel = 150;
|
|
8571
|
+
/* MT5 İLK KURULUM: bağlantı kurulunca EA derlenir + AutoTrading izni + grafik
|
|
8572
|
+
enjeksiyonu otomatik uygulanır (false = yalnız elle "🛠 Kurulum" ile) */
|
|
8573
|
+
if (typeof f.autoSetup !== 'boolean') f.autoSetup = true;
|
|
8574
|
+
/* Kurulum ilk kez uygulanınca MT5'i bir kez otomatik yeniden başlat
|
|
8575
|
+
(EA + AutoTrading + grafik ancak yeniden başlatmada etkinleşir) */
|
|
8576
|
+
if (typeof f.autoRestart !== 'boolean') f.autoRestart = true;
|
|
8555
8577
|
if (f.weeklyReport == null) f.weeklyReport = true;
|
|
8556
8578
|
return f;
|
|
8557
8579
|
}
|
|
@@ -8564,8 +8586,9 @@ const FIN_ROLES = [
|
|
|
8564
8586
|
{ id: 'risk', label: 'Risk Ajanı', desc: 'marj/kaldıraç/SL disiplini, exposure ve günlük kayıp hızı denetimi' },
|
|
8565
8587
|
{ id: 'technic', label: 'Teknik Analiz', desc: 'trend/yapı/destek-direnç/momentum okuma, AL-SAT-BEKLE önerileri' },
|
|
8566
8588
|
{ id: 'macro', label: 'Haber / Makro', desc: 'haber akışı + ekonomik takvim, DXY/emtia bağıntıları, yön eğilimi' },
|
|
8589
|
+
{ id: 'visual', label: 'Görsel Ajan', desc: 'MT5 grafiği/ekran görüntüsü — trend, formasyon, seviye ve mum yapısını görsel doğrulama' },
|
|
8567
8590
|
];
|
|
8568
|
-
const FIN_ROLES_AUTO = ['technic', 'risk', 'macro'];
|
|
8591
|
+
const FIN_ROLES_AUTO = ['technic', 'risk', 'macro', 'visual'];
|
|
8569
8592
|
function finRolesValid(list) {
|
|
8570
8593
|
return (Array.isArray(list) ? list : [])
|
|
8571
8594
|
.map((r) => String(r || '').trim())
|
|
@@ -8808,6 +8831,26 @@ function financeNotify(text, kind, panel) {
|
|
|
8808
8831
|
}
|
|
8809
8832
|
}
|
|
8810
8833
|
|
|
8834
|
+
/* ENTEGRASYON BİLDİRİMİ (tool adımları): bağlı TÜM kanallara (WhatsApp/
|
|
8835
|
+
Telegram/Discord) düşer — finance trade filtresine takılmaz. Tool botu
|
|
8836
|
+
yazım/doğrulama raporları ve araç yayın duyuruları buradan gider. */
|
|
8837
|
+
function integrationBroadcast(text) {
|
|
8838
|
+
const body = String(text || '').trim();
|
|
8839
|
+
if (!body) return;
|
|
8840
|
+
try {
|
|
8841
|
+
if (wa && wa.connected) {
|
|
8842
|
+
const own = waOwnerNum();
|
|
8843
|
+
if (own) Promise.resolve(sendWaSafe(own + '@s.whatsapp.net', body)).catch(() => {});
|
|
8844
|
+
}
|
|
8845
|
+
} catch {}
|
|
8846
|
+
try {
|
|
8847
|
+
if (tg && tg.connected) for (const id of tgOwnerIds()) Promise.resolve(sendTgSafe(id, body)).catch(() => {});
|
|
8848
|
+
} catch {}
|
|
8849
|
+
try {
|
|
8850
|
+
if (dc && dc.connected) for (const id of dcOwnerIds()) Promise.resolve(sendDcSafe(id, body)).catch(() => {});
|
|
8851
|
+
} catch {}
|
|
8852
|
+
}
|
|
8853
|
+
|
|
8811
8854
|
/* ---- fiyat alarmları (kalıcı) ---- */
|
|
8812
8855
|
function finAlertsLoad() {
|
|
8813
8856
|
const raw = finReadJson(finFile('alerts.json'), []);
|
|
@@ -9378,12 +9421,31 @@ try {
|
|
|
9378
9421
|
});
|
|
9379
9422
|
} catch {}
|
|
9380
9423
|
|
|
9381
|
-
function financeEnsureBridge() {
|
|
9424
|
+
async function financeEnsureBridge() {
|
|
9382
9425
|
/* BEAST FINANCE = MT5 KAPISI: mod KAPALIYKEN köprü HİÇ başlatılmaz —
|
|
9383
9426
|
Beast, kullanıcı finance açmadıkça MT5 terminalini açmaz/yeniden
|
|
9384
9427
|
başlatmaz. Mod açılınca finance:mode handler'ı burayı çağırır. */
|
|
9385
9428
|
if (!financeState.mode) return mt5bridge.status();
|
|
9386
9429
|
const f = finCfg();
|
|
9430
|
+
/* MT5 KAPALIYSA AÇILMADAN ÖNCE KUR: terminal ilk açılışta BeastFinance EA
|
|
9431
|
+
yüklü + AutoTrading açık + grafikte pano hazır başlar. */
|
|
9432
|
+
try {
|
|
9433
|
+
if (f.autoSetup !== false && !mt5setup.terminalRunning()) {
|
|
9434
|
+
const det = mt5setup.detectTerminal();
|
|
9435
|
+
const dataPath = det.dataPath || '';
|
|
9436
|
+
if (dataPath) {
|
|
9437
|
+
const r = await mt5setup.runSetup({
|
|
9438
|
+
dataPath,
|
|
9439
|
+
terminalExe: String(f.terminalPath || '').trim() || det.exe || '',
|
|
9440
|
+
force: false,
|
|
9441
|
+
});
|
|
9442
|
+
for (const s of (r && r.steps) || []) financeLog('[kurulum] ' + s);
|
|
9443
|
+
if (r && r.ok) {
|
|
9444
|
+
finPush('setup', { ok: true, changed: !!r.changed, compiled: !!r.compiled, chartAttached: !!r.chartAttached, restartRequired: false, steps: r.steps || [] });
|
|
9445
|
+
}
|
|
9446
|
+
}
|
|
9447
|
+
}
|
|
9448
|
+
} catch {}
|
|
9387
9449
|
const candidates = [String(f.pythonPath || '').trim(), 'python', 'py -3'].filter(Boolean);
|
|
9388
9450
|
/* Beast gömülü Python runtime kuruluysa en başa ekle (makinede Python olmasa da köprü çalışır) */
|
|
9389
9451
|
try {
|
|
@@ -9421,7 +9483,7 @@ function financeTryInstall() {
|
|
|
9421
9483
|
if (code === 0) {
|
|
9422
9484
|
financeLog('[MT5] MetaTrader5 paketi kuruldu — köprü yeniden başlatılıyor');
|
|
9423
9485
|
mt5bridge.stop();
|
|
9424
|
-
financeEnsureBridge();
|
|
9486
|
+
financeEnsureBridge().catch(() => {});
|
|
9425
9487
|
} else {
|
|
9426
9488
|
financeLog('[MT5] kurulum başarısız (kod ' + code + ') ' + tail.slice(-300));
|
|
9427
9489
|
}
|
|
@@ -9429,12 +9491,168 @@ function financeTryInstall() {
|
|
|
9429
9491
|
});
|
|
9430
9492
|
}
|
|
9431
9493
|
|
|
9494
|
+
/* MT5 İLK KURULUM (otomatik + elle): EA yaz/derle, AutoTrading izni ve grafik
|
|
9495
|
+
enjeksiyonunu uygular. İdempotent — her bağlantıda zararsız çalışır. */
|
|
9496
|
+
let finSetupBusy = false;
|
|
9497
|
+
let finSetupDoneAt = 0;
|
|
9498
|
+
let finSetupRestarted = false; /* kurulum etkinleşmesi için MT5'i BİR KEZ restart ettik mi */
|
|
9499
|
+
async function finMt5SetupEnsure(force) {
|
|
9500
|
+
if (finSetupBusy) return { ok: false, error: 'kurulum zaten çalışıyor' };
|
|
9501
|
+
if (!force && finCfg().autoSetup === false) return { ok: false, error: 'otomatik kurulum kapalı' };
|
|
9502
|
+
if (!force && finSetupDoneAt && Date.now() - finSetupDoneAt < 10 * 60 * 1000) return { ok: true, cached: true, steps: [] };
|
|
9503
|
+
const st = mt5bridge.status();
|
|
9504
|
+
const term = (st && st.terminal) || {};
|
|
9505
|
+
const dataPath = String((term && (term.data_path || term.dataPath)) || '').trim();
|
|
9506
|
+
if (!dataPath) return { ok: false, error: 'MT5 veri klasörü henüz bilinmiyor — bağlantı bekleniyor' };
|
|
9507
|
+
finSetupBusy = true;
|
|
9508
|
+
try {
|
|
9509
|
+
const r = await mt5setup.runSetup({
|
|
9510
|
+
dataPath,
|
|
9511
|
+
terminalExe: String((term && term.path) || '').trim(),
|
|
9512
|
+
force: !!force,
|
|
9513
|
+
});
|
|
9514
|
+
finSetupDoneAt = Date.now();
|
|
9515
|
+
const steps = (r && r.steps) || [];
|
|
9516
|
+
for (const s of steps) financeLog('[kurulum] ' + s);
|
|
9517
|
+
if (r && r.ok) {
|
|
9518
|
+
finPush('setup', { ok: true, changed: !!r.changed, compiled: !!r.compiled, chartAttached: !!r.chartAttached, restartRequired: !!r.restartRequired, steps });
|
|
9519
|
+
if (r.changed) {
|
|
9520
|
+
try {
|
|
9521
|
+
integrationBroadcast(
|
|
9522
|
+
'🛠️ MT5 kurulumu — BeastFinance.mq5 ' + (r.compiled ? 'derlendi' : 'hazır') +
|
|
9523
|
+
(r.autoTrading ? ' · AutoTrading izni açıldı' : '') +
|
|
9524
|
+
(r.chartAttached ? ' · grafik profiline eklendi' : '') +
|
|
9525
|
+
(r.restartRequired ? '\nMT5 yeniden başlatılınca etkin olur.' : '')
|
|
9526
|
+
);
|
|
9527
|
+
} catch {}
|
|
9528
|
+
}
|
|
9529
|
+
if (term && term.trade_allowed === false) {
|
|
9530
|
+
financeLog('[kurulum] dikkat: AutoTrading kapalı — MT5 yeniden başlatılmalı (common.ini yazıldı)');
|
|
9531
|
+
}
|
|
9532
|
+
/* İLK KURULUM etkinleşmesi: terminal açıksa BİR KEZ otomatik restart
|
|
9533
|
+
(EA + AutoTrading + grafik ancak yeniden başlatmada devreye girer) */
|
|
9534
|
+
if (r.restartRequired && !finSetupRestarted && finCfg().autoRestart !== false) {
|
|
9535
|
+
finMt5RestartForSetup(String((term && term.path) || '').trim(), dataPath).catch(() => {});
|
|
9536
|
+
}
|
|
9537
|
+
} else if (r && r.error) {
|
|
9538
|
+
financeLog('[kurulum] hata: ' + r.error);
|
|
9539
|
+
finPush('setup', { ok: false, error: r.error, steps });
|
|
9540
|
+
}
|
|
9541
|
+
return r || { ok: false, error: 'kurulum yanıtı yok' };
|
|
9542
|
+
} finally {
|
|
9543
|
+
finSetupBusy = false;
|
|
9544
|
+
}
|
|
9545
|
+
}
|
|
9546
|
+
|
|
9547
|
+
/* Kurulumu etkinleştirmek için MT5'i YENİDEN BAŞLAT (tek sefer):
|
|
9548
|
+
kapat → ayarları tazele (kapanışta profil üzerine yazılmış olabilir) →
|
|
9549
|
+
terminali aç → köprüyü tazele. */
|
|
9550
|
+
async function finMt5RestartForSetup(terminalExe, dataPath) {
|
|
9551
|
+
if (finSetupRestarted) return;
|
|
9552
|
+
finSetupRestarted = true;
|
|
9553
|
+
const exe = String(terminalExe || '').trim();
|
|
9554
|
+
financeLog('[kurulum] MT5 yeniden başlatılıyor (EA + AutoTrading etkinleşmesi)…');
|
|
9555
|
+
/* ÖNCE NAZİK KAPAT (WM_CLOSE): MT5 profilini/config'ini KAYDEDER — /F
|
|
9556
|
+
kullanırsak kaydetmez ve enjeksiyon/manuel eklenen EA kaybolur */
|
|
9557
|
+
try { spawn('taskkill', ['/IM', 'terminal64.exe'], { windowsHide: true, stdio: 'ignore' }); } catch {}
|
|
9558
|
+
await new Promise((r) => setTimeout(r, 4500));
|
|
9559
|
+
if (mt5setup.terminalRunning()) {
|
|
9560
|
+
try { spawn('taskkill', ['/IM', 'terminal64.exe', '/F'], { windowsHide: true, stdio: 'ignore' }); } catch {}
|
|
9561
|
+
await new Promise((r) => setTimeout(r, 2000));
|
|
9562
|
+
}
|
|
9563
|
+
/* terminal kapalıyken profil/ini TAZELE — kapanış kaydı enjeksiyonu ezmiş olabilir */
|
|
9564
|
+
try {
|
|
9565
|
+
const r2 = await mt5setup.runSetup({ dataPath, terminalExe: exe, force: false });
|
|
9566
|
+
for (const s of (r2 && r2.steps) || []) financeLog('[kurulum] ' + s);
|
|
9567
|
+
} catch {}
|
|
9568
|
+
if (exe) {
|
|
9569
|
+
try {
|
|
9570
|
+
const p = spawn(exe, [], { detached: true, stdio: 'ignore' });
|
|
9571
|
+
p.unref();
|
|
9572
|
+
financeLog('[kurulum] MT5 açıldı: ' + exe);
|
|
9573
|
+
} catch (e) {
|
|
9574
|
+
financeLog('[kurulum] terminal başlatılamadı: ' + String((e && e.message) || e));
|
|
9575
|
+
return;
|
|
9576
|
+
}
|
|
9577
|
+
} else {
|
|
9578
|
+
financeLog('[kurulum] terminal yolu yok — MT5 elle açılmalı');
|
|
9579
|
+
}
|
|
9580
|
+
await new Promise((r) => setTimeout(r, 6000));
|
|
9581
|
+
mt5bridge.stop();
|
|
9582
|
+
financeEnsureBridge().catch(() => {});
|
|
9583
|
+
}
|
|
9584
|
+
|
|
9585
|
+
/* EA heartbeat kontrolü: BeastFinance grafikte mi + izinler açık mı.
|
|
9586
|
+
Yoksa OTOMATİK onarım: kurulumu zorla + gerekiyorsa terminali yeniden başlat.
|
|
9587
|
+
Sonuç entegrasyonlara ve panele bildirilir. */
|
|
9588
|
+
let finEaCheckDone = false;
|
|
9589
|
+
let finEaCheckAt = 0;
|
|
9590
|
+
let finEaRepairTried = false;
|
|
9591
|
+
async function finEaStatusCheck() {
|
|
9592
|
+
if (finEaCheckDone || !mt5bridge.running) return;
|
|
9593
|
+
if (Date.now() - finEaCheckAt < 20000) return; /* spam koruması */
|
|
9594
|
+
finEaCheckAt = Date.now();
|
|
9595
|
+
try {
|
|
9596
|
+
const r = await mt5bridge.call('ea_status', {}, 10000);
|
|
9597
|
+
if (!r || !r.ok) return;
|
|
9598
|
+
const d = r.data || {};
|
|
9599
|
+
if (!d.installed) {
|
|
9600
|
+
financeLog('[EA] BeastFinance grafikte yüklü değil — otomatik kurulum deneniyor');
|
|
9601
|
+
finPush('setup', { ok: false, error: 'BeastFinance EA grafikte yüklü değil', ea: false, filesDir: d.files_dir || '' });
|
|
9602
|
+
if (!finEaRepairTried && finCfg().autoSetup !== false) {
|
|
9603
|
+
finEaRepairTried = true;
|
|
9604
|
+
try {
|
|
9605
|
+
const rr = await finMt5SetupEnsure(true);
|
|
9606
|
+
if (rr && rr.ok && rr.restartRequired && !finSetupRestarted && finCfg().autoRestart !== false) {
|
|
9607
|
+
const dataPath = d.files_dir ? path.dirname(path.dirname(String(d.files_dir))) : '';
|
|
9608
|
+
const termPath = String(((mt5bridge.status() || {}).terminal || {}).path || '');
|
|
9609
|
+
finMt5RestartForSetup(termPath, dataPath).catch(() => {});
|
|
9610
|
+
}
|
|
9611
|
+
} catch {}
|
|
9612
|
+
}
|
|
9613
|
+
return;
|
|
9614
|
+
}
|
|
9615
|
+
finEaCheckDone = true;
|
|
9616
|
+
const ea = d.ea || {};
|
|
9617
|
+
const tradeOk = ea.terminal_trade_allowed !== false && ea.mql_trade_allowed !== false;
|
|
9618
|
+
financeLog(
|
|
9619
|
+
'[EA] BeastFinance v' + String(ea.version || '?') + ' · ' + String(ea.symbol || '') +
|
|
9620
|
+
' · AutoTrading=' + (ea.terminal_trade_allowed ? 'açık' : 'KAPALI') +
|
|
9621
|
+
' · EA izni=' + (ea.mql_trade_allowed ? 'açık' : 'KAPALI')
|
|
9622
|
+
);
|
|
9623
|
+
finPush('setup', { ok: true, ea: true, eaInfo: ea });
|
|
9624
|
+
if (!tradeOk) {
|
|
9625
|
+
try {
|
|
9626
|
+
integrationBroadcast(
|
|
9627
|
+
'⚠️ BeastFinance EA izin uyarısı: AutoTrading=' + (ea.terminal_trade_allowed ? 'açık' : 'KAPALI') +
|
|
9628
|
+
' · EA izni=' + (ea.mql_trade_allowed ? 'açık' : 'KAPALI') +
|
|
9629
|
+
'\nMT5 → Ctrl+E (AutoTrading) ve EA özellikleri → Canlı işlem izni.'
|
|
9630
|
+
);
|
|
9631
|
+
} catch {}
|
|
9632
|
+
} else {
|
|
9633
|
+
try {
|
|
9634
|
+
integrationBroadcast(
|
|
9635
|
+
'✅ BeastFinance EA grafikte aktif: ' + String(ea.symbol || '') + ' ' + String(ea.period || '') +
|
|
9636
|
+
' · AutoTrading açık · equity ' + String(ea.equity != null ? ea.equity : '?')
|
|
9637
|
+
);
|
|
9638
|
+
} catch {}
|
|
9639
|
+
}
|
|
9640
|
+
} catch {}
|
|
9641
|
+
}
|
|
9642
|
+
|
|
9432
9643
|
mt5bridge.on('bridge', (m) => {
|
|
9433
9644
|
if (m && m.connected) {
|
|
9434
9645
|
financeLog('[MT5] terminal bağlı: ' + ((m.terminal && (m.terminal.name + ' @ ' + m.terminal.company)) || 'MT5'));
|
|
9435
9646
|
if (m.account) financeLog(`[MT5] hesap ${m.account.login} · bakiye ${m.account.balance} ${m.account.currency}`);
|
|
9436
9647
|
finWatchStart();
|
|
9437
9648
|
finStatsRefresh(true).catch(() => {});
|
|
9649
|
+
/* İLK ENTEGRASYON: EA + AutoTrading + grafik kurulumu otomatik */
|
|
9650
|
+
finMt5SetupEnsure(false)
|
|
9651
|
+
.then(() => setTimeout(() => { finEaStatusCheck().catch(() => {}); }, 7000))
|
|
9652
|
+
.catch(() => {});
|
|
9653
|
+
if (m.terminal && m.terminal.trade_allowed === false) {
|
|
9654
|
+
financeLog('[MT5] AutoTrading KAPALI görünüyor — kurulum yazıldıysa terminali yeniden başlat');
|
|
9655
|
+
}
|
|
9438
9656
|
} else if (m && m.error) {
|
|
9439
9657
|
financeLog('[MT5] bağlantı yok — ' + m.error);
|
|
9440
9658
|
if (/paket/i.test(m.error)) financeTryInstall();
|
|
@@ -9835,7 +10053,7 @@ ipcMain.handle('finance:state', async () => {
|
|
|
9835
10053
|
|
|
9836
10054
|
ipcMain.handle('finance:snapshot', async () => {
|
|
9837
10055
|
const f = finCfg();
|
|
9838
|
-
const st = financeEnsureBridge();
|
|
10056
|
+
const st = await financeEnsureBridge();
|
|
9839
10057
|
let account = st.account || null;
|
|
9840
10058
|
let positions = [];
|
|
9841
10059
|
let orders = [];
|
|
@@ -9886,7 +10104,7 @@ ipcMain.handle('finance:mode', async (_e, payload) => {
|
|
|
9886
10104
|
açık pozisyonlara dokunulmaz); finance tekrar açılınca MT5 gerekirse
|
|
9887
10105
|
yeniden otomatik başlar. */
|
|
9888
10106
|
if (financeState.mode) {
|
|
9889
|
-
try { financeEnsureBridge(); } catch {}
|
|
10107
|
+
try { await financeEnsureBridge(); } catch {}
|
|
9890
10108
|
try { await mt5bridge.call('policy', { launch: true }, 4000); } catch {}
|
|
9891
10109
|
} else {
|
|
9892
10110
|
try { await mt5bridge.call('policy', { launch: false }, 4000); } catch {}
|
|
@@ -10142,6 +10360,8 @@ function finTeamStart(f) {
|
|
|
10142
10360
|
}
|
|
10143
10361
|
}
|
|
10144
10362
|
|
|
10363
|
+
ipcMain.handle('finance:mt5:setup', () => finMt5SetupEnsure(true));
|
|
10364
|
+
|
|
10145
10365
|
ipcMain.handle('finance:trader:start', () => financeTraderStart());
|
|
10146
10366
|
|
|
10147
10367
|
ipcMain.handle('finance:trader:stop', async () => {
|
|
@@ -10187,7 +10407,7 @@ ipcMain.handle('finance:agent:spawn', async (_e, payload) => {
|
|
|
10187
10407
|
|
|
10188
10408
|
ipcMain.handle('finance:connect', async () => {
|
|
10189
10409
|
mt5bridge.stop();
|
|
10190
|
-
const st = financeEnsureBridge();
|
|
10410
|
+
const st = await financeEnsureBridge();
|
|
10191
10411
|
return { ok: true, bridge: st };
|
|
10192
10412
|
});
|
|
10193
10413
|
|
package/src/preload.js
CHANGED
|
@@ -120,6 +120,7 @@ contextBridge.exposeInMainWorld('beast', {
|
|
|
120
120
|
financeClose: (ticket, volume) => ipcRenderer.invoke('finance:close', { ticket, volume }),
|
|
121
121
|
financeCancel: (ticket) => ipcRenderer.invoke('finance:cancel', { ticket }),
|
|
122
122
|
financeInstall: () => ipcRenderer.invoke('finance:install'),
|
|
123
|
+
financeMt5Setup: () => ipcRenderer.invoke('finance:mt5:setup'),
|
|
123
124
|
financeSymbolsList: (filter) => ipcRenderer.invoke('finance:symbols:list', filter),
|
|
124
125
|
financeReport: () => ipcRenderer.invoke('finance:report'),
|
|
125
126
|
clipRead: () => ipcRenderer.invoke('clip:read'),
|
package/src/renderer/index.html
CHANGED
|
@@ -163,7 +163,7 @@
|
|
|
163
163
|
</div>
|
|
164
164
|
</div>
|
|
165
165
|
<div class="fin-card fin-card-trader" data-fin-card="trader">
|
|
166
|
-
<div class="fin-card-title">TRADE AJANI <span id="finTraderDot" class="fin-dot off" title="Trader durumu"></span><span class="file-spacer"></span><button id="finModelRefreshBtn" title="Modelleri yeniden çek — eksik/güncel modelleri tazeler">⟳</button><button id="finSkillsBtn" title="Rol → skill eşleştirmesi —
|
|
166
|
+
<div class="fin-card-title">TRADE AJANI <span id="finTraderDot" class="fin-dot off" title="Trader durumu"></span><span class="file-spacer"></span><button id="finSetupBtn" title="MT5 kurulumunu uygula — BeastFinance.mq5 derle + AutoTrading izni + grafiğe ekle">🛠</button><button id="finModelRefreshBtn" title="Modelleri yeniden çek — eksik/güncel modelleri tazeler">⟳</button><button id="finSkillsBtn" title="Rol → skill eşleştirmesi — rol başına tek skill (çöp ikonuyla kaldırılır; boş = ajan kendi seçer)">⚙</button><button id="finAdvToggle" type="button" aria-expanded="false" title="Gelişmiş — disiplin kuralları + shadow mod"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px"><path d="M4 6h9"/><circle cx="16.5" cy="6" r="2.5"/><path d="M20 6h0.01"/><path d="M4 12h3"/><circle cx="10.5" cy="12" r="2.5"/><path d="M15 12h5"/><path d="M4 18h11"/><circle cx="18.5" cy="18" r="2.5"/></svg></button></div>
|
|
167
167
|
<div class="fin-field">
|
|
168
168
|
<span>Model</span>
|
|
169
169
|
<select id="finTraderModel" title="Trader ajanının modeli — farklı API/model seçilebilir"></select>
|
|
@@ -183,13 +183,14 @@
|
|
|
183
183
|
<button id="finSymBtn" class="fin-sym-select" title="MT5 sembol listesinden seç — tıkla">…</button>
|
|
184
184
|
</div>
|
|
185
185
|
<div class="fin-field">
|
|
186
|
-
<span>Analiz ekibi <i class="fin-hint">—
|
|
187
|
-
<div id="finRoles" class="fin-roles" title="Trader'ın yanında koşacak uzman
|
|
186
|
+
<span>Analiz ekibi <i class="fin-hint">— çoklu seç: hangi uzman ajanlar koşacak (işlem açmaz)</i></span>
|
|
187
|
+
<div id="finRoles" class="fin-roles" title="Trader'ın yanında koşacak uzman ajanları seç — Risk / Teknik / Haber / Görsel; seçilen her rol AYRI sürekli ajan olarak koşar (işlem açmaz)"></div>
|
|
188
188
|
</div>
|
|
189
189
|
<div class="fin-field">
|
|
190
190
|
<span>Ajan talimatı <i class="fin-hint">— 1-2 cümle; trader + tüm paralel ajanlara iletilir</i></span>
|
|
191
191
|
<textarea id="finStrategy" rows="2" maxlength="2000" placeholder="örn. Her türde scalp yap — M1/M5 hızlı gir-çık, günlük kâr hedefine ulaşınca dur" title="Buraya yazdığın talimat trade ajanına ve koşan tüm paralel ajanlara (ekip + sembol işçileri) sistem promptunda öncelikli strateji notu olarak gider; kaydetmek için alandan çık"></textarea>
|
|
192
192
|
</div>
|
|
193
|
+
<div id="finAdvWrap" hidden>
|
|
193
194
|
<div class="fin-field">
|
|
194
195
|
<span>Disiplin <i class="fin-hint">— kodla zorlanır; 0 = kural kapalı</i></span>
|
|
195
196
|
<div class="fin-grid2">
|
|
@@ -206,6 +207,7 @@
|
|
|
206
207
|
<input id="finShadow" type="checkbox" /> Shadow mod — emir açmadan karar kaydı (canlı test)
|
|
207
208
|
</label>
|
|
208
209
|
</div>
|
|
210
|
+
</div>
|
|
209
211
|
<div class="fin-row fin-btn-row">
|
|
210
212
|
<button id="finTraderBtn" class="fin-start">▶︎ Ajanı Başlat</button>
|
|
211
213
|
</div>
|
|
@@ -777,7 +779,21 @@
|
|
|
777
779
|
</div>
|
|
778
780
|
<div class="mini-body">
|
|
779
781
|
<div id="finSkillsList" class="mini-list"></div>
|
|
780
|
-
<div class="fin-sym-hint">Her rol için TEK skill
|
|
782
|
+
<div class="fin-sym-hint">Her rol için TEK skill seçilir — aynı role birden fazla skill seçilemez. Seçili skill'i satırın sağ üstündeki çöp ikonuyla kaldırabilirsin; boş bırakırsan ajan skill'i göreve göre SKILLS kataloğundan kendi seçer. Seçim, koşan ajanlar dahil sonraki turdan itibaren sistem promptuna girer.</div>
|
|
783
|
+
</div>
|
|
784
|
+
</div>
|
|
785
|
+
</div>
|
|
786
|
+
|
|
787
|
+
<div id="finTeamOverlay" class="mini-overlay" hidden>
|
|
788
|
+
<div class="mini-dialog fin-sym-dialog">
|
|
789
|
+
<div class="mini-head">
|
|
790
|
+
<span class="mini-title">ANALİZ EKİBİ — AJAN SEÇ</span>
|
|
791
|
+
<span id="finTeamCount" class="fin-sym-count"></span>
|
|
792
|
+
<button class="mini-close" id="finTeamClose" title="Kapat">×</button>
|
|
793
|
+
</div>
|
|
794
|
+
<div class="mini-body">
|
|
795
|
+
<div id="finTeamPick" class="mini-list"></div>
|
|
796
|
+
<div class="fin-sym-hint">Tıkla: ajanı ekibe ekle/çıkar — seçilen her rol AYRI sürekli ajan olarak koşar (işlem açmaz). Değişiklik anında kaydedilir; ajanı başlatınca seçili roller başlar.</div>
|
|
781
797
|
</div>
|
|
782
798
|
</div>
|
|
783
799
|
</div>
|