beast-agent 2.75.0 → 2.76.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "beast-agent",
3
3
  "productName": "Beast Agent",
4
- "version": "2.75.0",
4
+ "version": "2.76.1",
5
5
  "description": "Ultra-fast local agent shell for Windows.",
6
6
  "author": "algokodcom (AlgoKod)",
7
7
  "license": "MIT",
package/src/main.js CHANGED
@@ -9906,7 +9906,8 @@ const financeState = {
9906
9906
  watchTickAt: 0,
9907
9907
  /* POZİSYON YÖNETİCİSİ (JEV): açık pozisyon varken 5 sn'lik watchdog turundan
9908
9908
  tetiklenen ayrı Jev ajanı — kapat/kısmi/SL kararlarını kendi talimatıyla verir */
9909
- posManager: { busy: false, rounds: 0, lastAt: 0, lastErr: '', lastPosCount: 0, tsPartials: new Set() },
9909
+ posManager: { busy: false, rounds: 0, lastAt: 0, lastErr: '', lastPosCount: 0, timer: null, tsPartials: new Set() },
9910
+ posSnapshot: null, /* son watchdog turunun pozisyon/hesap anlık görüntüsü (yönetici yeniden kullanır) */
9910
9911
  hoursTimer: null, /* trade saatleri otomatik duraklatma denetimi (10 sn) */
9911
9912
  hoursPaused: null, /* pencere kapanınca durdurulan ajanların planı — açılınca geri gelir */
9912
9913
  alerts: [], /* fiyat alarmları (kalıcı: finance/alerts.json) */
@@ -10045,6 +10046,9 @@ function finCfg() {
10045
10046
  ajan — varsayılan AÇIK; kendi talimatı (posManagerNote) yalnız onu bağlar. */
10046
10047
  if (typeof f.posManagerEnabled !== 'boolean') f.posManagerEnabled = true;
10047
10048
  if (typeof f.posManagerNote !== 'string') f.posManagerNote = '';
10049
+ /* Yönetici kontrol sıklığı (sn): 1-300; varsayılan 5 */
10050
+ if (!Number.isFinite(Number(f.posManagerSec))) f.posManagerSec = 5;
10051
+ f.posManagerSec = Math.max(1, Math.min(300, Math.round(Number(f.posManagerSec) || 5)));
10048
10052
  /* GÜNLÜK RUTİN: plan/review saatleri (HH:MM; boş = kapalı) — hafta içi cron */
10049
10053
  if (typeof f.planTime !== 'string') f.planTime = '';
10050
10054
  if (typeof f.reviewTime !== 'string') f.reviewTime = '';
@@ -11664,10 +11668,13 @@ async function finWatchTick() {
11664
11668
  try { await finRecordClose(ticket, st); } catch {}
11665
11669
  }
11666
11670
  }
11667
- /* POZİSYON YÖNETİCİSİ (JEV): açık pozisyon varken 5 sn'lik tur aynı anda
11668
- yönetici karar turunu tetikler (ayrı MT5 sorgusu yok; meşgulse atlar) */
11669
- if (positionsOk && positions.length) {
11670
- try { finPosManagerMaybe(positions, account); } catch {}
11671
+ /* POZİSYON YÖNETİCİSİ (JEV): pozisyon anlık görüntüsü saklanır (yönetici
11672
+ kendi zamanlayıcısında yeniden kullanır) + tur burada da tetiklenir */
11673
+ if (positionsOk) {
11674
+ financeState.posSnapshot = { at: Date.now(), positions, account };
11675
+ if (positions.length) {
11676
+ try { finPosManagerMaybe(positions, account); } catch {}
11677
+ }
11671
11678
  }
11672
11679
  try { await finCheckAlerts(); } catch {}
11673
11680
  if (!financeState.lastStatsAt || Date.now() - financeState.lastStatsAt > 120000) {
@@ -11683,9 +11690,12 @@ async function finWatchTick() {
11683
11690
  }
11684
11691
 
11685
11692
  function finWatchStart() {
11686
- if (financeState.watchTimer) return;
11687
- financeState.watchTimer = setInterval(() => { finWatchTick().catch(() => {}); }, 5000);
11688
- finWatchTick().catch(() => {});
11693
+ if (!financeState.watchTimer) {
11694
+ financeState.watchTimer = setInterval(() => { finWatchTick().catch(() => {}); }, 5000);
11695
+ finWatchTick().catch(() => {});
11696
+ }
11697
+ /* Pozisyon yöneticisinin KENDİ zamanlayıcısı (ayarlı aralık; 1-300 sn) */
11698
+ try { finPosManagerStart(); } catch {}
11689
11699
  }
11690
11700
 
11691
11701
  function finWatchStop() {
@@ -11693,6 +11703,7 @@ function finWatchStop() {
11693
11703
  clearInterval(financeState.watchTimer);
11694
11704
  financeState.watchTimer = null;
11695
11705
  }
11706
+ try { finPosManagerStop(); } catch {}
11696
11707
  }
11697
11708
 
11698
11709
  function finWatchLoad() {
@@ -13807,13 +13818,28 @@ function finParseInstructions(text) {
13807
13818
  if (m) out.lotMult = finInstrNum(m[1] || m[2] || m[3]);
13808
13819
  if (out.lotMult != null) out.lotMult = Math.max(1, Math.min(5, out.lotMult));
13809
13820
  if (/martingale|mart[ıi]ngale/.test(low)) {
13810
- /* Faktör serbest: "martingale 1.2", "martingale x1.20", "martingale 1,2",
13811
- "martingale çarpanı 1.2", "1.2x martingale", "1.2 kat martingale".
13812
- Yalnız bilinen bağlaçlardan sonra sayı okunur — "martingale kullan, 1R..."
13813
- gibi metinden yanlış sayı kapmaz. Varsayılan ×2 (1.01–5 arası geçerli). */
13814
- m = low.match(/(?:mart[ıi]ngale\s*(?:x|×|çarpan[ıi]?|carpan[ıi]?|oran[ıi]?|fakt[öo]r[üu]?|kat[ıi]?)?\s*(\d+(?:[.,]\d+)?))|(?:(\d+(?:[.,]\d+)?)\s*(?:x|×|kat[ıi]?)?\s*mart[ıi]ngale)/);
13815
- const mf = m ? finInstrNum(m[1] || m[2]) : null;
13816
- out.martingale = Math.max(1.01, Math.min(5, mf != null && mf > 1 ? mf : 2));
13821
+ /* FAKTÖR SERBEST — doğal yazımların hepsi denenir:
13822
+ "martingale 1.2" "martingale x1.20" "martingale 1,2"
13823
+ "martingale çarpanı 1.2" "1.2x martingale" "1.2 kat martingale"
13824
+ "martingale kullan, 1.2 kat" "martingale kullan (x1.2)" "martingale e 1.2x"
13825
+ Yanlış sayı kapmamak için: "1R de %50" gibi R-yüzdeleri ve 1 ve altı
13826
+ sayılar faktör sayılmaz (varsayılan ×2 kalır). Geçerli aralık 1.01-5. */
13827
+ const pats = [
13828
+ /mart[ıi]ngale\s*(?:x|×|çarpan[ıi]?|carpan[ıi]?|oran[ıi]?|fakt[öo]r[üu]?|kat[ıi]?)?\s*(\d+(?:[.,]\d+)?)(?!\s*r\b)/,
13829
+ /(\d+(?:[.,]\d+)?)\s*(?:x|×|kat[ıi]?)?\s*mart[ıi]ngale/,
13830
+ /mart[ıi]ngale[^0-9%\n]{0,24}?(\d+(?:[.,]\d+)?)\s*(?:x|×|kat[ıi]?)/,
13831
+ /mart[ıi]ngale[^0-9%\n]{0,24}?(\d+[.,]\d+)(?!\s*r\b)/,
13832
+ ];
13833
+ let mf = null;
13834
+ for (const p of pats) {
13835
+ m = low.match(p);
13836
+ const v = m ? finInstrNum(m[1]) : null;
13837
+ if (v != null && v > 1 && v <= 5) {
13838
+ mf = v;
13839
+ break;
13840
+ }
13841
+ }
13842
+ out.martingale = Math.max(1.01, Math.min(5, mf != null ? mf : 2));
13817
13843
  }
13818
13844
  /* kısmi kapatma: "1R'de %50" → atR=1, pct=50; "%50 1R" → aynı; "kısmi %50" → atR=1 */
13819
13845
  m = low.match(/(\d+(?:[.,]\d+)?)\s*r[^%\d]{0,28}%\s*(\d+(?:[.,]\d+)?)/);
@@ -14222,6 +14248,66 @@ async function finTsToolRequest(sidS, agent, ans, lines) {
14222
14248
  const FIN_POSMGR_ID = 'posmanager';
14223
14249
  const FIN_POSMGR_AGENT = { main: false, role: '', __posmgr: true };
14224
14250
 
14251
+ /* Yönetici kontrol sıklığı (sn) — ayarlardan; 1-300 */
14252
+ function finPosMgrSec() {
14253
+ try {
14254
+ return Math.max(1, Math.min(300, Math.round(Number(finCfg().posManagerSec) || 5)));
14255
+ } catch {
14256
+ return 5;
14257
+ }
14258
+ }
14259
+
14260
+ /* KENDİ ZAMANLAYICISI: 1 sn'lik yoklama, ayarlı aralık dolunca turu başlatır —
14261
+ böylece 5 sn'den hızlı (ör. 2 sn) ve yavaş (ör. 60 sn) aralıklar da çalışır.
14262
+ Taze watchdog anlık görüntüsü varsa onu kullanır (ekstra MT5 sorgusu yok). */
14263
+ async function finPosManagerTick() {
14264
+ const pm = financeState.posManager;
14265
+ if (!pm || pm.busy) return;
14266
+ let f = {};
14267
+ try { f = finCfg(); } catch {}
14268
+ if (f.posManagerEnabled === false) return;
14269
+ const sec = finPosMgrSec();
14270
+ if (pm.lastAt && Date.now() - pm.lastAt < sec * 1000) return;
14271
+ if (!mt5bridge.running) return;
14272
+ let positions = null;
14273
+ let account = null;
14274
+ const snap = financeState.posSnapshot;
14275
+ if (snap && Date.now() - Number(snap.at || 0) < 5000) {
14276
+ positions = snap.positions;
14277
+ account = snap.account;
14278
+ } else {
14279
+ try {
14280
+ const [posR, accR] = await Promise.all([
14281
+ mt5bridge.call('positions', {}, 8000).catch(() => null),
14282
+ mt5bridge.call('account', {}, 8000).catch(() => null),
14283
+ ]);
14284
+ positions = (posR && posR.ok && posR.data && posR.data.positions) || [];
14285
+ account = (accR && accR.ok && accR.data && accR.data.account) || null;
14286
+ financeState.posSnapshot = { at: Date.now(), positions, account };
14287
+ } catch {
14288
+ return;
14289
+ }
14290
+ }
14291
+ if (!Array.isArray(positions) || !positions.length) {
14292
+ pm.lastPosCount = 0;
14293
+ return;
14294
+ }
14295
+ finPosManagerMaybe(positions, account);
14296
+ }
14297
+
14298
+ function finPosManagerStart() {
14299
+ const pm = financeState.posManager;
14300
+ if (!pm || pm.timer) return;
14301
+ pm.timer = setInterval(() => { finPosManagerTick().catch(() => {}); }, 1000);
14302
+ }
14303
+
14304
+ function finPosManagerStop() {
14305
+ const pm = financeState.posManager;
14306
+ if (!pm || !pm.timer) return;
14307
+ clearInterval(pm.timer);
14308
+ pm.timer = null;
14309
+ }
14310
+
14225
14311
  /* Watchdog turundan çağrılır: uygunSA yönetici turunu arka planda başlatır
14226
14312
  (MT5 pozisyon verisi watchdog turundan gelir — ikinci sorgu yok). */
14227
14313
  function finPosManagerMaybe(positions, account) {
@@ -14230,6 +14316,8 @@ function finPosManagerMaybe(positions, account) {
14230
14316
  let f = {};
14231
14317
  try { f = finCfg(); } catch {}
14232
14318
  if (f.posManagerEnabled === false) return;
14319
+ const sec = finPosMgrSec();
14320
+ if (pm.lastAt && Date.now() - pm.lastAt < sec * 1000) return; /* ayarlı aralık dolmadı */
14233
14321
  const list = Array.isArray(positions) ? positions.filter(Boolean) : [];
14234
14322
  pm.lastPosCount = list.length;
14235
14323
  if (!list.length) return;
@@ -14397,7 +14485,7 @@ async function finPosManagerRound(positions, account) {
14397
14485
  finTsPost(
14398
14486
  FIN_POSMGR_ID,
14399
14487
  FIN_POSMGR_AGENT,
14400
- `🛡️ Pozisyon yöneticisi turu #${pm.rounds} (LLM yok — 5 sn):\n` +
14488
+ `🛡️ Pozisyon yöneticisi turu #${pm.rounds} (LLM yok — ${finPosMgrSec()} sn):\n` +
14401
14489
  (instrTxt ? 'TALİMAT AYARLARI (kod uygular): ' + instrTxt + '\n' : '') +
14402
14490
  lines.join('\n'),
14403
14491
  'yönetim'
@@ -14709,7 +14797,7 @@ async function finTypeSafeRound(sid, agent) {
14709
14797
  if (pos) {
14710
14798
  /* POZİSYON YÖNETİCİSİ açık: kapat/kısmi/SL kararları onun turunda */
14711
14799
  if (posManagerOn) {
14712
- lines.push(`- ${sym}: pozisyon açık #${pos.ticket} — yönetim Pozisyon Yöneticisi'nde (5 sn Jev turu)`);
14800
+ lines.push(`- ${sym}: pozisyon açık #${pos.ticket} — yönetim Pozisyon Yöneticisi'nde (${finPosMgrSec()} sn Jev turu)`);
14713
14801
  continue;
14714
14802
  }
14715
14803
  const ex = finTsNoul(ans, 'kapat_' + i);
@@ -14882,6 +14970,13 @@ async function finTypeSafeRound(sid, agent) {
14882
14970
  }
14883
14971
  /* JEV ARAÇ İSTEĞİ (tur düzeyi): eksik araç varsa TOOL botuna asenkron yazdır */
14884
14972
  try { await finTsToolRequest(sidS, agent, ans, lines); } catch {}
14973
+ /* GÖRÜNÜRLÜK: açık pozisyon varken de trade ajanı tur atar ve YENİ
14974
+ girişleri değerlendirir (yönetim ayrı ajanda olsa bile) */
14975
+ if (posManagerOn && posList.length) {
14976
+ lines.unshift(
14977
+ `ℹ️ ${posList.length} açık pozisyon Pozisyon Yöneticisi'nde (${finPosMgrSec()} sn) — bu trade turu yeni girişleri değerlendirdi.`
14978
+ );
14979
+ }
14885
14980
  const insTxt = finInstrSummary(ins);
14886
14981
  finTsPost(
14887
14982
  sidS,
@@ -15206,6 +15301,7 @@ ipcMain.handle('finance:snapshot', async () => {
15206
15301
  lastErr: String(financeState.posManager.lastErr || ''),
15207
15302
  positions: Number(financeState.posManager.lastPosCount) || 0,
15208
15303
  note: String(f.posManagerNote || ''),
15304
+ sec: Number(f.posManagerSec) || 5,
15209
15305
  },
15210
15306
  };
15211
15307
  });
@@ -15439,6 +15535,7 @@ ipcMain.handle('finance:settings', async (_e, patch) => {
15439
15535
  /* POZİSYON YÖNETİCİSİ: kendi talimatı + aç/kapa */
15440
15536
  if (p.posManagerNote !== undefined) f.posManagerNote = String(p.posManagerNote || '').slice(0, 1500);
15441
15537
  if (p.posManagerEnabled !== undefined) f.posManagerEnabled = p.posManagerEnabled !== false;
15538
+ if (p.posManagerSec !== undefined) f.posManagerSec = Math.max(1, Math.min(300, Math.round(Number(p.posManagerSec) || 5)));
15442
15539
  if (p.planTime !== undefined) f.planTime = /^([01]?\d|2[0-3]):([0-5]\d)$/.test(String(p.planTime || '').trim()) ? String(p.planTime).trim() : '';
15443
15540
  if (p.reviewTime !== undefined) f.reviewTime = /^([01]?\d|2[0-3]):([0-5]\d)$/.test(String(p.reviewTime || '').trim()) ? String(p.reviewTime).trim() : '';
15444
15541
  /* TRADE SAATLERİ: {on, start, end} — yerel saat; aralık dışında ajan turları
@@ -222,10 +222,14 @@
222
222
  <div class="fin-card" id="finPosCard" data-fin-card="posmgr">
223
223
  <div class="fin-card-title">POZİSYON YÖNETİCİSİ <span id="finPosDot" class="fin-dot off" title="Pozisyon yöneticisi durumu"></span><span id="finPosInfo" class="fin-hint"></span></div>
224
224
  <div class="fin-field fin-check">
225
- <label title="Açık pozisyon varken 5 saniyede bir JEV turu: kapat / kısmi kapat / SL taşı kararları. Trade ajanından bağımsız ayrı bir ajan — kendi talimatıyla çalışır; LLM kullanmaz.">
226
- <input id="finPosOn" type="checkbox" /> Aktif — açık pozisyonları 5 sn'de bir Jev ile yönet
225
+ <label title="Açık pozisyon varken ayarlı sıklıkta JEV turu: kapat / kısmi kapat / SL taşı kararları. Trade ajanından bağımsız ayrı bir ajan — kendi talimatıyla çalışır; LLM kullanmaz.">
226
+ <input id="finPosOn" type="checkbox" /> Aktif — açık pozisyonları Jev ile yönet
227
227
  </label>
228
228
  </div>
229
+ <div class="fin-field">
230
+ <span>Kontrol (sn)</span>
231
+ <input id="finPosSec" type="number" min="1" max="300" step="1" title="Kaç saniyede bir kontrol edilsin — 1-300 (varsayılan 5). Trade ajanından bağımsız kendi zamanlayıcısı vardır." />
232
+ </div>
229
233
  <div class="fin-field">
230
234
  <span>Yönetici talimatı <i class="fin-hint">— yalnız bu ajanı bağlar</i><button id="finPosHelp" class="fin-help-btn" type="button" title="Neler yazabilirim? Desteklenen talimatlar ve örnekler">?</button></span>
231
235
  <textarea id="finPosNote" rows="2" maxlength="1500" placeholder="örn. 1- 1R'de %50 kısmi kapat 2- kâr 2R'ye gelince kalanı kapat 3- zarar -0.5R'yi geçerse kes" title="Bu talimat YALNIZ Pozisyon Yöneticisi Jev ajanına gider (5 sn turu, kapat/kısmi/SL kararları); kaydetmek için alandan çık"></textarea>
@@ -253,6 +253,7 @@ const els = {
253
253
  finPosDot: $('#finPosDot'),
254
254
  finPosInfo: $('#finPosInfo'),
255
255
  finPosOn: $('#finPosOn'),
256
+ finPosSec: $('#finPosSec'),
256
257
  finPosNote: $('#finPosNote'),
257
258
  finPosStatus: $('#finPosStatus'),
258
259
  finPosList: $('#finPosList'),
@@ -9947,6 +9948,7 @@ function finTraderInputsSet(cfg) {
9947
9948
  if (els.finStrategy && ae !== els.finStrategy && !finStrategyDirty) els.finStrategy.value = cfg.strategy || '';
9948
9949
  if (els.finPosNote && ae !== els.finPosNote && !finPosNoteDirty) els.finPosNote.value = cfg.posManagerNote || '';
9949
9950
  if (els.finPosOn && ae !== els.finPosOn) els.finPosOn.checked = cfg.posManagerEnabled !== false;
9951
+ if (els.finPosSec && ae !== els.finPosSec) els.finPosSec.value = Number(cfg.posManagerSec) || 5;
9950
9952
  if (els.finMaxTradesDay && ae !== els.finMaxTradesDay) els.finMaxTradesDay.value = Number(cfg.maxTradesPerDay) || 0;
9951
9953
  if (els.finLossStreak && ae !== els.finLossStreak) els.finLossStreak.value = Number(cfg.lossStreakLimit) || 0;
9952
9954
  if (els.finLossStreakPause && ae !== els.finLossStreakPause) els.finLossStreakPause.value = Number(cfg.lossStreakPauseMin) || 0;
@@ -10113,13 +10115,14 @@ function finRenderPosManager(pm, cfg) {
10113
10115
  if (!pm) return;
10114
10116
  const enabled = cfg ? cfg.posManagerEnabled !== false : pm.enabled !== false;
10115
10117
  const pos = Number(pm.positions) || 0;
10118
+ const sec = Number(pm.sec || (cfg && cfg.posManagerSec)) || 5;
10116
10119
  if (els.finPosDot) {
10117
10120
  els.finPosDot.classList.remove('on', 'off', 'busy');
10118
10121
  els.finPosDot.classList.add(!enabled ? 'off' : pm.busy ? 'busy' : pos ? 'on' : 'off');
10119
10122
  els.finPosDot.title = !enabled
10120
10123
  ? 'Pozisyon yöneticisi kapalı'
10121
10124
  : pos
10122
- ? 'İzliyor — ' + pos + ' açık pozisyon (5 sn Jev turu)'
10125
+ ? 'İzliyor — ' + pos + ' açık pozisyon (' + sec + ' sn Jev turu)'
10123
10126
  : 'Açık pozisyon yok — beklemede';
10124
10127
  }
10125
10128
  if (els.finPosInfo) els.finPosInfo.textContent = pm.rounds ? '· tur ' + pm.rounds : '';
@@ -10127,8 +10130,8 @@ function finRenderPosManager(pm, cfg) {
10127
10130
  let t;
10128
10131
  if (!enabled) t = 'Kapalı — kutucuktan aç';
10129
10132
  else if (pm.busy) t = 'Tur çalışıyor…';
10130
- else if (!pos) t = 'Beklemede — açık pozisyon yok';
10131
- else t = 'İzliyor · ' + pos + ' pozisyon';
10133
+ else if (!pos) t = 'Beklemede — açık pozisyon yok (' + sec + ' sn yoklama)';
10134
+ else t = 'İzliyor · ' + pos + ' pozisyon · ' + sec + ' sn';
10132
10135
  if (pm.lastAt) {
10133
10136
  const d = new Date(pm.lastAt);
10134
10137
  const p = (x) => String(x).padStart(2, '0');
@@ -10797,6 +10800,7 @@ finAutoNum(els.finMaxTradesDay, 'maxTradesPerDay', 0, 50, 1);
10797
10800
  finAutoNum(els.finLossStreak, 'lossStreakLimit', 0, 10, 1);
10798
10801
  finAutoNum(els.finLossStreakPause, 'lossStreakPauseMin', 0, 1440, 5);
10799
10802
  finAutoNum(els.finReentry, 'reentryCooldownMin', 0, 1440, 5);
10803
+ finAutoNum(els.finPosSec, 'posManagerSec', 1, 300, 1);
10800
10804
  finAutoNum(els.finMaxPerCurrency, 'maxPerCurrency', 0, 20, 1);
10801
10805
  const finTimeSave = (el, key) => {
10802
10806
  if (!el) return;
@@ -10951,7 +10955,7 @@ function finHelpHtml(which) {
10951
10955
  ? `1- 1R'de %50 kısmi kapat\n2- kâr 2R'ye gelince kalanı kapat\n3- zarar -0.5R'yi geçerse kes`
10952
10956
  : `1- risk yüzde 2\n2- martingale kullan (x1.2)\n3- her mumda işlem açmak zorundasın\n4- aynı anda en fazla 10 işlem\n5- başlangıç bakiye 10.000\n6- günlük zarar %3`;
10953
10957
  const head = posmgr
10954
- ? 'Pozisyon Yöneticisi (5 sn turu) açık pozisyonları yönetir: kapat / kısmi kapat / SL taşı.'
10958
+ ? 'Pozisyon Yöneticisi (ayarlı sıklık — varsayılan 5 sn) açık pozisyonları yönetir: kapat / kısmi kapat / SL taşı. Trade Ajanı pozisyon açıkken de tur atmaya devam eder ve yeni girişleri değerlendirir.'
10955
10959
  : 'Trade Ajanı girişleri yönetir: yön, emir tipi, risk, lot, martingale ve günlük limitler.';
10956
10960
  const rows = items
10957
10961
  .map((it) => '<div class="fin-help-item"><div class="fin-help-code">' + it[0] + '</div><div class="fin-help-desc">' + it[1] + '</div></div>')