beast-agent 2.39.0 → 2.41.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 +101 -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/opencode/agents.js +4 -3
- package/src/agent/seeds/mql5/SKILL.md +4 -2
- package/src/agent/tools.js +16 -0
- package/src/main.js +307 -39
- package/src/preload.js +6 -1
- package/src/renderer/index.html +6 -4
- package/src/renderer/renderer.js +115 -39
- package/src/renderer/style.css +27 -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
|
|
@@ -2102,6 +2106,7 @@ class Engine {
|
|
|
2102
2106
|
? 'Bağımsız alt-işleri run_background ile PARALEL ajana devret; işi KENDİN YÜRÜTME — emri ver, takip et, raporla.'
|
|
2103
2107
|
: 'Bağımsız alt-işleri delegate_task ile devret; kendi başına halledebileceğin işleri devretme.',
|
|
2104
2108
|
'Güncel/dış bilgi gerekiyorsa web_search kullan (zincir DAHİLİ tarayıcıyla başlar — gerçek Chromium ile Google); hızlı ham metin okuması için webfetch (veya http_fetch) kullan.',
|
|
2109
|
+
'KULLANICI GITHUB REPO ADRESİ/LİNKİ VERİRSE (github.com/owner/repo) ya da "şu repoyu indir/kur/çalıştır" derse sandbox_repo aracını kullan: action=indir → Beast Sandbox\'a (~/Beast-Sandbox) klonlar; ardından action=kur (bağımlılıklar) ve action=baslat (çalıştır) ile devam et — uzun sürse bile tur KİLİTLENMEZ, çıktı Sandbox ÇALIŞTIR panelinde canlı akar, localhost adresi sağdaki dahili tarayıcıda otomatik açılır. Sonucu kullanıcıya tek cümleyle bildir (repo, komut, çalışıyor mu).',
|
|
2105
2110
|
'DERİN ARAŞTIRMA: web_search\u2019in sonucu yetersizse/istenen bilgi listede YOKSA aramayı tekrar tekrar deneme yerine deep_search kullan — 1-4 sorgu varyantını (eş anlamlı, Türkçe+İngilizce yazımlar) PARALEL aratır ve ilk sayfaları GİZLİ gerçek Chromium\u2019da açıp tam metin okur (paneli açmaz, kullanıcıyı rahatsız etmez; JS/SPA sayfalar çalışır). Fiyat karşılaştırma, çok kaynaklı araştırma, "her şeyi bul" işleri ve Türkçe sorgularda sonuç zayıfsa doğrudan deep_search seç. read_top=0 verirsen yalnız harmanlanmış sonuç listesi döner.',
|
|
2106
2111
|
'ARAMA-DİSİPLİN: bir bilgiyi 2-3 denemede bulamazsan TAKILMA — farklı bir açıya/sorguya geç, yine yoksa bulabildiğin kısmi bilgiyle cevap ver ve neyi bulamadığını açıkça söyle. Kapalı/gizli içerik (private profil, login arkası veri) peşinde KOŞMA — bulunamayacağı belliyse hemen vazgeç.',
|
|
2107
2112
|
'TARAYICI VARSAYILANI (ZORUNLU): kullanıcı "şu siteyi aç", "bunu ara / google\u2019da ara", "şu sayfaya git" gibi bir web isteği verdiğinde HEP DAHİLİ TARAYICIYI KULLAN (browser_open ile aç → açılış yanıtında hazır snapshot gelir → ref numaralarıyla browser_click/browser_type/browser_select ile hareket et; HER eylem yanıtında taze snapshot döner — ayrıca browser_snapshot çağırma, yanıttaki refleri kullan; browser_read ile metin oku; sadece görsel yerleşim/grafik gerekiyorsa browser_screenshot çek). Tarih/saat alanlarını (type=date/time) browser_type ile DÜZ METİN yaz ("15.03.2026", "2026-03-15") — takvimden tıklamaya çalışma, alan programatik ayarlanır. Panel ekranın sağında açılır ve kullanıcı da sayfayı anında görür; JS/login/SPA/dinamik içerik için idealdir. Bu kural TÜM oturumları kapsar — masaüstü sohbeti ve çok kullanıcılı botlar (WhatsApp vb.) dahil.' +
|
|
@@ -4324,7 +4329,7 @@ class Engine {
|
|
|
4324
4329
|
const imgMsg = {
|
|
4325
4330
|
role: 'user',
|
|
4326
4331
|
content: [
|
|
4327
|
-
{ type: 'text', text: '[
|
|
4332
|
+
{ type: 'text', text: '[araç görseli — bu kareyi analiz et ve devam et]' },
|
|
4328
4333
|
{ type: 'image_url', image_url: { url: injectedImage } },
|
|
4329
4334
|
],
|
|
4330
4335
|
};
|
|
@@ -5006,6 +5011,51 @@ const skills = require('./skills');
|
|
|
5006
5011
|
return { ...r, via };
|
|
5007
5012
|
}
|
|
5008
5013
|
|
|
5014
|
+
/* Sandbox köprüsü (main.js hook'ları): ana sohbetteki ajan sandbox_repo
|
|
5015
|
+
aracıyla repo indirir/kurar/çalıştırır — Sandbox paneliyle AYNI makine.
|
|
5016
|
+
Kur/Başlat yönetilen süreçtir: tur kilitlenmez, çıktı panelde akar,
|
|
5017
|
+
localhost adresi sağdaki dahili tarayıcıda açılır. */
|
|
5018
|
+
async _sandboxRepo(args) {
|
|
5019
|
+
const action = String((args && args.action) || '').trim().toLowerCase();
|
|
5020
|
+
const repo = String((args && args.repo) || '').trim();
|
|
5021
|
+
if (action === 'indir') {
|
|
5022
|
+
if (typeof this.sbCloneHook !== 'function') return { ok: false, error: 'sandbox köprüsü yok' };
|
|
5023
|
+
const r = await this.sbCloneHook(repo);
|
|
5024
|
+
if (!r || !r.ok) return r || { ok: false, error: 'klonlanamadı' };
|
|
5025
|
+
let info = null;
|
|
5026
|
+
try { if (typeof this.sbDetectHook === 'function') info = this.sbDetectHook(r.folder); } catch {}
|
|
5027
|
+
return {
|
|
5028
|
+
ok: true,
|
|
5029
|
+
name: r.name,
|
|
5030
|
+
folder: r.folder,
|
|
5031
|
+
detected: info ? { kind: info.kind, label: info.label, install: info.install, run: info.run } : undefined,
|
|
5032
|
+
note:
|
|
5033
|
+
'Repo "' + r.name + '" → ' + r.folder + ' klasörüne indirildi. Kurmak için sandbox_repo action=kur, çalıştırmak için action=baslat; kullanıcı Sandbox panelindeki Kur/Başlat butonlarını da kullanabilir.',
|
|
5034
|
+
};
|
|
5035
|
+
}
|
|
5036
|
+
if (action !== 'kur' && action !== 'baslat' && action !== 'durdur') {
|
|
5037
|
+
return { ok: false, error: 'action şunlardan biri olmalı: indir | kur | baslat | durdur' };
|
|
5038
|
+
}
|
|
5039
|
+
let folder = '';
|
|
5040
|
+
try { if (typeof this.sbFolderHook === 'function') folder = String(this.sbFolderHook(repo) || ''); } catch {}
|
|
5041
|
+
if (!folder) return { ok: false, error: 'repo bulunamadı — önce sandbox_repo action=indir ile indir ya da Sandbox panelinden bir repo seç' };
|
|
5042
|
+
if (action === 'kur') {
|
|
5043
|
+
if (typeof this.sbInstallHook !== 'function') return { ok: false, error: 'sandbox köprüsü yok' };
|
|
5044
|
+
const r = this.sbInstallHook(folder);
|
|
5045
|
+
if (!r || !r.ok) return r || { ok: false, error: 'kurulum başlatılamadı' };
|
|
5046
|
+
return { ok: true, folder, command: r.cmd, note: 'Kurulum ÇALIŞTIR panelinde başladı: ' + r.cmd + ' — çıktı panelde canlı akar; bitince kullanıcıya bildir, sonra action=baslat.' };
|
|
5047
|
+
}
|
|
5048
|
+
if (action === 'baslat') {
|
|
5049
|
+
if (typeof this.sbStartHook !== 'function') return { ok: false, error: 'sandbox köprüsü yok' };
|
|
5050
|
+
const r = this.sbStartHook(folder, 'run');
|
|
5051
|
+
if (!r || !r.ok) return r || { ok: false, error: 'başlatılamadı' };
|
|
5052
|
+
return { ok: true, folder, command: r.cmd, note: 'Süreç ÇALIŞTIR panelinde başladı: ' + r.cmd + '. Dev server adresi yakalanınca sağdaki dahili tarayıcıda otomatik açılır; durdurmak için action=durdur.' };
|
|
5053
|
+
}
|
|
5054
|
+
if (typeof this.sbStopHook !== 'function') return { ok: false, error: 'sandbox köprüsü yok' };
|
|
5055
|
+
const stopped = !!this.sbStopHook(folder);
|
|
5056
|
+
return { ok: true, folder, wasRunning: stopped, note: stopped ? 'Süreç durduruldu.' : 'Bu repoda çalışan bir süreç yoktu.' };
|
|
5057
|
+
}
|
|
5058
|
+
|
|
5009
5059
|
async _subExecTool(name, args, signal) {
|
|
5010
5060
|
try {
|
|
5011
5061
|
const blocked = this._guardTool(name, args);
|
|
@@ -5020,6 +5070,7 @@ const skills = require('./skills');
|
|
|
5020
5070
|
});
|
|
5021
5071
|
}
|
|
5022
5072
|
if (name === 'ocr_read') return JSON.stringify(await this._ocrRead(args || {}, signal));
|
|
5073
|
+
if (name === 'sandbox_repo') return JSON.stringify(await this._sandboxRepo(args || {}));
|
|
5023
5074
|
/* opencode general-agent portu: alt-ajan da edit/grep/glob kullanır.
|
|
5024
5075
|
MT5 (mt5_*) araçları da tools.exec'e geçer (finance işçileri/danışma). */
|
|
5025
5076
|
if (!(name === 'run_command' || name === 'read_file' || name === 'write_file' || name === 'edit_file' ||
|
|
@@ -5561,6 +5612,9 @@ const skills = require('./skills');
|
|
|
5561
5612
|
const n = Number((args && args.max_results) || 8);
|
|
5562
5613
|
return JSON.stringify(await this._webSearchChain(q, n, sessionId, signal));
|
|
5563
5614
|
}
|
|
5615
|
+
if (name === 'sandbox_repo') {
|
|
5616
|
+
return JSON.stringify(await this._sandboxRepo(args || {}));
|
|
5617
|
+
}
|
|
5564
5618
|
if (name === 'ocr_read') {
|
|
5565
5619
|
return JSON.stringify(await this._ocrRead(args || {}, signal, sessionId));
|
|
5566
5620
|
}
|
|
@@ -5723,7 +5777,7 @@ const AGENT_DM_DEF = {
|
|
|
5723
5777
|
function: {
|
|
5724
5778
|
name: 'agent_dm',
|
|
5725
5779
|
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
|
|
5780
|
+
'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
5781
|
parameters: {
|
|
5728
5782
|
type: 'object',
|
|
5729
5783
|
properties: {
|
|
@@ -5731,7 +5785,7 @@ const AGENT_DM_DEF = {
|
|
|
5731
5785
|
topic: { type: 'string', description: 'Short subject label for the conversation thread, e.g. "GOLD pozisyon riski"' },
|
|
5732
5786
|
message: { type: 'string', description: 'Short message (1-3 sentences)' },
|
|
5733
5787
|
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
|
|
5788
|
+
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
5789
|
},
|
|
5736
5790
|
required: ['message'],
|
|
5737
5791
|
},
|
|
@@ -6547,9 +6601,17 @@ Engine.prototype._agentDmSend = async function (fromSid, args) {
|
|
|
6547
6601
|
const to = String((args && args.to) || '').trim();
|
|
6548
6602
|
const text = String((args && args.message) || '').trim().slice(0, 1200);
|
|
6549
6603
|
if (!text) return { ok: false, error: 'mesaj boş' };
|
|
6550
|
-
/* GÖRSEL DM: son ekran görüntüsü (yoksa taze yakalama)
|
|
6551
|
-
|
|
6552
|
-
|
|
6604
|
+
/* GÖRSEL DM: image:true → son ekran görüntüsü (yoksa taze yakalama);
|
|
6605
|
+
image:"<dosya yolu>" ya da data URL → o görsel BİREBİR iliştirilir
|
|
6606
|
+
(ör. tool__mt5_shot dönen PNG path'i). Karşı ajan görüntüyü görür. */
|
|
6607
|
+
const imgArg = args && args.image;
|
|
6608
|
+
let image = '';
|
|
6609
|
+
if (typeof imgArg === 'string' && imgArg.trim()) {
|
|
6610
|
+
const s = imgArg.trim();
|
|
6611
|
+
image = /^data:image\//i.test(s) ? s : this._agentDmImageFromFile(s);
|
|
6612
|
+
} else if (imgArg === true || imgArg === 'true') {
|
|
6613
|
+
image = await this._agentDmCaptureImage(fromSid);
|
|
6614
|
+
}
|
|
6553
6615
|
const groupName = String((args && args.group) || '').replace(/\s+/g, ' ').trim().slice(0, 40);
|
|
6554
6616
|
const jobs = this._bgJobs || new Map();
|
|
6555
6617
|
const fromJob = jobs.get(String(fromSid));
|
|
@@ -6722,6 +6784,29 @@ Engine.prototype._agentDmSend = async function (fromSid, args) {
|
|
|
6722
6784
|
}
|
|
6723
6785
|
};
|
|
6724
6786
|
|
|
6787
|
+
/* AJAN DM görseli (dosyadan): png/jpg/webp/gif dosyasını data URL'e çevirir.
|
|
6788
|
+
Send_file kapısına takılmadan (ör. tool__mt5_shot path'i) görsel paylaşımı;
|
|
6789
|
+
2.5MB üstü DM kaydını şişirmesin diye atlanır. */
|
|
6790
|
+
Engine.prototype._agentDmImageFromFile = function (p) {
|
|
6791
|
+
try {
|
|
6792
|
+
const fp = String(p || '').trim();
|
|
6793
|
+
if (!fp) return '';
|
|
6794
|
+
const ext = path.extname(fp).toLowerCase();
|
|
6795
|
+
const mime =
|
|
6796
|
+
ext === '.png' ? 'image/png'
|
|
6797
|
+
: ext === '.jpg' || ext === '.jpeg' ? 'image/jpeg'
|
|
6798
|
+
: ext === '.webp' ? 'image/webp'
|
|
6799
|
+
: ext === '.gif' ? 'image/gif'
|
|
6800
|
+
: '';
|
|
6801
|
+
if (!mime) return '';
|
|
6802
|
+
const buf = fs.readFileSync(fp);
|
|
6803
|
+
if (!buf.length || buf.length > 2500000) return '';
|
|
6804
|
+
return 'data:' + mime + ';base64,' + buf.toString('base64');
|
|
6805
|
+
} catch {
|
|
6806
|
+
return '';
|
|
6807
|
+
}
|
|
6808
|
+
};
|
|
6809
|
+
|
|
6725
6810
|
/* AJAN DM görseli: gönderenin oturumundaki EN SON ekran görüntüsünü (yoksa
|
|
6726
6811
|
taze yakalama) data URL olarak döndürür. Çok büyük görseller DM kaydını
|
|
6727
6812
|
ş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');
|
|
@@ -130,9 +130,10 @@ function build(opts = {}) {
|
|
|
130
130
|
user
|
|
131
131
|
),
|
|
132
132
|
prompt: [
|
|
133
|
-
'BEAST SANDBOX MODUNDASIN: GitHub\u2019dan indirilmi\u015f A\u00c7IK KAYNAK bir repo klas\u00f6r\u00fcndesin (Beast-Sandbox). Bu kodun sahibi de\u011filsin \u2014
|
|
134
|
-
'\
|
|
135
|
-
'
|
|
133
|
+
'BEAST SANDBOX MODUNDASIN: GitHub\u2019dan indirilmi\u015f A\u00c7IK KAYNAK bir repo klas\u00f6r\u00fcndesin (Beast-Sandbox). Bu kodun sahibi de\u011filsin \u2014 haz\u0131r bir d\u0131\u015f proje; repo sahibinin konvansiyonlar\u0131na uy, gereksiz yeniden bi\u00e7imlendirme yapma.',
|
|
134
|
+
'PANEL: \u00c7ALI\u015eTIR b\u00f6l\u00fcm\u00fcndeki Kur/Ba\u015flat/Dev butonlar\u0131 proje tipini OTOMAT\u0130K alg\u0131lar (package.json scripts + npm/pnpm/yarn/bun kilidi; requirements.txt/pyproject + uv; Cargo.toml; go.mod; statik index.html) ve do\u011fru komutu do\u011frudan \u00e7al\u0131\u015ft\u0131r\u0131r. \u00d6zel komut kutusu ad-hoc komut \u00e7al\u0131\u015ft\u0131r\u0131r; kaydet butonu o komutu repo i\u00e7in kal\u0131c\u0131 ba\u015flatma komutu yapar. Kullan\u0131c\u0131 butonla ba\u015flatt\u0131ysa \u00e7\u0131kt\u0131 panelde canl\u0131 akar, localhost adresi yakalan\u0131nca sa\u011fdaki dahili taray\u0131c\u0131da otomatik a\u00e7\u0131l\u0131r.',
|
|
135
|
+
'\u0130\u015fe README + paket bildirim dosyalar\u0131yla ba\u015fla (list/glob); kullan\u0131c\u0131 Kur demediyse ba\u011f\u0131ml\u0131l\u0131klar\u0131 sen kurabilirsin (npm install, pip install -r requirements.txt vb.). Kur/Ba\u015flat ba\u015far\u0131s\u0131z olursa ger\u00e7ek hatay\u0131 g\u00f6rmek i\u00e7in ayn\u0131 komutu bash ile \u00e7al\u0131\u015ft\u0131r, nedenini bul, gerekiyorsa d\u00fczelt ve kullan\u0131c\u0131ya do\u011fru \u00f6zel komutu s\u00f6yle (kutuya yaz\u0131p kaydetsin).',
|
|
136
|
+
'UZUN S\u00dcREL\u0130 sunucu/s\u00fcre\u00e7 (npm start, npm run dev, python app.py vb.) bash ile ASLA ba\u015flatma \u2014 tur kilitlenir; kullan\u0131c\u0131 senden isterse panel_run ile ba\u015flat (\u00e7\u0131kt\u0131 panelde akar, adres sa\u011fda a\u00e7\u0131l\u0131r). Repo ba\u015f\u0131na TEK s\u00fcre\u00e7: kullan\u0131c\u0131 zaten ba\u015flatt\u0131ysa panel_run hata verir \u2014 kullan\u0131c\u0131ya \u00f6nce Durdur demesini s\u00f6yle.',
|
|
136
137
|
].join('\n'),
|
|
137
138
|
mode: 'all',
|
|
138
139
|
native: false,
|
|
@@ -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/agent/tools.js
CHANGED
|
@@ -1613,6 +1613,22 @@ const definitions = [
|
|
|
1613
1613
|
},
|
|
1614
1614
|
},
|
|
1615
1615
|
},
|
|
1616
|
+
{
|
|
1617
|
+
type: 'function',
|
|
1618
|
+
function: {
|
|
1619
|
+
name: 'sandbox_repo',
|
|
1620
|
+
description:
|
|
1621
|
+
'Beast Sandbox yönetimi — kullanıcı GitHub repo adresi/linki verdiğinde ya da indirilmiş bir repoyu kurmak/çalıştırmak istediğinde kullan. action=indir: repoyu ~/Beast-Sandbox klasörüne klonlar (owner/repo ya da tam URL); action=kur: algılanan kurulum komutunu (npm install, pip install -r requirements.txt, uv sync, cargo fetch, go mod download) ÇALIŞTIR panelinde başlatır; action=baslat: algılanan çalıştırma komutunu başlatır (npm run dev, python app.py vb.) — localhost adresi yakalanınca sağdaki dahili tarayıcıda otomatik açılır; action=durdur: repodaki çalışan süreci durdurur. Kur/Başlat turu KİLİTLEMEZ, çıktı panelde canlı akar. repo alanı boşsa panelde son kullanılan repo kullanılır.',
|
|
1622
|
+
parameters: {
|
|
1623
|
+
type: 'object',
|
|
1624
|
+
properties: {
|
|
1625
|
+
action: { type: 'string', enum: ['indir', 'kur', 'baslat', 'durdur'], description: 'Yapılacak işlem' },
|
|
1626
|
+
repo: { type: 'string', description: 'GitHub adresi (owner/repo ya da tam URL) ya da repo adı/klasör yolu; son kullanılan repo için boş bırak' },
|
|
1627
|
+
},
|
|
1628
|
+
required: ['action'],
|
|
1629
|
+
},
|
|
1630
|
+
},
|
|
1631
|
+
},
|
|
1616
1632
|
{
|
|
1617
1633
|
type: 'function',
|
|
1618
1634
|
function: {
|