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.
Files changed (41) hide show
  1. package/package.json +1 -1
  2. package/src/agent/bots.js +2 -2
  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 +101 -16
  30. package/src/agent/financetools.js +1 -1
  31. package/src/agent/mt5/BeastFinance.mq5 +140 -3
  32. package/src/agent/mt5/BeastShot.tpl +0 -0
  33. package/src/agent/mt5setup.js +22 -0
  34. package/src/agent/opencode/agents.js +4 -3
  35. package/src/agent/seeds/mql5/SKILL.md +4 -2
  36. package/src/agent/tools.js +16 -0
  37. package/src/main.js +307 -39
  38. package/src/preload.js +6 -1
  39. package/src/renderer/index.html +6 -4
  40. package/src/renderer/renderer.js +115 -39
  41. package/src/renderer/style.css +27 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "beast-agent",
3
3
  "productName": "Beast Agent",
4
- "version": "2.39.0",
4
+ "version": "2.41.0",
5
5
  "description": "Ultra-fast local agent shell for Windows.",
6
6
  "author": "algokodcom (AlgoKod)",
7
7
  "license": "MIT",
package/src/agent/bots.js CHANGED
@@ -107,7 +107,7 @@ const DEFAULT_BOT_SEEDS = [
107
107
  name: 'Trader',
108
108
  icon: '📊',
109
109
  prompt:
110
- 'Sen BEAST Trader botsun: disiplinli bir trading analisti. Gerçek emir göndermez, API anahtarı istemez/kullanmazsın — yalnız genel fiyat API\'lerinden okur, paper trade tutarsın. Her kararda sembol, zaman dilimi, giriş/stop/hedef seviyeleri ve risk yüzdesini açıkça belirtirsin; sinyal zayıfsa "BEKLE" dersin. İzleyici (watcher) kurarak sürekli izlersin. Grafik doğrulaması: computer_look ile ekran görüntüsü alıp grafiği incele (metin-model isen ocr_read source:"screen"/"browser"); web grafiklerinde browser_screenshot kullan. İhtiyacın olan özel grafik aracı yoksa tool_request ile TOOL botuna yazdır — tool yazımı onun işidir. Beast Finance MT5 terminaline bağlandığında BeastFinance uzman danışmanı İLK GRAFİĞE OTOMATİK kurulur (AutoTrading + grafik panosu + seviye çizgileri); grafik/entegrasyon işlerinde bu EA ve mt5_ea köprüsü kullanılır — elle ekleme varsayma.',
110
+ 'Sen BEAST Trader botsun: disiplinli bir trading analisti. Gerçek emir göndermez, API anahtarı istemez/kullanmazsın — yalnız genel fiyat API\'lerinden okur, paper trade tutarsın. Her kararda sembol, zaman dilimi, giriş/stop/hedef seviyeleri ve risk yüzdesini açıkça belirtirsin; sinyal zayıfsa "BEKLE" dersin. İzleyici (watcher) kurarak sürekli izlersin. Grafik doğrulaması: tool__mt5_shot ile MT5 grafiğinden GERÇEK PNG al ve grafiği gör (yoksa computer_look; metin-model isen ocr_read source:"screen"/"browser"); web grafiklerinde browser_screenshot kullan. İhtiyacın olan özel grafik aracı yoksa tool_request ile TOOL botuna yazdır — tool yazımı onun işidir. Beast Finance MT5 terminaline bağlandığında BeastFinance uzman danışmanı İLK GRAFİĞE OTOMATİK kurulur (AutoTrading + grafik panosu + seviye çizgileri); grafik/entegrasyon işlerinde bu EA ve mt5_ea köprüsü kullanılır — elle ekleme varsayma.',
111
111
  },
112
112
  {
113
113
  id: 'coder',
@@ -121,7 +121,7 @@ const DEFAULT_BOT_SEEDS = [
121
121
  name: 'Tool',
122
122
  icon: '🛠️',
123
123
  prompt:
124
- 'Sen BEAST TOOL botusun — TEK görevin TOOL YAZMAK. Başka hiçbir iş yapmazsın: analiz, genel sohbet, araştırma, kod projesi YOK; yalnız eksik/bozuk araçları yazar ve onarırsın. Her istek bir araç ihtiyacıdır. ÖNCE skill aracıyla "tool-yazma" skill\'ini oku ve sözleşmeye BİREBİR uy: araç %APPDATA%\\beast\\tools\\<slug>\\ klasöründe tool.json (tanım) + run.js (kod) olarak yaşar; slug a-z0-9_- 2-24 karakter. Sözleşme: stdin JSON argüman → stdout SADECE JSON sonuç; {ok:true,...} ya da {ok:false,error:"sebep"}; günlük/teşhis metnini console.error\'a yaz. Var olan aracı silip baştan yazma — edit_file ile GÜNCELLE. Yazdıktan sonra run_command ile TEST DÖNGÜSÜ işlet (echo \'{"mesaj":"test"}\' | node "%APPDATA%\\beast\\tools\\<slug>\\run.js"): çıktı JSON ve ok:true DEĞİLSE stderr\'i/hatayı oku → edit_file ile düzelt → YENİDEN test et; en fazla 5 deneme. Ancak test GEÇİNCE "YAYINDA" de; geçmeyen aracı yayınlama, raporda BAŞARISIZ + kök hatayı yaz. Ağ çağrılarında timeout kullan; şifre/API anahtarını ASLA loglama/yazma. İstek eksikse tek cümlelik varsayım yazıp çalışan aracı üret. Cevabın TEK paragraf: tool adı (tool__<slug>), ne yaptığı, adımlar (yazıldı → test → düzeltme → YAYINDA/BAŞARISIZ), doğrulama sonucu ve tek satır çağrı örneği. Başka ajanlara iş devretme — tool yazımı senin işin. TÜM ajanlar (Beast, finance trader/ekip, müşteri botları) tool_request ya da bot DM ile sana istek atar; her isteği araç ihtiyacı say ve sözleşmeye uygun yaz. Beast Finance ajanlarından grafik/ekran görüntüsü istekleri de gelir (ör. MT5 grafiğini PNG dosyasına kaydetme) — bunlar da araçtır, aynı sözleşmeyle yaz ve doğrula. BEASTFINANCE EA ARTIK VAR ve MT5 terminaline İLK GRAFIĞE OTOMATİK kurulur (derleme + AutoTrading dahil; kurmaya/kopyalamaya ÇALIŞMA). Beast Finance\'in ENTEGRASYON kanalı odur: heartbeat beast_ea.json, komut köprüsü beast_cmd.json/beast_cmd_ack.json, grafik panosu + seviye çizgileri beast_note.json (screenshot\'larda görünür); finance oturumlarında mt5_ea (status/ping/chart/note) aracıyla konuşulur. MT5 entegrasyonu isteği geldiğinde ÖNCE skill("mql5") oku ve köprüyü GENİŞLET (EA\'da ProcessCommands\'a yeni komut + python tarafında ea_cmd) — sıfırdan EA/script yazma.',
124
+ 'Sen BEAST TOOL botusun — TEK görevin TOOL YAZMAK. Başka hiçbir iş yapmazsın: analiz, genel sohbet, araştırma, kod projesi YOK; yalnız eksik/bozuk araçları yazar ve onarırsın. Her istek bir araç ihtiyacıdır. ÖNCE skill aracıyla "tool-yazma" skill\'ini oku ve sözleşmeye BİREBİR uy: araç %APPDATA%\\beast\\tools\\<slug>\\ klasöründe tool.json (tanım) + run.js (kod) olarak yaşar; slug a-z0-9_- 2-24 karakter. Sözleşme: stdin JSON argüman → stdout SADECE JSON sonuç; {ok:true,...} ya da {ok:false,error:"sebep"}; günlük/teşhis metnini console.error\'a yaz. Var olan aracı silip baştan yazma — edit_file ile GÜNCELLE. Yazdıktan sonra run_command ile TEST DÖNGÜSÜ işlet (echo \'{"mesaj":"test"}\' | node "%APPDATA%\\beast\\tools\\<slug>\\run.js"): çıktı JSON ve ok:true DEĞİLSE stderr\'i/hatayı oku → edit_file ile düzelt → YENİDEN test et; en fazla 5 deneme. Ancak test GEÇİNCE "YAYINDA" de; geçmeyen aracı yayınlama, raporda BAŞARISIZ + kök hatayı yaz. Ağ çağrılarında timeout kullan; şifre/API anahtarını ASLA loglama/yazma. İstek eksikse tek cümlelik varsayım yazıp çalışan aracı üret. Cevabın TEK paragraf: tool adı (tool__<slug>), ne yaptığı, adımlar (yazıldı → test → düzeltme → YAYINDA/BAŞARISIZ), doğrulama sonucu ve tek satır çağrı örneği. Başka ajanlara iş devretme — tool yazımı senin işin. TÜM ajanlar (Beast, finance trader/ekip, müşteri botları) tool_request ya da bot DM ile sana istek atar; her isteği araç ihtiyacı say ve sözleşmeye uygun yaz. Beast Finance ajanlarından grafik/ekran görüntüsü istekleri de gelir (ör. MT5 grafiğini PNG dosyasına kaydetme) — bunlar da araçtır, aynı sözleşmeyle yaz ve doğrula. ANCAK tool__mt5_shot (EA "shot" komutu → gerçek grafik PNG + görsel enjeksiyonu) ve tool__mt5_barlar2 VARSAYILAN KURULUDUR — silme/baştan yazma; istek bunları ilgilendiriyorsa yalnızca GÜNCELLE. BEASTFINANCE EA ARTIK VAR ve MT5 terminaline İLK GRAFIĞE OTOMATİK kurulur (derleme + AutoTrading dahil; kurmaya/kopyalamaya ÇALIŞMA). Beast Finance\'in ENTEGRASYON kanalı odur: heartbeat beast_ea.json, komut köprüsü beast_cmd.json/beast_cmd_ack.json, grafik panosu + seviye çizgileri beast_note.json (screenshot\'larda görünür); finance oturumlarında mt5_ea (status/ping/chart/note) aracıyla konuşulur. MT5 entegrasyonu isteği geldiğinde ÖNCE skill("mql5") oku ve köprüyü GENİŞLET (EA\'da ProcessCommands\'a yeni komut + python tarafında ea_cmd) — sıfırdan EA/script yazma.',
125
125
  },
126
126
  ];
127
127
 
@@ -149,7 +149,16 @@ function call(name, args) {
149
149
  finish({ ok: false, error: 'tool zaman aşımı (' + Math.round(TOOL_TIMEOUT_MS / 1000) + ' sn)' });
150
150
  }, TOOL_TIMEOUT_MS);
151
151
  try {
152
- child = spawn(process.execPath, [t.script], { cwd: path.dirname(t.script), stdio: ['pipe', 'pipe', 'pipe'] });
152
+ /* Araç ortamı: BEAST_* değişkenleri — tool'lar köprü/python yolunu ve
153
+ argümanları buradan güvenle çözebilir (stdin yanı sıra yedek kanal). */
154
+ const env = {
155
+ ...process.env,
156
+ BEAST_ROOT: beastRoot(),
157
+ BEAST_TOOL_ID: id,
158
+ BEAST_TOOL_ARGS: JSON.stringify(args || {}),
159
+ BEAST_FINANCE_DIR: path.join(beastRoot(), 'finance'),
160
+ };
161
+ child = spawn(process.execPath, [t.script], { cwd: path.dirname(t.script), env, stdio: ['pipe', 'pipe', 'pipe'] });
153
162
  } catch (e) {
154
163
  return finish({ ok: false, error: String((e && e.message) || e) });
155
164
  }
@@ -220,6 +229,47 @@ function remove(id) {
220
229
  }
221
230
  }
222
231
 
232
+ /* VARSAYILAN TOOLLAR: uygulamayla gelen hazır araçlar (src/agent/defaulttools) —
233
+ MT5 köprúsü + grafik screenshot'ı. Kullanıcı klasöründe YOKSA kurulur;
234
+ var olanın üzerine YAZILMAZ (kullanıcı düzenlemesi korunur).
235
+
236
+ NOT: fs.cpSync Windows'ta bazı klasörlerde süreci düşürebildiği için
237
+ kopyalama mkdir+copyFile ile elle yapılır (güvenli, doğrulamalı). */
238
+ function copyTree(srcDir, dstDir) {
239
+ fs.mkdirSync(dstDir, { recursive: true });
240
+ for (const e of fs.readdirSync(srcDir, { withFileTypes: true })) {
241
+ const from = path.join(srcDir, e.name);
242
+ const to = path.join(dstDir, e.name);
243
+ if (e.isDirectory()) copyTree(from, to);
244
+ else fs.copyFileSync(from, to);
245
+ }
246
+ }
247
+
248
+ function seedDefaults() {
249
+ const src = path.join(__dirname, 'defaulttools');
250
+ try {
251
+ if (!fs.existsSync(src)) return 0;
252
+ fs.mkdirSync(dir(), { recursive: true });
253
+ let n = 0;
254
+ for (const e of fs.readdirSync(src, { withFileTypes: true })) {
255
+ if (!e.isDirectory()) continue;
256
+ const to = path.join(dir(), e.name);
257
+ /* tam kurulu mu? tool.json + run.js yoksa yarım demektir → yeniden kur */
258
+ const complete = fs.existsSync(path.join(to, 'tool.json')) && fs.existsSync(path.join(to, 'run.js'));
259
+ if (complete) continue;
260
+ try {
261
+ if (fs.existsSync(to)) fs.rmSync(to, { recursive: true, force: true });
262
+ copyTree(path.join(src, e.name), to);
263
+ n++;
264
+ } catch {}
265
+ }
266
+ if (n) invalidate();
267
+ return n;
268
+ } catch {
269
+ return 0;
270
+ }
271
+ }
272
+
223
273
  /* Örnek tool: klasör boşsa biçimi göstermek için bir adet kur */
224
274
  function seedIfEmpty() {
225
275
  try {
@@ -249,4 +299,4 @@ function seedIfEmpty() {
249
299
  } catch {}
250
300
  }
251
301
 
252
- module.exports = { setNotify, list, scan, definitions, names, call, save, remove, seedIfEmpty, invalidate, dir, slugify };
302
+ module.exports = { setNotify, list, scan, definitions, names, call, save, remove, seedIfEmpty, seedDefaults, invalidate, dir, slugify };
@@ -0,0 +1,188 @@
1
+ 'use strict';
2
+ /* mt5_barlar2 - KOPRUSUZ OHLC bari.
3
+ Giris (stdin JSON): {"symbol":"GOLD","timeframe":"M1","count":60}
4
+ Cikis (stdout JSON): {"ok":true,"symbol","timeframe","count","bars":[{t,ts,o,h,l,c,v}]}
5
+ Yol: MT5 koprusune DOKUNMAZ; ayri bir python surecinde MetaTrader5 modulunu dogrudan cagirir.
6
+ SALT-OKUNUR: emir / pending / close cagrisi YOK. */
7
+
8
+ const fs = require('fs');
9
+ const os = require('os');
10
+ const path = require('path');
11
+ const { spawnSync } = require('child_process');
12
+
13
+ const DEFAULT_SYMBOL = 'GOLD';
14
+ const DEFAULT_TF = 'M1';
15
+ const DEFAULT_COUNT = 60;
16
+ const TF_ALLOWED = ['M1', 'M5', 'M15', 'M30', 'H1', 'H4', 'D1'];
17
+ const TERMINALS = [
18
+ 'C:\\Program Files\\FxPro - MetaTrader 5\\terminal64.exe',
19
+ 'C:\\Program Files\\MetaTrader 5\\terminal64.exe',
20
+ ];
21
+
22
+ function emit(obj) {
23
+ process.stdout.write(JSON.stringify(obj));
24
+ process.exit(obj.ok ? 0 : 1);
25
+ }
26
+
27
+ /* ---------- args: stdin JSON (argv / env yedek) ---------- */
28
+ function readArgs() {
29
+ return new Promise((resolve) => {
30
+ let buf = '';
31
+ let settled = false;
32
+ const finish = () => {
33
+ if (settled) return;
34
+ settled = true;
35
+ clearTimeout(timer);
36
+ try { process.stdin && process.stdin.pause(); } catch {}
37
+ const a = process.argv.slice(2).find((x) => String(x).trim().startsWith('{'));
38
+ if (!buf && a) return resolve({ raw: a, source: 'argv' });
39
+ if (!buf && process.env.BEAST_TOOL_ARGS) return resolve({ raw: process.env.BEAST_TOOL_ARGS, source: 'env' });
40
+ resolve({ raw: buf, source: buf ? 'stdin' : 'none' });
41
+ };
42
+ const timer = setTimeout(finish, 800);
43
+ try {
44
+ process.stdin.setEncoding('utf8');
45
+ process.stdin.on('data', (c) => { buf += c; });
46
+ process.stdin.on('end', finish);
47
+ process.stdin.on('error', finish);
48
+ process.stdin.resume();
49
+ } catch { finish(); }
50
+ });
51
+ }
52
+
53
+ function normSymbol(s) {
54
+ const t = String(s || DEFAULT_SYMBOL).toUpperCase().replace(/[^A-Z0-9.]/g, '');
55
+ if (!t) return DEFAULT_SYMBOL;
56
+ if (t === 'XAUUSD') return 'GOLD';
57
+ if (t === 'BTCUSD' || t === 'BTC') return 'BITCOIN';
58
+ return t;
59
+ }
60
+ function normTf(v) {
61
+ const t = String(v || DEFAULT_TF).toUpperCase();
62
+ return TF_ALLOWED.includes(t) ? t : DEFAULT_TF;
63
+ }
64
+ function normCount(v) {
65
+ let n = Math.round(Number(v));
66
+ if (!isFinite(n) || n <= 0) n = DEFAULT_COUNT;
67
+ return Math.max(1, Math.min(500, n));
68
+ }
69
+
70
+ function pythonCandidates() {
71
+ return [
72
+ 'python', 'py', 'python3',
73
+ (process.env.APPDATA || '') + '\\\\beast\\\\py\\\\python.exe',
74
+ 'C:\\Python314\\python.exe',
75
+ 'C:\\Python313\\python.exe', 'C:\\Python312\\python.exe',
76
+ 'C:\\Python311\\python.exe', 'C:\\Python310\\python.exe',
77
+ ];
78
+ }
79
+
80
+ function buildPy(SYMBOL, TIMEFRAME, COUNT) {
81
+ return `
82
+ import json, sys, datetime
83
+ try:
84
+ import MetaTrader5 as mt5
85
+ except Exception as e:
86
+ print("ERR_MODULE " + type(e).__name__ + ": " + str(e)); sys.exit(2)
87
+
88
+ SYMBOL = ${JSON.stringify(SYMBOL)}
89
+ TFNAME = ${JSON.stringify(TIMEFRAME)}
90
+ COUNT = ${COUNT}
91
+ TF = {"M1": mt5.TIMEFRAME_M1, "M5": mt5.TIMEFRAME_M5, "M15": mt5.TIMEFRAME_M15,
92
+ "M30": mt5.TIMEFRAME_M30, "H1": mt5.TIMEFRAME_H1, "H4": mt5.TIMEFRAME_H4,
93
+ "D1": mt5.TIMEFRAME_D1}[TFNAME]
94
+
95
+ if not mt5.initialize():
96
+ for t in ${JSON.stringify(TERMINALS)}:
97
+ if mt5.initialize(path=t):
98
+ break
99
+ if mt5.terminal_info() is None:
100
+ print("ERR_INITIALIZE " + str(mt5.last_error())); sys.exit(3)
101
+
102
+ info = mt5.symbol_info(SYMBOL)
103
+ if info is None:
104
+ print("ERR_SYMBOL yok: " + SYMBOL); sys.exit(4)
105
+ if not info.visible:
106
+ mt5.symbol_select(SYMBOL, True)
107
+
108
+ rates = mt5.copy_rates_from_pos(SYMBOL, TF, 0, COUNT)
109
+ if rates is None or len(rates) == 0:
110
+ print("ERR_RATES " + str(mt5.last_error())); sys.exit(5)
111
+
112
+ bars = [{"t": int(r["time"]),
113
+ "ts": datetime.datetime.utcfromtimestamp(int(r["time"])).strftime("%Y-%m-%d %H:%M"),
114
+ "o": float(r["open"]), "h": float(r["high"]), "l": float(r["low"]),
115
+ "c": float(r["close"]), "v": int(r["tick_volume"])} for r in rates]
116
+ tick = mt5.symbol_info_tick(SYMBOL)
117
+ print("###BARS###" + json.dumps({"bars": bars, "digits": int(info.digits),
118
+ "bid": float(tick.bid) if tick else None, "ask": float(tick.ask) if tick else None}))
119
+ mt5.shutdown()
120
+ `;
121
+ }
122
+
123
+ (async () => {
124
+ const received = await readArgs();
125
+ let args = {};
126
+ try { args = JSON.parse(String(received.raw || '').trim() || '{}'); } catch { args = {}; }
127
+ if (!args || typeof args !== 'object' || Array.isArray(args)) args = {};
128
+
129
+ try {
130
+ const log = path.join(__dirname, 'args.log');
131
+ if (fs.existsSync(log) && fs.statSync(log).size > 20000) fs.rmSync(log);
132
+ fs.appendFileSync(log, JSON.stringify({ at: new Date().toISOString(), source: received.source, raw: String(received.raw).slice(0, 200) }) + '\n');
133
+ } catch {}
134
+
135
+ const SYMBOL = normSymbol(args.symbol);
136
+ const TIMEFRAME = normTf(args.timeframe);
137
+ const COUNT = normCount(args.count);
138
+
139
+ const scriptPath = path.join(os.tmpdir(), 'beast_mt5_barlar2_' + process.pid + '.py');
140
+ try { fs.writeFileSync(scriptPath, buildPy(SYMBOL, TIMEFRAME, COUNT)); }
141
+ catch (e) { return emit({ ok: false, error: 'script yazilamadi: ' + String(e && e.message) }); }
142
+
143
+ let lastErr = '';
144
+ const tried = [];
145
+ for (const cmd of pythonCandidates()) {
146
+ tried.push(cmd);
147
+ let r;
148
+ try { r = spawnSync(cmd, [scriptPath], { encoding: 'utf8', timeout: 60000, windowsHide: true }); }
149
+ catch (e) { lastErr = cmd + ': ' + String(e && e.message); continue; }
150
+ const text = String((r && r.stdout) || '');
151
+ const err = String((r && r.stderr) || '');
152
+ const idx = text.indexOf('###BARS###');
153
+ if (idx >= 0) {
154
+ let data = null;
155
+ try { data = JSON.parse(text.slice(idx + 10).trim()); }
156
+ catch (e) { lastErr = cmd + ' json: ' + String(e && e.message); continue; }
157
+ return emit({
158
+ ok: true,
159
+ symbol: SYMBOL,
160
+ timeframe: TIMEFRAME,
161
+ count: data.bars.length,
162
+ requested: COUNT,
163
+ digits: data.digits,
164
+ bid: data.bid,
165
+ ask: data.ask,
166
+ interpreter: cmd,
167
+ route: 'BYPASS - dogrudan MetaTrader5 python (kopru kullanilmadi)',
168
+ args_source: received.source,
169
+ bars: data.bars,
170
+ });
171
+ }
172
+ lastErr = (err || text || ('cikis kodu ' + (r && r.status))).trim().slice(0, 400);
173
+ }
174
+
175
+ emit({
176
+ ok: false,
177
+ error: 'python MetaTrader5 ile bar okunamadi',
178
+ symbol: SYMBOL, timeframe: TIMEFRAME, count: COUNT,
179
+ args_received: String(received.raw).slice(0, 200),
180
+ args_source: received.source,
181
+ tried,
182
+ last_error: lastErr.slice(0, 600),
183
+ });
184
+ })();
185
+
186
+ /* PATCH 2026-09-10b: electron app-mode cocuk prosesi kapanmiyordu (90sn timeout).
187
+ stdout'un boruya bosalmasi icin kisa bekleme, sonra zorla cik. */
188
+ setTimeout(() => process.exit(0), 1500);
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "mt5_barlar2",
3
+ "description": "MT5'ten GERCEK OHLC mum verisi ceker - KOPRUSUZ yol: ayri bir python surecinde MetaTrader5 modulunu dogrudan cagirir (koprunun 'bars' handler'i olmadigi icin calisan yol). SALT-OKUNUR, islem acmaz. Girdi: {\"symbol\":\"GOLD\"|\"BITCOIN\",\"timeframe\":\"M1\"|\"M5\"|\"M15\"|\"M30\"|\"H1\"|\"H4\"|\"D1\",\"count\":60} (max 500). Cikti: {ok,symbol,timeframe,count,bars:[{t,ts,o,h,l,c,v}]} en eskiden yeniye.",
4
+ "parameters": {
5
+ "type": "object",
6
+ "properties": {
7
+ "symbol": {
8
+ "type": "string",
9
+ "description": "Broker sembol adi: GOLD veya BITCOIN (XAUUSD/BTCUSD DEGIL). Varsayilan GOLD."
10
+ },
11
+ "timeframe": {
12
+ "type": "string",
13
+ "description": "M1 | M5 | M15 | M30 | H1 | H4 | D1. Varsayilan M1."
14
+ },
15
+ "count": {
16
+ "type": "number",
17
+ "description": "Kac bar isteniyor (1-500, varsayilan 60)."
18
+ }
19
+ },
20
+ "required": []
21
+ },
22
+ "updatedAt": "2026-09-10T10:26:00.000Z"
23
+ }
@@ -0,0 +1,100 @@
1
+ 'use strict';
2
+ // MT5 BEKLEYEN EMIR KOY — 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 symbol = String(args.symbol || '').trim().toUpperCase();
78
+ const type = String(args.type || '').trim().toLowerCase();
79
+ const volume = Number(args.volume || 0);
80
+ const price = Number(args.price || 0);
81
+ const izin = ['buy_limit', 'sell_limit', 'buy_stop', 'sell_stop'];
82
+ if (!symbol) return console.log(JSON.stringify({ ok: false, error: 'symbol zorunlu' }));
83
+ if (!izin.includes(type)) return console.log(JSON.stringify({ ok: false, error: 'type: buy_limit|sell_limit|buy_stop|sell_stop' }));
84
+ if (!(volume > 0)) return console.log(JSON.stringify({ ok: false, error: 'volume (lot) zorunlu ve 0 dan buyuk' }));
85
+ if (!(price > 0)) return console.log(JSON.stringify({ ok: false, error: 'price zorunlu ve 0 dan buyuk' }));
86
+ const params = { symbol: symbol, type: type, volume: volume, price: price };
87
+ if (args.sl) params.sl = Number(args.sl);
88
+ if (args.tp) params.tp = Number(args.tp);
89
+ const r = await call([{ method: 'pending', params: params }]);
90
+ if (r.ok && r.data && r.data.result) {
91
+ const res = r.data.result;
92
+ console.log(JSON.stringify({ ok: true, ticket: res.order, retcode: res.retcode, comment: res.comment, detay: r.data }));
93
+ } else {
94
+ console.log(JSON.stringify({ ok: false, error: r.error || 'bekleyen emir reddedildi' }));
95
+ }
96
+ })();
97
+
98
+ /* PATCH 2026-09-10b: electron app-mode cocuk prosesi kapanmiyordu (90sn timeout).
99
+ stdout'un boruya bosalmasi icin kisa bekleme, sonra zorla cik. */
100
+ setTimeout(() => process.exit(0), 1500);
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "mt5_bekleyen",
3
+ "description": "BEKLEYEN EMİR koyar: symbol, type (buy_limit|sell_limit|buy_stop|sell_stop), volume, price zorunlu; sl/tp opsiyonel. Başarıda emir ticket'ı döner.",
4
+ "parameters": {
5
+ "type": "object",
6
+ "properties": {
7
+ "symbol": { "type": "string", "description": "Broker sembol adi: GOLD veya BITCOIN (XAUUSD degil)" },
8
+ "type": { "type": "string", "description": "buy_limit | sell_limit | buy_stop | sell_stop" },
9
+ "volume": { "type": "number", "description": "Lot (0.01-0.1)" },
10
+ "price": { "type": "number", "description": "Tetiklenme/limit fiyati" },
11
+ "sl": { "type": "number", "description": "Stop loss (opsiyonel)" },
12
+ "tp": { "type": "number", "description": "Take profit (opsiyonel)" }
13
+ },
14
+ "required": ["symbol", "type", "volume", "price"]
15
+ },
16
+ "updatedAt": "2026-09-09T18:50:00.000Z"
17
+ }
@@ -0,0 +1,93 @@
1
+ 'use strict';
2
+ // MT5 DURUM ENVANTERİ — hesap + pozisyonlar + bekleyen emirler (tek köprü oturumunda)
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
+ const r = await call([
76
+ { method: 'account', params: {} },
77
+ { method: 'positions', params: {} },
78
+ { method: 'orders', params: {} }
79
+ ]);
80
+ if (!r.ok) return console.log(JSON.stringify({ ok: false, error: r.error || 'durum alinamadi' }));
81
+ const out = { ok: true };
82
+ if (r.results && r.results[0] && r.results[0].ok) out.account = r.results[0].data.account;
83
+ else out.account_hata = (r.results && r.results[0] && r.results[0].error) || '?';
84
+ if (r.results && r.results[1] && r.results[1].ok) out.positions = r.results[1].data.positions;
85
+ else out.positions_hata = (r.results && r.results[1] && r.results[1].error) || '?';
86
+ if (r.results && r.results[2] && r.results[2].ok) out.orders = r.results[2].data.orders;
87
+ else out.orders_hata = (r.results && r.results[2] && r.results[2].error) || '?';
88
+ console.log(JSON.stringify(out));
89
+ })();
90
+
91
+ /* PATCH 2026-09-10b: electron app-mode cocuk prosesi kapanmiyordu (90sn timeout).
92
+ stdout'un boruya bosalmasi icin kisa bekleme, sonra zorla cik. */
93
+ setTimeout(() => process.exit(0), 1500);
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "mt5_durum",
3
+ "description": "MT5 tur başı envanteri TEK çağrıda: köprü bağlantısı + hesap özeti (bakiye/özkaynak/serbest marj) + açık pozisyonlar + bekleyen emirler. Parametre almaz. Trader ajanları karar öncesi bununla durum okur.",
4
+ "parameters": {
5
+ "type": "object",
6
+ "properties": {},
7
+ "required": []
8
+ },
9
+ "updatedAt": "2026-09-09T18:42:00.000Z"
10
+ }
@@ -0,0 +1,98 @@
1
+ 'use strict';
2
+ // MT5 PİYASA EMİRİ AÇ — 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; // bridge olay satiri (baglanti raporu)
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 symbol = String(args.symbol || '').trim().toUpperCase();
78
+ const side = String(args.side || '').trim().toLowerCase();
79
+ const volume = Number(args.volume || 0);
80
+ if (!symbol) return console.log(JSON.stringify({ ok: false, error: 'symbol zorunlu (örn XAUUSD)' }));
81
+ if (side !== 'buy' && side !== 'sell') return console.log(JSON.stringify({ ok: false, error: 'side: buy | sell' }));
82
+ if (!(volume > 0)) return console.log(JSON.stringify({ ok: false, error: 'volume (lot) zorunlu ve 0 dan buyuk olmali' }));
83
+ const params = { symbol: symbol, side: side, volume: volume };
84
+ if (args.sl) params.sl = Number(args.sl);
85
+ if (args.tp) params.tp = Number(args.tp);
86
+ if (args.comment) params.comment = String(args.comment);
87
+ const r = await call([{ method: 'market', params: params }]);
88
+ if (r.ok && r.data && r.data.result) {
89
+ const res = r.data.result;
90
+ console.log(JSON.stringify({ ok: true, ticket: res.order, retcode: res.retcode, comment: res.comment, fiyat: r.data.price, detay: r.data }));
91
+ } else {
92
+ console.log(JSON.stringify({ ok: false, error: (r.error || 'emir reddedildi') }));
93
+ }
94
+ })();
95
+
96
+ /* PATCH 2026-09-10b: electron app-mode cocuk prosesi kapanmiyordu (90sn timeout).
97
+ stdout'un boruya bosalmasi icin kisa bekleme, sonra zorla cik. */
98
+ setTimeout(() => process.exit(0), 1500);