beast-agent 2.39.0 → 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.
- package/package.json +1 -1
- package/src/agent/bots.js +2 -2
- package/src/agent/customtools.js +52 -2
- package/src/agent/defaulttools/mt5_barlar2/run.js +188 -0
- package/src/agent/defaulttools/mt5_barlar2/tool.json +23 -0
- package/src/agent/defaulttools/mt5_bekleyen/run.js +100 -0
- package/src/agent/defaulttools/mt5_bekleyen/tool.json +17 -0
- package/src/agent/defaulttools/mt5_durum/run.js +93 -0
- package/src/agent/defaulttools/mt5_durum/tool.json +10 -0
- package/src/agent/defaulttools/mt5_emir/run.js +98 -0
- package/src/agent/defaulttools/mt5_emir/tool.json +17 -0
- package/src/agent/defaulttools/mt5_emir_iptal/run.js +90 -0
- package/src/agent/defaulttools/mt5_emir_iptal/tool.json +12 -0
- package/src/agent/defaulttools/mt5_fiyat/run.js +87 -0
- package/src/agent/defaulttools/mt5_fiyat/tool.json +16 -0
- package/src/agent/defaulttools/mt5_gecmis/run.js +87 -0
- package/src/agent/defaulttools/mt5_gecmis/tool.json +12 -0
- package/src/agent/defaulttools/mt5_kapat/run.js +92 -0
- package/src/agent/defaulttools/mt5_kapat/tool.json +13 -0
- package/src/agent/defaulttools/mt5_m15_m5/m15m5.py +60 -0
- package/src/agent/defaulttools/mt5_m15_m5/run.js +73 -0
- package/src/agent/defaulttools/mt5_m15_m5/tool.json +10 -0
- package/src/agent/defaulttools/mt5_pozisyon_gecmis/run.js +144 -0
- package/src/agent/defaulttools/mt5_pozisyon_gecmis/tool.json +12 -0
- package/src/agent/defaulttools/mt5_shot/run.js +428 -0
- package/src/agent/defaulttools/mt5_shot/tool.json +20 -0
- package/src/agent/defaulttools/mt5_sltp/run.js +92 -0
- package/src/agent/defaulttools/mt5_sltp/tool.json +14 -0
- package/src/agent/engine.js +51 -16
- package/src/agent/financetools.js +1 -1
- package/src/agent/mt5/BeastFinance.mq5 +140 -3
- package/src/agent/mt5/BeastShot.tpl +0 -0
- package/src/agent/mt5setup.js +22 -0
- package/src/agent/seeds/mql5/SKILL.md +4 -2
- package/src/main.js +1 -1
- package/src/renderer/renderer.js +11 -1
- package/src/renderer/style.css +15 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// MT5 SL/TP GUNCELLE — stdin: JSON args · stdout: JSON sonuç
|
|
3
|
+
const { spawn } = require('child_process');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
/* TAŞINABİLİR YOL ÇÖZÜMÜ: Beast gömülü python → sistem python'ları → PATH.
|
|
8
|
+
Köprü dosyası %APPDATA%\beast\finance\mt5_bridge.py'den (veya BEAST_FINANCE_DIR)
|
|
9
|
+
okunur; ortam değişkenleriyle geçersiz kılınabilir. */
|
|
10
|
+
function resolvePython() {
|
|
11
|
+
const cands = [];
|
|
12
|
+
if (process.env.BEAST_PYTHON) cands.push({ exe: String(process.env.BEAST_PYTHON), args: [] });
|
|
13
|
+
if (process.env.APPDATA) cands.push({ exe: path.join(process.env.APPDATA, 'beast', 'py', 'python.exe'), args: [] });
|
|
14
|
+
for (const v of ['314', '313', '312', '311', '310']) cands.push({ exe: 'C:\\Python' + v + '\\python.exe', args: [] });
|
|
15
|
+
cands.push({ exe: 'python', args: [] }, { exe: 'py', args: ['-3'] });
|
|
16
|
+
for (const c of cands) {
|
|
17
|
+
if (c.exe === 'python' || c.exe === 'py') return c;
|
|
18
|
+
try { if (fs.existsSync(c.exe)) return c; } catch (e) {}
|
|
19
|
+
}
|
|
20
|
+
return { exe: 'python', args: [] };
|
|
21
|
+
}
|
|
22
|
+
function resolveBridge() {
|
|
23
|
+
const cands = [];
|
|
24
|
+
if (process.env.BEAST_BRIDGE) cands.push(String(process.env.BEAST_BRIDGE));
|
|
25
|
+
if (process.env.BEAST_FINANCE_DIR) cands.push(path.join(String(process.env.BEAST_FINANCE_DIR), 'mt5_bridge.py'));
|
|
26
|
+
if (process.env.APPDATA) cands.push(path.join(process.env.APPDATA, 'beast', 'finance', 'mt5_bridge.py'));
|
|
27
|
+
for (const p of cands) { try { if (p && fs.existsSync(p)) return p; } catch (e) {} }
|
|
28
|
+
return cands[0] || '';
|
|
29
|
+
}
|
|
30
|
+
const PYSPEC = resolvePython();
|
|
31
|
+
const PY = PYSPEC.exe;
|
|
32
|
+
const PY_ARGS = PYSPEC.args;
|
|
33
|
+
const BRIDGE = resolveBridge();
|
|
34
|
+
|
|
35
|
+
const TIMEOUT = 35000;
|
|
36
|
+
|
|
37
|
+
function call(requests) {
|
|
38
|
+
return new Promise((resolve) => {
|
|
39
|
+
let py;
|
|
40
|
+
try { py = spawn(PY, [...PY_ARGS, BRIDGE], { windowsHide: true, stdio: ['pipe', 'pipe', 'pipe'] }); }
|
|
41
|
+
catch (e) { return resolve({ ok: false, error: 'python baslatilamadi: ' + e.message }); }
|
|
42
|
+
const results = {};
|
|
43
|
+
let buf = '';
|
|
44
|
+
let errTail = '';
|
|
45
|
+
let settled = false;
|
|
46
|
+
const finish = (obj) => { if (!settled) { settled = true; clearTimeout(timer); try { py.kill(); } catch (e) {} resolve(obj); } };
|
|
47
|
+
const timer = setTimeout(() => finish({ ok: false, error: 'zaman asimi: MT5 terminali acik ve yanit veriyor mu?' }), TIMEOUT);
|
|
48
|
+
py.stdout.on('data', (d) => {
|
|
49
|
+
buf += d.toString('utf8');
|
|
50
|
+
let i;
|
|
51
|
+
while ((i = buf.indexOf('\n')) >= 0) {
|
|
52
|
+
const line = buf.slice(0, i).trim(); buf = buf.slice(i + 1);
|
|
53
|
+
if (!line) continue;
|
|
54
|
+
let o = null;
|
|
55
|
+
try { o = JSON.parse(line); } catch (e) { continue; }
|
|
56
|
+
if (o && o.event) continue;
|
|
57
|
+
if (o && typeof o.id === 'number' && Object.prototype.hasOwnProperty.call(o, 'ok')) {
|
|
58
|
+
results[o.id] = o;
|
|
59
|
+
if (Object.keys(results).length >= requests.length) {
|
|
60
|
+
const arr = requests.map((_, k) => results[k + 1]);
|
|
61
|
+
finish(arr.length === 1 ? arr[0] : { ok: true, results: arr });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
py.stderr.on('data', (d) => { errTail = (errTail + d.toString('utf8')).slice(-800); });
|
|
67
|
+
py.on('error', (e) => finish({ ok: false, error: 'python baslatilamadi: ' + e.message }));
|
|
68
|
+
py.on('close', (code) => { if (Object.keys(results).length < requests.length) finish({ ok: false, error: 'bridge erken cikti code=' + code + ' ' + errTail }); });
|
|
69
|
+
requests.forEach((r, k) => py.stdin.write(JSON.stringify({ id: k + 1, method: r.method, params: r.params || {} }) + '\n'));
|
|
70
|
+
py.stdin.end();
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
(async function main() {
|
|
75
|
+
let args = {};
|
|
76
|
+
try { args = JSON.parse(fs.readFileSync(0, 'utf8') || '{}'); } catch (e) {}
|
|
77
|
+
const ticket = Number(args.ticket || 0);
|
|
78
|
+
if (!ticket) return console.log(JSON.stringify({ ok: false, error: 'ticket zorunlu' }));
|
|
79
|
+
if (args.sl === undefined && args.tp === undefined) return console.log(JSON.stringify({ ok: false, error: 'sl veya tp vermelisin' }));
|
|
80
|
+
const params = { ticket: ticket, sl: Number(args.sl || 0), tp: Number(args.tp || 0) };
|
|
81
|
+
const r = await call([{ method: 'modify', params: params }]);
|
|
82
|
+
if (r.ok && r.data && r.data.result) {
|
|
83
|
+
const res = r.data.result;
|
|
84
|
+
console.log(JSON.stringify({ ok: true, retcode: res.retcode, comment: res.comment, detay: r.data }));
|
|
85
|
+
} else {
|
|
86
|
+
console.log(JSON.stringify({ ok: false, error: r.error || 'SL/TP guncelleme reddedildi' }));
|
|
87
|
+
}
|
|
88
|
+
})();
|
|
89
|
+
|
|
90
|
+
/* PATCH 2026-09-10b: electron app-mode cocuk prosesi kapanmiyordu (90sn timeout).
|
|
91
|
+
stdout'un boruya bosalmasi icin kisa bekleme, sonra zorla cik. */
|
|
92
|
+
setTimeout(() => process.exit(0), 1500);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mt5_sltp",
|
|
3
|
+
"description": "Açık pozisyonun STOP LOSS / TAKE PROFIT seviyelerini günceller: ticket zorunlu, sl ve/veya tp verilir (0 = o seviyeyi kaldir). SL'siz pozisyon bırakmamak için risk yönetiminde kullanılır.",
|
|
4
|
+
"parameters": {
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"ticket": { "type": "number", "description": "Pozisyonun ticket numarasi" },
|
|
8
|
+
"sl": { "type": "number", "description": "Yeni stop loss fiyati (0 = kaldir)" },
|
|
9
|
+
"tp": { "type": "number", "description": "Yeni take profit fiyati (0 = kaldir)" }
|
|
10
|
+
},
|
|
11
|
+
"required": ["ticket"]
|
|
12
|
+
},
|
|
13
|
+
"updatedAt": "2026-09-09T18:48:00.000Z"
|
|
14
|
+
}
|
package/src/agent/engine.js
CHANGED
|
@@ -402,6 +402,7 @@ class Engine {
|
|
|
402
402
|
if (nrBoot.unref) nrBoot.unref();
|
|
403
403
|
skills.seedIfEmpty();
|
|
404
404
|
agentdefs.seedIfEmpty();
|
|
405
|
+
try { customtools.seedDefaults(); } catch {} // varsayılan MT5 toolları (mt5_shot, mt5_barlar2, ...) — tüm oturumlara açılır
|
|
405
406
|
}
|
|
406
407
|
|
|
407
408
|
/* ---------- opencode agent.ts port: özel ajanlar ---------- */
|
|
@@ -1918,11 +1919,11 @@ class Engine {
|
|
|
1918
1919
|
risk:
|
|
1919
1920
|
'ROL: RİSK AJANI 🛡 — portföyün RİSK GÖZCÜSÜSÜN, İşlem AÇMAZSIN (mt5_trade/mt5_pending/mt5_close KULLANMA). Her turda: hesap + pozisyonlar + marj kullanımı → kaldıraç/exposure değerlendirmesi; SL\u2019siz pozisyon, limit aşımı, tek yönlü birikme, günlük kayıp hızı risklerini raporla; net düzeltme önerisi ver (hangi pozisyon küçültülmeli/kapatılmalı).',
|
|
1920
1921
|
technic:
|
|
1921
|
-
'ROL: TEKNİK ANALİZ AJANI 📊 — fiyat yapısı uzmanısın, İşlem AÇMAZSIN (mt5_trade/mt5_pending/mt5_close KULLANMA). Her turda odak semboller için: trend/yapı, destek-direnç bölgeleri, momentum (mt5_market + mt5_history verisiyle); sembol başına AL/SAT/BEKLE + giriş/SL/TP fikri üret — trader bu öneriyi işleme çevirir.',
|
|
1922
|
+
'ROL: TEKNİK ANALİZ AJANI 📊 — fiyat yapısı uzmanısın, İşlem AÇMAZSIN (mt5_trade/mt5_pending/mt5_close KULLANMA). Her turda odak semboller için: trend/yapı, destek-direnç bölgeleri, momentum (mt5_market + mt5_history verisiyle); sembol başına AL/SAT/BEKLE + giriş/SL/TP fikri üret — trader bu öneriyi işleme çevirir. Bulgularını mt5_ea action:"note" ile grafiğe ÇİZ (destek/direnç/SL/TP seviyeleri) ve tool__mt5_shot ile seviyelerin göründüğünü teyit et; önemli seviyeleri görselle birlikte agent_dm ile trader\'a/ekibe ilet — grafik üzerinde ortak karar alın.',
|
|
1922
1923
|
macro:
|
|
1923
1924
|
'ROL: MAKRO AJANI 🌍 — büyük resim uzmanısın, İşlem AÇMAZSIN (mt5_trade/mt5_pending/mt5_close KULLANMA). Her turda web_search ile güncel makro manşetleri + ekonomik takvim riskleri (faiz, CPI, jeopolitik); DXY/altın/petrol bağıntılarını odak sembollere çevir; sembol başına yön eğilimi + TEMKİN/BEKLE notu ver.',
|
|
1924
1925
|
visual:
|
|
1925
|
-
'ROL: GÖRSEL ANALİZ AJANI 👁 — grafik/ekran görüntüsü uzmanısın, İşlem AÇMAZSIN (mt5_trade/mt5_pending/mt5_close KULLANMA).
|
|
1926
|
+
'ROL: GÖRSEL ANALİZ AJANI 👁 — grafik/ekran görüntüsü uzmanısın, İşlem AÇMAZSIN (mt5_trade/mt5_pending/mt5_close KULLANMA). MT5 grafiği için ÖNCE tool__mt5_shot kullan (BeastFinance EA "shot": gerçek grafik PNG + görsel SONRAKİ TURDA gözüne gelir; symbol/timeframe vererek başka sembol/periyot çekebilirsin; dönen path send_file ile gönderilebilir); gerekirse EA panosuna mt5_ea action:"note" ile plan/seviye yaz. web grafiklerinde browser_open + browser_screenshot; bilgisayar ekranı için computer_look; görsel göremeyen metin-model isen ocr_read (source:"screen"/"browser") kullan. Gördüğün yapıyı yorumla: trend, formasyon, mum yapısı, destek-direnç ve SL/TP çizgileri; sembol başına GÖRSEL TEYİT + AL/SAT/BEKLE notu üret. Önemli bulguyu GÖRSELİYLE paylaş: agent_dm image:true (son ekran görüntün) ya da image:"<mt5_shot path>" ile ANA TRADER\'a/ekibe gönder — karşı ajan görüntüyü GERÇEKTEN görür, AJAN DM panelinde açılır.',
|
|
1926
1927
|
})[String((session && session.financeRole) || '')] || '';
|
|
1927
1928
|
/* ROL → SKILL eşleştirmesi (ayarlar modalı): rol başına TEK ve ZORUNLU
|
|
1928
1929
|
skill; ANA TRADER için ayrıca PLAYBOOK skill'i (roleSkills.trader).
|
|
@@ -1962,19 +1963,22 @@ class Engine {
|
|
|
1962
1963
|
(roleBlockFull ? roleBlockFull + '\n' : '') +
|
|
1963
1964
|
(teamLine || '') +
|
|
1964
1965
|
'MT5 ARAÇLARI: mt5_status (bağlantı), mt5_account (hesap), mt5_market (canlı fiyat), mt5_positions (açık pozisyonlar), mt5_orders (bekleyen emirler), mt5_history (kapanan işlemler), mt5_ea (BeastFinance grafik panosu: status/ping/chart/note), mt5_trade (piyasa emri), mt5_close (kapat), mt5_modify (SL/TP), mt5_pending (bekleyen emir), mt5_cancel (emir iptal).\n' +
|
|
1965
|
-
'
|
|
1966
|
+
'KİŞİSEL MT5 ARAÇLARI (VARSAYILAN KURULU — tool__* tüm oturumlarda çağrılabilir): tool__mt5_shot (grafikten GERÇEK PNG + görsel ajana enjekte — grafik işlerinde BİRİNCİL), tool__mt5_barlar2 (OHLC mumlar, köprüsüz), tool__mt5_m15_m5 (GOLD M15+M5 hazır paket), tool__mt5_fiyat, tool__mt5_durum (hesap+pozisyon+emir tek çağrı), tool__mt5_gecmis, tool__mt5_pozisyon_gecmis, tool__mt5_sltp, tool__mt5_kapat, tool__mt5_bekleyen, tool__mt5_emir, tool__mt5_emir_iptal.\n' +
|
|
1967
|
+
'BEASTFINANCE EA (OTOMATİK GRAFİK UZMANI — ENTEGRASYON KANALI): MT5 terminaline bağlanıldığında BeastFinance uzman danışmanı İLK GRAFİĞE OTOMATİK yüklenir, AutoTrading izni açılır (kurulum sistem tarafından yapılır; elle ekleme gerekmez). Grafik panosu + seviye çizgileri + dosya köprüsü (beast_ea.json / beast_cmd.json / beast_note.json) bu EA üzerinden yürür: entegrasyon işlerinde (status/ping/chart/note) mt5_ea kullan; ekran görüntüsü işlerinde tool__mt5_shot ("shot" komutu — gerçek PNG + ajan görseli) birincildir. Yazdığın not ve çizgiler tool__mt5_shot ve computer_look screenshot\'ında GÖRÜNÜR.\n' +
|
|
1966
1968
|
'YETKİLERİN (AÇIK — çekinmeden kullan):\n' +
|
|
1967
1969
|
'- skill: kurulu SKILL.md kataloğunu oku ve uygula — tool yazmadan ÖNCE skill("tool-yazma"), MT5 tarafı işlerden ÖNCE skill("mql5") oku ve prosedürüne birebir uy.\n' +
|
|
1968
1970
|
'- Kişisel tool yazma: %APPDATA%\\beast\\tools\\<slug>\\ içine tool.json + run.js yaz (write_file/edit_file); run_command ile çıktısını (JSON, ok alanlı) doğrula → tool__<slug> ANINDA tüm finance ajanlarında çağrılabilir olur.\n' +
|
|
1969
1971
|
'- MQL5: MT5 tarafında script/gösterge/EA yaz (write_file), metaeditor64.exe /compile ile derle, MQL5\\Files dosya köprüsüyle veriyi Beast\'e taşı; kullanıcıya çalıştırma adımını açıkça söyle.\n' +
|
|
1970
1972
|
'- Yerleşik araçlar: run_command, python_run, read_file/write_file/edit_file, web_search/deep_search, browser_*, computer_look (ekran görüntüsü) — hepsi açık.\n' +
|
|
1971
|
-
'GRAFİK &
|
|
1972
|
-
'-
|
|
1973
|
-
'- mt5_ea action:"note": grafiğe kısa
|
|
1974
|
-
'- browser_screenshot: web
|
|
1975
|
-
'- Görsel göremiyorsan (metin-model) ocr_read
|
|
1973
|
+
'GRAFİK & GÖRSEL DOĞRULAMA (karar öncesi — vazgeçilmez):\n' +
|
|
1974
|
+
'- tool__mt5_shot: MT5 grafiğinin GERÇEK PNG\'si (BeastFinance EA "shot" komutu). Görsel SONRAKİ TURDA gözüne gelir; aktif grafikte Beast panosu + mt5_ea note ile çizilen seviyeler GÖRÜNÜR. symbol/timeframe ver → EA geçici grafik açıp o sembol/periyottan çeker; dönen path send_file ile kullanıcıya gönderilebilir. Grafik analizinde İLK tercih budur.\n' +
|
|
1975
|
+
'- mt5_ea action:"note": grafiğe kısa plan metni + yatay seviye çizgileri yazar (destek/direnç/SL/TP) — sonra tool__mt5_shot ile çekip seviyelerin doğru yerde olduğunu GÖRSEL doğrula.\n' +
|
|
1976
|
+
'- computer_look: tüm masaüstü ekranı (MT5 dışı pencereler dahil); browser_screenshot: web grafikleri (TradingView/Investing) — browser_open ile aç.\n' +
|
|
1977
|
+
'- Görsel göremiyorsan (metin-model) ocr_read (source:"screen"/"browser") ile grafikteki fiyat/seviyeleri metne çevir.\n' +
|
|
1976
1978
|
'- Grafikte gezinme/ölçek: computer_act ile timeframe, scroll, zoom (arka planda çalışır — kullanıcının faresini çalmaz).\n' +
|
|
1977
|
-
'-
|
|
1979
|
+
'- EKİPLE GÖRSEL PAYLAŞIM: chart PNG\'sini agent_dm image:true (son görüntün) ya da image:"<dosya yolu>" (ör. tool__mt5_shot dönen path) ile trader/ekibe gönder — karşı ajan görüntüyü GERÇEKTEN görür, AJAN DM panelinde açılır. Ortak kararlarda grafiği paylaşmak zorunlu disiplindir.\n' +
|
|
1980
|
+
'- PARALEL EKİP AKIŞI: teknik ajan seviyeleri hesaplar → mt5_ea note ile grafiğe çizer; görsel ajan tool__mt5_shot ile çekip TEYİT eder ve agent_dm ile görseli trader\'a atar; risk ajanı aynı görsel üzerinden SL/TP yerleşimini denetler; trader kararı işleme çevirir. Aynı sembolde koşan ajanlar tek DM grubunda (agent_dm group) toplanır — çelişen hareket etme.\n' +
|
|
1981
|
+
'- EKSİK ARAÇ: özel grafik aracı gerekiyorsa (ör. çoklu timeframe tek görüntü, indikatör paneli okuma) VAR SAYMA — tool_request ile TOOL botuna yazdır (doğrulanınca tool__<ad> olarak ANINDA çağrılır); küçük aracı skill("tool-yazma") prosedürüyle kendin de yazabilirsin.\n' +
|
|
1978
1982
|
'VERİ AKIŞI (her değerlendirmede): mt5_account + mt5_positions + mt5_market çağrılarını AYNI turda PARALEL ver; gerekiyorsa mt5_history ile son işlemleri gör.\n' +
|
|
1979
1983
|
'PARALEL + KOORDİNASYON: uzun araştırma/işleri run_background ile paralel finance işçisine devret (parent finance olduğu için işçi mt5 okuma araçlarını görür); koşan ajanlarla konuşmak için agent_dm (to: ajan başlığındaki anahtar kelime, örn "GOLD"; ortak karar için group: "İSİM" ile grup sohbeti kur — mesaj tüm üyelere düşer). Görevin bitince DM/grup sohbetleri otomatik KAPANIR (geçmiş panelde kalır).\n' +
|
|
1980
1984
|
(symbols ? `İZLEME LİSTESİ: ${symbols}\n` : '') +
|
|
@@ -2049,7 +2053,7 @@ class Engine {
|
|
|
2049
2053
|
if (bctx) {
|
|
2050
2054
|
parts.push(
|
|
2051
2055
|
'# MT5 / BEAST FINANCE ENTEGRASYONU\n' +
|
|
2052
|
-
'Beast Finance açıldığında MT5 terminaline bağlanılır; BeastFinance.mq5 uzman danışmanı İLK GRAFİĞE OTOMATİK kurulur ve AutoTrading açılır. Grafik/entegrasyon işleri bu EA üzerinden yürür (heartbeat beast_ea.json, komut köprüsü beast_cmd.json, grafik panosu/seviyeler beast_note.json; finance oturumlarında mt5_ea status/ping/chart/note) — pano ve çizgiler screenshot\'
|
|
2056
|
+
'Beast Finance açıldığında MT5 terminaline bağlanılır; BeastFinance.mq5 uzman danışmanı İLK GRAFİĞE OTOMATİK kurulur ve AutoTrading açılır. Grafik/entegrasyon işleri bu EA üzerinden yürür (heartbeat beast_ea.json, komut köprüsü beast_cmd.json, grafik panosu/seviyeler beast_note.json; finance oturumlarında mt5_ea status/ping/chart/note). Grafik görseli için varsayılan kurulu tool__mt5_shot kullan (EA "shot" komutu: gerçek PNG + görsel ajana enjekte edilir; path send_file/agent_dm ile paylaşılabilir) — pano ve çizgiler bu screenshot\'ta görünür. Elle EA ekleme varsayma; eksik araç gerekiyorsa Tool botuna tool_request at.'
|
|
2053
2057
|
);
|
|
2054
2058
|
}
|
|
2055
2059
|
/* opencode instruction port (ajan modu): workspace AGENTS/CLAUDE/CONTEXT
|
|
@@ -4324,7 +4328,7 @@ class Engine {
|
|
|
4324
4328
|
const imgMsg = {
|
|
4325
4329
|
role: 'user',
|
|
4326
4330
|
content: [
|
|
4327
|
-
{ type: 'text', text: '[
|
|
4331
|
+
{ type: 'text', text: '[araç görseli — bu kareyi analiz et ve devam et]' },
|
|
4328
4332
|
{ type: 'image_url', image_url: { url: injectedImage } },
|
|
4329
4333
|
],
|
|
4330
4334
|
};
|
|
@@ -5723,7 +5727,7 @@ const AGENT_DM_DEF = {
|
|
|
5723
5727
|
function: {
|
|
5724
5728
|
name: 'agent_dm',
|
|
5725
5729
|
description:
|
|
5726
|
-
'Send a short DM to another running agent (parallel agents / finance agents) to coordinate: share findings, ask status, warn about risk, hand off work, and MAKE JOINT DECISIONS. `to` = target session id OR a keyword from the agent title (e.g. "GOLD", "Trader"). `topic` = short subject label — replies to the same topic stay in the SAME conversation thread, so ALWAYS reuse the topic you were DMed with when replying. `group` = optional group-chat name (e.g. "GOLD EKIP"): creates or reuses a group conversation, adds the target agent as a member, and your message is delivered to EVERY member — use groups when a decision needs multiple agents. `image
|
|
5730
|
+
'Send a short DM to another running agent (parallel agents / finance agents) to coordinate: share findings, ask status, warn about risk, hand off work, and MAKE JOINT DECISIONS. `to` = target session id OR a keyword from the agent title (e.g. "GOLD", "Trader"). `topic` = short subject label — replies to the same topic stay in the SAME conversation thread, so ALWAYS reuse the topic you were DMed with when replying. `group` = optional group-chat name (e.g. "GOLD EKIP"): creates or reuses a group conversation, adds the target agent as a member, and your message is delivered to EVERY member — use groups when a decision needs multiple agents. `image` shares a chart/screen as an attachment the receiving agent REALLY sees and the AJAN DM panel shows: true = your last screenshot (fresh capture if none); a file path (e.g. the tool__mt5_shot "path") or a data URL = that exact image.',
|
|
5727
5731
|
parameters: {
|
|
5728
5732
|
type: 'object',
|
|
5729
5733
|
properties: {
|
|
@@ -5731,7 +5735,7 @@ const AGENT_DM_DEF = {
|
|
|
5731
5735
|
topic: { type: 'string', description: 'Short subject label for the conversation thread, e.g. "GOLD pozisyon riski"' },
|
|
5732
5736
|
message: { type: 'string', description: 'Short message (1-3 sentences)' },
|
|
5733
5737
|
group: { type: 'string', description: 'Optional group-chat name — send to ALL members of that group (creates it on first use, adds the target agent)' },
|
|
5734
|
-
image: { type: 'boolean', description: 'true
|
|
5738
|
+
image: { type: ['boolean', 'string'], description: 'true = son ekran görüntün (yoksa taze yakalar); dosya yolu (ör. tool__mt5_shot dönen PNG path) ya da data:image URL = o görsel iliştirilir. Panelde ve karşı ajanda GÖRÜNÜR; grafik/ekran bulgusunu paylaşmak için kullan' },
|
|
5735
5739
|
},
|
|
5736
5740
|
required: ['message'],
|
|
5737
5741
|
},
|
|
@@ -6547,9 +6551,17 @@ Engine.prototype._agentDmSend = async function (fromSid, args) {
|
|
|
6547
6551
|
const to = String((args && args.to) || '').trim();
|
|
6548
6552
|
const text = String((args && args.message) || '').trim().slice(0, 1200);
|
|
6549
6553
|
if (!text) return { ok: false, error: 'mesaj boş' };
|
|
6550
|
-
/* GÖRSEL DM: son ekran görüntüsü (yoksa taze yakalama)
|
|
6551
|
-
|
|
6552
|
-
|
|
6554
|
+
/* GÖRSEL DM: image:true → son ekran görüntüsü (yoksa taze yakalama);
|
|
6555
|
+
image:"<dosya yolu>" ya da data URL → o görsel BİREBİR iliştirilir
|
|
6556
|
+
(ör. tool__mt5_shot dönen PNG path'i). Karşı ajan görüntüyü görür. */
|
|
6557
|
+
const imgArg = args && args.image;
|
|
6558
|
+
let image = '';
|
|
6559
|
+
if (typeof imgArg === 'string' && imgArg.trim()) {
|
|
6560
|
+
const s = imgArg.trim();
|
|
6561
|
+
image = /^data:image\//i.test(s) ? s : this._agentDmImageFromFile(s);
|
|
6562
|
+
} else if (imgArg === true || imgArg === 'true') {
|
|
6563
|
+
image = await this._agentDmCaptureImage(fromSid);
|
|
6564
|
+
}
|
|
6553
6565
|
const groupName = String((args && args.group) || '').replace(/\s+/g, ' ').trim().slice(0, 40);
|
|
6554
6566
|
const jobs = this._bgJobs || new Map();
|
|
6555
6567
|
const fromJob = jobs.get(String(fromSid));
|
|
@@ -6722,6 +6734,29 @@ Engine.prototype._agentDmSend = async function (fromSid, args) {
|
|
|
6722
6734
|
}
|
|
6723
6735
|
};
|
|
6724
6736
|
|
|
6737
|
+
/* AJAN DM görseli (dosyadan): png/jpg/webp/gif dosyasını data URL'e çevirir.
|
|
6738
|
+
Send_file kapısına takılmadan (ör. tool__mt5_shot path'i) görsel paylaşımı;
|
|
6739
|
+
2.5MB üstü DM kaydını şişirmesin diye atlanır. */
|
|
6740
|
+
Engine.prototype._agentDmImageFromFile = function (p) {
|
|
6741
|
+
try {
|
|
6742
|
+
const fp = String(p || '').trim();
|
|
6743
|
+
if (!fp) return '';
|
|
6744
|
+
const ext = path.extname(fp).toLowerCase();
|
|
6745
|
+
const mime =
|
|
6746
|
+
ext === '.png' ? 'image/png'
|
|
6747
|
+
: ext === '.jpg' || ext === '.jpeg' ? 'image/jpeg'
|
|
6748
|
+
: ext === '.webp' ? 'image/webp'
|
|
6749
|
+
: ext === '.gif' ? 'image/gif'
|
|
6750
|
+
: '';
|
|
6751
|
+
if (!mime) return '';
|
|
6752
|
+
const buf = fs.readFileSync(fp);
|
|
6753
|
+
if (!buf.length || buf.length > 2500000) return '';
|
|
6754
|
+
return 'data:' + mime + ';base64,' + buf.toString('base64');
|
|
6755
|
+
} catch {
|
|
6756
|
+
return '';
|
|
6757
|
+
}
|
|
6758
|
+
};
|
|
6759
|
+
|
|
6725
6760
|
/* AJAN DM görseli: gönderenin oturumundaki EN SON ekran görüntüsünü (yoksa
|
|
6726
6761
|
taze yakalama) data URL olarak döndürür. Çok büyük görseller DM kaydını
|
|
6727
6762
|
şişirmesin diye 2.5MB üstü atlanır. */
|
|
@@ -229,7 +229,7 @@ const definitions = NAMES.map((name) => {
|
|
|
229
229
|
},
|
|
230
230
|
mt5_ea: {
|
|
231
231
|
description:
|
|
232
|
-
'BEASTFINANCE EA KÖPRÜSÜ (grafikte çalışan uzman danışman): action:"status" → EA heartbeat (yüklü mü, AutoTrading/EA izni, equity, pozisyon, son ack); "ping" → EA canlı yanıt; "chart" → aktif grafiğin sembol/periyot/fiyat/spread bilgisi; "note" → {symbol?, text, levels:[{price,label}]} grafik panosuna not + yatay seviye çizgileri yazar. NOT: yazdığın pano ve çizgiler görsel ajanın
|
|
232
|
+
'BEASTFINANCE EA KÖPRÜSÜ (grafikte çalışan uzman danışman): action:"status" → EA heartbeat (yüklü mü, AutoTrading/EA izni, equity, pozisyon, son ack); "ping" → EA canlı yanıt; "chart" → aktif grafiğin sembol/periyot/fiyat/spread bilgisi; "note" → {symbol?, text, levels:[{price,label}]} grafik panosuna not + yatay seviye çizgileri yazar. NOT: yazdığın pano ve çizgiler görsel ajanın screenshot\'ında GÖRÜNÜR — GERÇEK grafik PNG\'si için varsayılan kurulu tool__mt5_shot kullan (EA "shot" komutu; görsel ajanın gözüne gelir), seviyeleri çizdikten sonra tool__mt5_shot ile görsel doğrula; grafiği agent_dm image ile ekibe paylaş.',
|
|
233
233
|
parameters: {
|
|
234
234
|
type: 'object',
|
|
235
235
|
properties: {
|
|
@@ -170,9 +170,10 @@ void ApplyLevels(const string raw)
|
|
|
170
170
|
if(end < 0) return;
|
|
171
171
|
string body = StringSubstr(raw, arr + 1, end - arr - 1);
|
|
172
172
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
173
|
+
string names[];
|
|
174
|
+
ArrayResize(names, 64); /* FIX: dizi boyutlandirilmadan atama EA'yi dusuruyordu */
|
|
175
|
+
int n = 0;
|
|
176
|
+
int pos = 0;
|
|
176
177
|
while(pos < StringLen(body))
|
|
177
178
|
{
|
|
178
179
|
int p = StringFind(body, "\"price\"", pos);
|
|
@@ -279,6 +280,96 @@ void ProcessCommands()
|
|
|
279
280
|
RefreshPanel();
|
|
280
281
|
result = "{\"note\":true}";
|
|
281
282
|
}
|
|
283
|
+
else if(cmd == "shot")
|
|
284
|
+
{
|
|
285
|
+
/* ChartScreenShot -> MQL5\Files\<file> (png/gif/bmp). params:
|
|
286
|
+
file, width, height, timeframe (M15/H1/...), symbol (bos=aktif grafik)
|
|
287
|
+
Aktif grafik zaten istenen sembol+periyot ise ondan cekilir
|
|
288
|
+
(Beast panosu + seviye cizgileri gorunur); degilse gecici grafik acilir. */
|
|
289
|
+
string file = JsonGet(raw, "file");
|
|
290
|
+
if(StringLen(file) == 0) file = "beast_shot.png";
|
|
291
|
+
int w = (int)StringToInteger(JsonGet(raw, "width"));
|
|
292
|
+
int hh = (int)StringToInteger(JsonGet(raw, "height"));
|
|
293
|
+
if(w <= 0) w = 1600;
|
|
294
|
+
if(hh <= 0) hh = 900;
|
|
295
|
+
|
|
296
|
+
string symTxt = JsonGet(raw, "symbol");
|
|
297
|
+
string tfTxt = JsonGet(raw, "timeframe");
|
|
298
|
+
|
|
299
|
+
long cid = ChartID();
|
|
300
|
+
string symNow = ChartSymbol(cid);
|
|
301
|
+
ENUM_TIMEFRAMES tfNow = (ENUM_TIMEFRAMES)ChartPeriod(cid);
|
|
302
|
+
|
|
303
|
+
string symWant = symNow;
|
|
304
|
+
if(StringLen(symTxt) > 0 && StringCompare(symTxt, symNow) != 0)
|
|
305
|
+
{
|
|
306
|
+
if(SymbolSelect(symTxt, true)) symWant = symTxt;
|
|
307
|
+
}
|
|
308
|
+
if(SymbolSelect(symWant, true) == false)
|
|
309
|
+
{
|
|
310
|
+
ok = false;
|
|
311
|
+
err = "sembol bulunamadi: " + symWant;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
ENUM_TIMEFRAMES tfWant = TfFromText(tfTxt);
|
|
315
|
+
ENUM_TIMEFRAMES tfUse = (tfWant == PERIOD_CURRENT) ? tfNow : tfWant;
|
|
316
|
+
bool tempChart = false;
|
|
317
|
+
bool tplApplied = false;
|
|
318
|
+
bool themeOk = false;
|
|
319
|
+
int bgNow = -1;
|
|
320
|
+
|
|
321
|
+
if(ok && (symWant != symNow || tfUse != tfNow))
|
|
322
|
+
{
|
|
323
|
+
long newId = ChartOpen(symWant, tfUse);
|
|
324
|
+
if(newId == 0)
|
|
325
|
+
{
|
|
326
|
+
ok = false;
|
|
327
|
+
err = "gecici grafik acilamadi: " + symWant;
|
|
328
|
+
}
|
|
329
|
+
else
|
|
330
|
+
{
|
|
331
|
+
cid = newId;
|
|
332
|
+
tempChart = true;
|
|
333
|
+
/* temiz gorunum: BeastFinance.tpl temasi (EA blogu cikarilmis BeastShot.tpl) */
|
|
334
|
+
string tpl = JsonGet(raw, "template");
|
|
335
|
+
if(StringLen(tpl) == 0) tpl = "BeastShot";
|
|
336
|
+
if(StringFind(tpl, ".") < 0) tpl = tpl + ".tpl";
|
|
337
|
+
bool tplOk = false;
|
|
338
|
+
if(StringCompare(tpl, "none.tpl") != 0)
|
|
339
|
+
{
|
|
340
|
+
tplOk = ChartApplyTemplate(cid, tpl);
|
|
341
|
+
ChartRedraw(cid);
|
|
342
|
+
Sleep(700);
|
|
343
|
+
}
|
|
344
|
+
/* sablon sembol/periyot degistirdiyse geri al */
|
|
345
|
+
if(StringCompare(ChartSymbol(cid), symWant) != 0 || (ENUM_TIMEFRAMES)ChartPeriod(cid) != tfUse)
|
|
346
|
+
ChartSetSymbolPeriod(cid, symWant, tfUse);
|
|
347
|
+
/* sablon bulunamasa da gorunum ayni olsun -> acik tema renklerini zorla */
|
|
348
|
+
themeOk = ApplyLightTheme(cid);
|
|
349
|
+
bgNow = (int)ChartGetInteger(cid, CHART_COLOR_BACKGROUND);
|
|
350
|
+
tplApplied = tplOk;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
if(ok)
|
|
355
|
+
{
|
|
356
|
+
ChartRedraw(cid);
|
|
357
|
+
Sleep(1200); /* mumlar/olcek otursun */
|
|
358
|
+
ChartRedraw(cid);
|
|
359
|
+
Sleep(200);
|
|
360
|
+
if(!ChartScreenShot(cid, file, w, hh, ALIGN_RIGHT))
|
|
361
|
+
{
|
|
362
|
+
ok = false;
|
|
363
|
+
err = "screenshot basarisiz, hata=" + IntegerToString(GetLastError());
|
|
364
|
+
}
|
|
365
|
+
else
|
|
366
|
+
{
|
|
367
|
+
result = StringFormat("{\"file\":\"%s\",\"width\":%d,\"height\":%d,\"symbol\":\"%s\",\"period\":%d,\"temp_chart\":%s,\"template_applied\":%s,\"theme_ok\":%s,\"bg\":%d}",
|
|
368
|
+
JStr(file), w, hh, symWant, (int)tfUse, (tempChart ? "true" : "false"), (tplApplied ? "true" : "false"), (themeOk ? "true" : "false"), bgNow);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
if(tempChart) ChartClose(cid);
|
|
372
|
+
}
|
|
282
373
|
else
|
|
283
374
|
{
|
|
284
375
|
ok = false;
|
|
@@ -287,4 +378,50 @@ void ProcessCommands()
|
|
|
287
378
|
WriteAck(id, cmd, ok, err, result);
|
|
288
379
|
FileDelete(CmdFile);
|
|
289
380
|
}
|
|
381
|
+
|
|
382
|
+
/* BeastFinance.tpl acik tema renklerini grafige uygular (sablon bulunamazsa da garanti) */
|
|
383
|
+
bool ApplyLightTheme(const long cid)
|
|
384
|
+
{
|
|
385
|
+
bool okAll = true;
|
|
386
|
+
okAll = ChartSetInteger(cid, CHART_COLOR_BACKGROUND, (long)16449525) && okAll;
|
|
387
|
+
okAll = ChartSetInteger(cid, CHART_COLOR_FOREGROUND, (long)0) && okAll;
|
|
388
|
+
okAll = ChartSetInteger(cid, CHART_COLOR_GRID, (long)12632256) && okAll;
|
|
389
|
+
okAll = ChartSetInteger(cid, CHART_COLOR_CHART_UP, (long)13434880) && okAll;
|
|
390
|
+
okAll = ChartSetInteger(cid, CHART_COLOR_CHART_DOWN, (long)0) && okAll;
|
|
391
|
+
okAll = ChartSetInteger(cid, CHART_COLOR_CHART_LINE, (long)0) && okAll;
|
|
392
|
+
okAll = ChartSetInteger(cid, CHART_COLOR_CANDLE_BULL, (long)13434880) && okAll;
|
|
393
|
+
okAll = ChartSetInteger(cid, CHART_COLOR_CANDLE_BEAR, (long)0) && okAll;
|
|
394
|
+
okAll = ChartSetInteger(cid, CHART_COLOR_VOLUME, (long)32768) && okAll;
|
|
395
|
+
okAll = ChartSetInteger(cid, CHART_COLOR_BID, (long)12632256) && okAll;
|
|
396
|
+
okAll = ChartSetInteger(cid, CHART_COLOR_ASK, (long)12632256) && okAll;
|
|
397
|
+
okAll = ChartSetInteger(cid, CHART_COLOR_LAST, (long)12632256) && okAll;
|
|
398
|
+
okAll = ChartSetInteger(cid, CHART_COLOR_STOP_LEVEL, (long)17919) && okAll;
|
|
399
|
+
okAll = ChartSetInteger(cid, CHART_MODE, CHART_CANDLES) && okAll;
|
|
400
|
+
okAll = ChartSetInteger(cid, CHART_SHOW_GRID, false) && okAll;
|
|
401
|
+
okAll = ChartSetInteger(cid, CHART_SHOW_OHLC, true) && okAll;
|
|
402
|
+
okAll = ChartSetInteger(cid, CHART_SHOW_BID_LINE, false) && okAll;
|
|
403
|
+
okAll = ChartSetInteger(cid, CHART_SHOW_ASK_LINE, false) && okAll;
|
|
404
|
+
okAll = ChartSetInteger(cid, CHART_SHOW_LAST_LINE, true) && okAll;
|
|
405
|
+
ChartRedraw(cid);
|
|
406
|
+
return okAll;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/* "M15"/"H1"/"15"/"60" gibi metni ENUM_TIMEFRAMES'e cevirir */
|
|
410
|
+
ENUM_TIMEFRAMES TfFromText(const string t)
|
|
411
|
+
{
|
|
412
|
+
string s = t;
|
|
413
|
+
StringTrimLeft(s);
|
|
414
|
+
StringTrimRight(s);
|
|
415
|
+
StringToUpper(s);
|
|
416
|
+
if(s == "M1" || s == "1") return PERIOD_M1;
|
|
417
|
+
if(s == "M5" || s == "5") return PERIOD_M5;
|
|
418
|
+
if(s == "M15" || s == "15") return PERIOD_M15;
|
|
419
|
+
if(s == "M30" || s == "30") return PERIOD_M30;
|
|
420
|
+
if(s == "H1" || s == "60") return PERIOD_H1;
|
|
421
|
+
if(s == "H4" || s == "240") return PERIOD_H4;
|
|
422
|
+
if(s == "D1" || s == "1440") return PERIOD_D1;
|
|
423
|
+
if(s == "W1") return PERIOD_W1;
|
|
424
|
+
if(s == "MN1") return PERIOD_MN1;
|
|
425
|
+
return PERIOD_CURRENT;
|
|
426
|
+
}
|
|
290
427
|
//+------------------------------------------------------------------+
|
|
Binary file
|
package/src/agent/mt5setup.js
CHANGED
|
@@ -493,6 +493,28 @@ function runSetup({ dataPath, terminalExe = '', force = false } = {}) {
|
|
|
493
493
|
steps.push('Aktif profil grafiği bulunamadı — EA Navigator\'dan elle sürüklenebilir');
|
|
494
494
|
}
|
|
495
495
|
|
|
496
|
+
/* 4c) BeastShot.tpl: mt5_shot geçici grafik açtığında uyguladığı temiz açık-tema
|
|
497
|
+
şablonu (EA bloğu yok) — kaynaktan kopyalanır; mt5_shot varsayılanı bunu arar. */
|
|
498
|
+
try {
|
|
499
|
+
const tplSrc = path.join(__dirname, 'mt5', 'BeastShot.tpl');
|
|
500
|
+
if (fs.existsSync(tplSrc)) {
|
|
501
|
+
const tplDir2 = path.join(mql5, 'Profiles', 'Templates');
|
|
502
|
+
const tplDst = path.join(tplDir2, 'BeastShot.tpl');
|
|
503
|
+
fs.mkdirSync(tplDir2, { recursive: true });
|
|
504
|
+
let same = false;
|
|
505
|
+
try { same = fs.readFileSync(tplDst).equals(fs.readFileSync(tplSrc)); } catch {}
|
|
506
|
+
if (!same) {
|
|
507
|
+
fs.copyFileSync(tplSrc, tplDst);
|
|
508
|
+
steps.push('Grafik şablonu yazıldı: ' + tplDst);
|
|
509
|
+
result.changed = true;
|
|
510
|
+
} else {
|
|
511
|
+
steps.push('Grafik şablonu güncel: ' + tplDst);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
} catch (e) {
|
|
515
|
+
steps.push('Grafik şablonu yazılamadı: ' + String((e && e.message) || e));
|
|
516
|
+
}
|
|
517
|
+
|
|
496
518
|
const running = terminalRunning();
|
|
497
519
|
result.restartRequired = running && result.changed;
|
|
498
520
|
if (result.restartRequired) steps.push('Değişiklikler MT5 yeniden başlatılınca etkinleşir');
|
|
@@ -62,11 +62,13 @@ Yani MT5 entegrasyonu yazarken EA'yı SIFIRDAN YAZMA, elle iliştirme varsayma
|
|
|
62
62
|
| Dosya (MQL5\Files) | Yön | İçerik |
|
|
63
63
|
|---|---|---|
|
|
64
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 |
|
|
65
|
+
| `beast_cmd.json` | Beast → EA | komut: `{id, cmd, params}` — desteklenen: ping / chart / status / note / shot |
|
|
66
66
|
| `beast_cmd_ack.json` | EA → Beast | komut sonucu: `{ok, id, cmd, result|error}` |
|
|
67
67
|
| `beast_note.json` | Beast → EA | grafik panosu: `{symbol?, text, levels:[{price,label}]}` — pano + yatay çizgiler; screenshot'ta görünür |
|
|
68
68
|
|
|
69
|
-
-
|
|
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).
|
|
70
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.
|
|
71
73
|
- EA kaynağı Beast uygulamasında `src/agent/mt5/BeastFinance.mq5`; güncelleme oradan yapılır, setup yeniden derler.
|
|
72
74
|
- Derleme hatalarında dosya kodlaması UTF-16 (`FILE_UNICODE`) kullanılır; MQL5'te `FILE_UTF8` yoktur.
|
package/src/main.js
CHANGED
|
@@ -3634,7 +3634,7 @@ app.whenReady().then(() => {
|
|
|
3634
3634
|
reloadBackend();
|
|
3635
3635
|
syncWhitelist(); // bot sistemi: whitelist.json aynası ilk açılışta garanti
|
|
3636
3636
|
try { bots.ensureBotCodes(); } catch {} // her bota benzersiz 5 haneli kod garanti
|
|
3637
|
-
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
|
|
3638
3638
|
createSplash();
|
|
3639
3639
|
createWindow();
|
|
3640
3640
|
log.info('main', 'Beast Agent başlatıldı');
|
package/src/renderer/renderer.js
CHANGED
|
@@ -5253,9 +5253,17 @@ function dmMsgHtml(m) {
|
|
|
5253
5253
|
const who = m.group
|
|
5254
5254
|
? dmName(m.fromTitle, m.from)
|
|
5255
5255
|
: `${dmName(m.fromTitle, m.from)} → ${dmName(m.toTitle, m.to)}`;
|
|
5256
|
+
const rawImg = String(m.image || '');
|
|
5257
|
+
const img = /^data:image\//i.test(rawImg)
|
|
5258
|
+
? `<img class="dmt-img" src="${escapeHtml(rawImg)}" alt="görsel" loading="lazy">`
|
|
5259
|
+
: m.imageOmitted
|
|
5260
|
+
? '<div class="dmt-img-note">görsel (bütçe) kaydedilmedi</div>'
|
|
5261
|
+
: '';
|
|
5256
5262
|
return (
|
|
5257
5263
|
`<div class="dmt-msg"><span class="dm-who">${who}</span>` +
|
|
5258
|
-
`${escapeHtml(String(m.text || ''))}
|
|
5264
|
+
`${escapeHtml(String(m.text || ''))}` +
|
|
5265
|
+
img +
|
|
5266
|
+
`<span class="dm-at">${dmTime(m.at)}</span></div>`
|
|
5259
5267
|
);
|
|
5260
5268
|
}
|
|
5261
5269
|
|
|
@@ -5788,6 +5796,8 @@ function onEvent(ev) {
|
|
|
5788
5796
|
toTitle: ev.toTitle,
|
|
5789
5797
|
topic: ev.topic,
|
|
5790
5798
|
text: ev.text,
|
|
5799
|
+
...(ev.image ? { image: ev.image } : {}),
|
|
5800
|
+
...(ev.imageOmitted ? { imageOmitted: true } : {}),
|
|
5791
5801
|
...(ev.group ? { group: ev.group, groupTitle: ev.groupTitle } : {}),
|
|
5792
5802
|
...(ev.closed ? { closed: true, closedAt: ev.closedAt } : {}),
|
|
5793
5803
|
};
|
package/src/renderer/style.css
CHANGED
|
@@ -2224,6 +2224,21 @@ body.browser-open #settingsDialog { width: min(70vw, calc(100vw - var(--bw, 480p
|
|
|
2224
2224
|
color: var(--muted);
|
|
2225
2225
|
margin-top: 2px;
|
|
2226
2226
|
}
|
|
2227
|
+
/* ajan DM görseli (mt5_shot / ekran görüntüsü paylaşımı) */
|
|
2228
|
+
.dmt-msg .dmt-img {
|
|
2229
|
+
display: block;
|
|
2230
|
+
max-width: 100%;
|
|
2231
|
+
max-height: 260px;
|
|
2232
|
+
border-radius: 6px;
|
|
2233
|
+
margin-top: 5px;
|
|
2234
|
+
border: 1px solid var(--border, rgba(255,255,255,0.12));
|
|
2235
|
+
}
|
|
2236
|
+
.dmt-msg .dmt-img-note {
|
|
2237
|
+
font-size: 10px;
|
|
2238
|
+
color: var(--muted);
|
|
2239
|
+
font-style: italic;
|
|
2240
|
+
margin-top: 3px;
|
|
2241
|
+
}
|
|
2227
2242
|
/* ajan adının yanındaki KOD rozeti (oturum id) */
|
|
2228
2243
|
.dm-code {
|
|
2229
2244
|
font-size: 9px; font-weight: 700; letter-spacing: 0.5px;
|