beast-agent 2.38.4 → 2.40.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.
Files changed (41) hide show
  1. package/package.json +1 -1
  2. package/src/agent/bots.js +66 -0
  3. package/src/agent/customtools.js +52 -2
  4. package/src/agent/defaulttools/mt5_barlar2/run.js +188 -0
  5. package/src/agent/defaulttools/mt5_barlar2/tool.json +23 -0
  6. package/src/agent/defaulttools/mt5_bekleyen/run.js +100 -0
  7. package/src/agent/defaulttools/mt5_bekleyen/tool.json +17 -0
  8. package/src/agent/defaulttools/mt5_durum/run.js +93 -0
  9. package/src/agent/defaulttools/mt5_durum/tool.json +10 -0
  10. package/src/agent/defaulttools/mt5_emir/run.js +98 -0
  11. package/src/agent/defaulttools/mt5_emir/tool.json +17 -0
  12. package/src/agent/defaulttools/mt5_emir_iptal/run.js +90 -0
  13. package/src/agent/defaulttools/mt5_emir_iptal/tool.json +12 -0
  14. package/src/agent/defaulttools/mt5_fiyat/run.js +87 -0
  15. package/src/agent/defaulttools/mt5_fiyat/tool.json +16 -0
  16. package/src/agent/defaulttools/mt5_gecmis/run.js +87 -0
  17. package/src/agent/defaulttools/mt5_gecmis/tool.json +12 -0
  18. package/src/agent/defaulttools/mt5_kapat/run.js +92 -0
  19. package/src/agent/defaulttools/mt5_kapat/tool.json +13 -0
  20. package/src/agent/defaulttools/mt5_m15_m5/m15m5.py +60 -0
  21. package/src/agent/defaulttools/mt5_m15_m5/run.js +73 -0
  22. package/src/agent/defaulttools/mt5_m15_m5/tool.json +10 -0
  23. package/src/agent/defaulttools/mt5_pozisyon_gecmis/run.js +144 -0
  24. package/src/agent/defaulttools/mt5_pozisyon_gecmis/tool.json +12 -0
  25. package/src/agent/defaulttools/mt5_shot/run.js +428 -0
  26. package/src/agent/defaulttools/mt5_shot/tool.json +20 -0
  27. package/src/agent/defaulttools/mt5_sltp/run.js +92 -0
  28. package/src/agent/defaulttools/mt5_sltp/tool.json +14 -0
  29. package/src/agent/engine.js +259 -47
  30. package/src/agent/financetools.js +52 -0
  31. package/src/agent/mt5/BeastFinance.mq5 +427 -0
  32. package/src/agent/mt5/BeastShot.tpl +0 -0
  33. package/src/agent/mt5setup.js +542 -0
  34. package/src/agent/scripts/mt5_bridge.py +112 -0
  35. package/src/agent/seeds/mql5/SKILL.md +27 -2
  36. package/src/agent/seeds/tool-yazma/SKILL.md +6 -4
  37. package/src/main.js +233 -13
  38. package/src/preload.js +1 -0
  39. package/src/renderer/index.html +18 -5
  40. package/src/renderer/renderer.js +170 -37
  41. package/src/renderer/style.css +45 -17
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: mql5
3
- description: MetaTrader 5 tarafında MQL5 (script / indicator / Expert Advisor) yazma-derleme rehberi — mt5_* araçlarının yapamadığı işleri (özel hesap, olay yakalama, EA ile otomatik yürütme, dosya köprüsü) MQL5 ile çözmek gerektiğinde ÖNCE bu skill'i oku. Veri klasörünü bulma, MetaEditor ile derleme, MQL5\Files köprüsü ve hazır kod iskeletleri burada.
4
- version: 1.0.0
3
+ description: MetaTrader 5 tarafında MQL5 (script / indicator / Expert Advisor) yazma-derleme rehberi — mt5_* araçlarının yapamadığı işleri (özel hesap, olay yakalama, EA ile otomatik yürütme, dosya köprüsü) MQL5 ile çözmek gerektiğinde ÖNCE bu skill'i oku. BeastFinance EA (varsayılan, otomatik kurulur) + dosya köprüsü, veri klasörünü bulma, MetaEditor ile derleme ve hazır kod iskeletleri burada.
4
+ version: 1.1.0
5
5
  ---
6
6
 
7
7
  # MQL5 Tool Yazma (MetaTrader 5)
@@ -50,6 +50,31 @@ version: 1.0.0
50
50
 
51
51
  ## 4) ÇALIŞTIRMA + BEAST KÖPRÜSÜ
52
52
 
53
+ ### 4.0) BEASTFINANCE EA — VARSAYILAN, OTOMATİK KURULUR (ÖNCE BUNU KULLAN)
54
+
55
+ Beast Finance MT5'e bağlandığında sistem bunları otomatik yapar:
56
+ - `BeastFinance.mq5`'i `MQL5\Experts\Beast\` altına yazar ve MetaEditor ile derler,
57
+ - ilk grafiğe EA'yı ekler (gerçek MT5 formatı: `<expert>` bloğu `<window>` öncesi, `path=Experts\Beast\BeastFinance.ex5`, `expertmode=5`),
58
+ - `config\common.ini [Experts]` üzerinden AutoTrading iznini açar.
59
+
60
+ Yani MT5 entegrasyonu yazarken EA'yı SIFIRDAN YAZMA, elle iliştirme varsayma — köprü ZATEN kurulu:
61
+
62
+ | Dosya (MQL5\Files) | Yön | İçerik |
63
+ |---|---|---|
64
+ | `beast_ea.json` | EA → Beast | heartbeat: version, symbol, period, equity/balance, `terminal_trade_allowed`, `mql_trade_allowed`, positions, note |
65
+ | `beast_cmd.json` | Beast → EA | komut: `{id, cmd, params}` — desteklenen: ping / chart / status / note / shot |
66
+ | `beast_cmd_ack.json` | EA → Beast | komut sonucu: `{ok, id, cmd, result|error}` |
67
+ | `beast_note.json` | Beast → EA | grafik panosu: `{symbol?, text, levels:[{price,label}]}` — pano + yatay çizgiler; screenshot'ta görünür |
68
+
69
+ - GRAFİK GÖRÜNTÜSÜ: `shot` komutu `{file, width, height, symbol?, timeframe?, template?}` alır — ChartScreenShot ile GERÇEK PNG üretir. Aktif grafik istenen sembol/periyot ile aynıysa panoyu + seviye çizgilerini içerir; farklıysa EA `ChartOpen` + `BeastShot.tpl` (açık tema, EA bloğu yok) ile geçici grafik açıp kapatır. Bu komutu sarmalayan VARSAYILAN araç `tool__mt5_shot`'tır: PNG'yi çağıran ajana görsel olarak enjekte eder, `path` döndürür (send_file / agent_dm image ile paylaşılır). Seviyeleri grafikte göstermek için önce `mt5_ea note`, sonra `tool__mt5_shot` çağır — paralel ekipte teknik ajan seviyeleri çizer, görsel ajan screenshot ile teyit edip trader'a atar.
70
+
71
+ - Finance oturumlarındaki ajan aracı: `mt5_ea` (action: status|ping|chart|note); grafik PNG'si için varsayılan `tool__mt5_shot` (tüm oturumlarda açık).
72
+ - Yeni MT5 entegrasyonu gerekiyorsa ÖNCE bu köprüyü GENİŞLET: EA'da `ProcessCommands()` içine yeni komut + Beast tarafında `mt5_ea` / python `ea_cmd`. Sıfırdan EA yazma.
73
+ - EA kaynağı Beast uygulamasında `src/agent/mt5/BeastFinance.mq5`; güncelleme oradan yapılır, setup yeniden derler.
74
+ - Derleme hatalarında dosya kodlaması UTF-16 (`FILE_UNICODE`) kullanılır; MQL5'te `FILE_UTF8` yoktur.
75
+
76
+ ### 4.1) Elle script/EA çalıştırma
77
+
53
78
  - **Script**: MT5 → Navigator → Scripts → çift tık (kullanıcı) — Python API'den MQL5 tetiklenemez.
54
79
  - **EA**: chart'a iliştirilir; AutoTrading düğmesi açık olmalıdır.
55
80
  - **Dosya köprüsü (önerilen)**:
@@ -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
- ## DÜZENLEME / DOĞRULAMA
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. Kayıttan sonra tool ANINDA aktifleşir (yeniden başlatma gerekmez) — bir sonraki turda `tool__<slug>` çağrılabilir.
69
- 3. Doğrula: `run_command` ile `echo "{\"mesaj\":\"test\"}" | node "%APPDATA%\beast\tools\<slug>\run.js"` — çıktı JSON olmalı ve `ok` alanı içermeli.
70
- 4. Hata çıktısı `ok:false + error` olsun — model hatayı okuyup düzeltir; çıplak stack yasak.
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: {
@@ -3631,7 +3634,7 @@ app.whenReady().then(() => {
3631
3634
  reloadBackend();
3632
3635
  syncWhitelist(); // bot sistemi: whitelist.json aynası ilk açılışta garanti
3633
3636
  try { bots.ensureBotCodes(); } catch {} // her bota benzersiz 5 haneli kod garanti
3634
- try { customtools.seedIfEmpty(); } catch {} // kişisel toollar klasörü boşsa örnek tool kur
3637
+ try { customtools.seedDefaults(); customtools.seedIfEmpty(); } catch {} // varsayılan MT5 toolları + kişisel toollar klasörü boşsa örnek tool kur
3635
3638
  createSplash();
3636
3639
  createWindow();
3637
3640
  log.info('main', 'Beast Agent başlatıldı');
@@ -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) => customtools.save(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 EKİBİ ARTIK SADECE SAYI: elle rol seçimi kaldırıldı — atama daima
8491
- otomatik (Teknik → Risk → Haber). 0 = ekip kapalı GEÇERLİ değerdir;
8492
- yalnız eksik/bozuk değerde varsayılan 2'ye düşülür. */
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'),
@@ -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">&#x27F3;</button><button id="finSkillsBtn" title="Rol → skill eşleştirmesi — her role ZORUNLU tek skill (ajan her turda onu okur)">&#9881;</button></div>
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">&#x1F6E0;</button><button id="finModelRefreshBtn" title="Modelleri yeniden çek — eksik/güncel modelleri tazeler">&#x27F3;</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)">&#9881;</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,14 +183,13 @@
183
183
  <button id="finSymBtn" class="fin-sym-select" title="MT5 sembol listesinden seç — tıkla">&#8230;</button>
184
184
  </div>
185
185
  <div class="fin-field">
186
- <span>Analiz ekibi <i class="fin-hint">— sadece sayı seç, rolleri sistem otomatik atar</i></span>
187
- <div id="finRoles" class="fin-roles" title="Trader&#39;ın yanında koşacak uzman ajan SAYISI — roller otomatik atanır (Teknik → Risk → Haber); işlem açmazlar"></div>
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&#39;ı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
- <button id="finAdvToggle" class="fin-adv-toggle" type="button" aria-expanded="false" title="Disiplin kuralları + shadow mod — gelişmiş seçenekler">&#x25B8; Gelişmiş</button>
194
193
  <div id="finAdvWrap" hidden>
195
194
  <div class="fin-field">
196
195
  <span>Disiplin <i class="fin-hint">— kodla zorlanır; 0 = kural kapalı</i></span>
@@ -780,7 +779,21 @@
780
779
  </div>
781
780
  <div class="mini-body">
782
781
  <div id="finSkillsList" class="mini-list"></div>
783
- <div class="fin-sym-hint">Her rol için TEK skill ZORUNLUDUR — aynı role birden fazla skill seçilemez. Seçili skill kaldırılamaz; değiştirmek için başka bir skill'e tıkla. Seçim, koşan ajanlar dahil sonraki turdan itibaren rol ajanının sistem promptuna zorunlu skill olarak girer.</div>
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">&#x00D7;</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>
784
797
  </div>
785
798
  </div>
786
799
  </div>