beast-agent 2.30.1 → 2.30.2

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.30.1",
4
+ "version": "2.30.2",
5
5
  "description": "Ultra-fast local agent shell for Windows.",
6
6
  "author": "algokodcom (AlgoKod)",
7
7
  "license": "MIT",
package/src/main.js CHANGED
@@ -8323,8 +8323,12 @@ function finCfg() {
8323
8323
  /* OTOMATİK İŞLEM hep açık — kullanıcı onay kutusu KALDIRILDI: trade ajanının
8324
8324
  amacı zaten işlem açmak; onay sorulmaz, limitler (max lot/pozisyon) korur */
8325
8325
  f.allowTrading = true;
8326
- if (typeof f.analysisAuto !== 'boolean') f.analysisAuto = true; /* sayıya göre otomatik atama */
8327
- if (!Number(f.analysisCount)) f.analysisCount = 2; /* varsayılan: 2 uzman ajan */
8326
+ /* ANALİZ EKİBİ ARTIK SADECE SAYI: elle rol seçimi kaldırıldı — atama daima
8327
+ otomatik (Teknik → Risk → Haber). 0 = ekip kapalı GEÇERLİ değerdir;
8328
+ yalnız eksik/bozuk değerde varsayılan 2'ye düşülür. */
8329
+ f.analysisAuto = true;
8330
+ if (!Number.isFinite(Number(f.analysisCount))) f.analysisCount = 2;
8331
+ f.analysisCount = Math.max(0, Math.min(FIN_ROLES_AUTO.length, Math.round(Number(f.analysisCount) || 0)));
8328
8332
  if (!Number(f.intervalSec)) f.intervalSec = 120;
8329
8333
  if (!Number(f.maxLot)) f.maxLot = 0.1;
8330
8334
  if (f.maxPositions == null) f.maxPositions = 3;
@@ -8767,6 +8771,7 @@ ipcMain.handle('finance:snapshot', async () => {
8767
8771
  let account = st.account || null;
8768
8772
  let positions = [];
8769
8773
  let orders = [];
8774
+ let ordersError = '';
8770
8775
  let symbols = [];
8771
8776
  if (st.running) {
8772
8777
  const [a, p, o, sy] = await Promise.all([
@@ -8778,6 +8783,7 @@ ipcMain.handle('finance:snapshot', async () => {
8778
8783
  if (a && a.ok) account = a.data && a.data.account;
8779
8784
  if (p && p.ok) positions = (p.data && p.data.positions) || [];
8780
8785
  if (o && o.ok) orders = (o.data && o.data.orders) || [];
8786
+ else if (o && o.error) ordersError = String(o.error).slice(0, 200);
8781
8787
  if (sy && sy.ok) symbols = (sy.data && sy.data.symbols) || [];
8782
8788
  }
8783
8789
  const busy = financeState.traderSid && engine ? engine.isBusy(financeState.traderSid) : false;
@@ -8787,9 +8793,11 @@ ipcMain.handle('finance:snapshot', async () => {
8787
8793
  account,
8788
8794
  positions,
8789
8795
  orders,
8796
+ ordersError,
8790
8797
  symbols,
8791
8798
  cfg: f,
8792
8799
  roles: FIN_ROLES,
8800
+ rolesAuto: FIN_ROLES_AUTO,
8793
8801
  trader: { on: financeState.traderOn, busy, rounds: financeState.traderRounds, lastAt: financeState.lastRoundAt },
8794
8802
  };
8795
8803
  });
@@ -163,15 +163,27 @@
163
163
  </div>
164
164
  <div class="fin-card fin-card-trader">
165
165
  <div class="fin-card-title">TRADE AJANI <span id="finTraderDot" class="fin-dot off" title="Trader durumu"></span></div>
166
- <div class="fin-row"><select id="finTraderModel" title="Trader ajanının modeli — farklı API/model seçilebilir"></select></div>
167
- <div class="fin-row fin-mini">
168
- <label>Tur (sn)</label><input id="finInterval" type="number" min="30" max="3600" step="10" />
169
- <label>Max lot</label><input id="finMaxLot" type="number" min="0.01" max="100" step="0.01" />
166
+ <div class="fin-field">
167
+ <span>Model</span>
168
+ <select id="finTraderModel" title="Trader ajanının modeli — farklı API/model seçilebilir"></select>
170
169
  </div>
171
- <div class="fin-row fin-mini"><label>Semboller</label><button id="finSymBtn" class="fin-sym-select" title="MT5 sembol listesinden seç — tıkla">&#8230;</button></div>
172
- <div class="fin-row fin-roles-row">
173
- <label>Analiz ekibi</label>
174
- <div id="finRoles" class="fin-roles" title="Trader&#39;ın yanında koşacak uzman ajanlar — tüm skill + mt5 erişimli, işlem açmazlar"></div>
170
+ <div class="fin-grid2">
171
+ <div class="fin-field">
172
+ <span>Tur (sn)</span>
173
+ <input id="finInterval" type="number" min="30" max="3600" step="10" />
174
+ </div>
175
+ <div class="fin-field">
176
+ <span>Max lot</span>
177
+ <input id="finMaxLot" type="number" min="0.01" max="100" step="0.01" />
178
+ </div>
179
+ </div>
180
+ <div class="fin-field">
181
+ <span>Semboller</span>
182
+ <button id="finSymBtn" class="fin-sym-select" title="MT5 sembol listesinden seç — tıkla">&#8230;</button>
183
+ </div>
184
+ <div class="fin-field">
185
+ <span>Analiz ekibi <i class="fin-hint">— sadece sayı seç, rolleri sistem otomatik atar</i></span>
186
+ <div id="finRoles" class="fin-roles" title="Trader&#39;ın yanında koşacak uzman ajan SAYISI — roller otomatik atanır (Teknik → Risk → Haber); işlem açmazlar"></div>
175
187
  </div>
176
188
  <div class="fin-row fin-btn-row">
177
189
  <button id="finTraderBtn" class="fin-start">&#9654;&#xFE0E; Ajanı Başlat</button>
@@ -181,9 +193,7 @@
181
193
  <div class="fin-card">
182
194
  <div class="fin-card-title">POZİSYONLAR <span id="finPosCount"></span></div>
183
195
  <div id="finPosList"><div class="fin-empty">Açık pozisyon yok</div></div>
184
- </div>
185
- <div class="fin-card">
186
- <div class="fin-card-title">BEKLEYEN EMİRLER <span id="finOrdCount"></span></div>
196
+ <div class="fin-sect-title">BEKLEYEN EMİRLER <span id="finOrdCount"></span></div>
187
197
  <div id="finOrdList"><div class="fin-empty">Bekleyen emir yok</div></div>
188
198
  </div>
189
199
  <div class="fin-card">
@@ -8888,14 +8888,14 @@ const FIN_ORDER_TYPES = {
8888
8888
  7: { t: 'SELL STP-LMT', c: 'sell' },
8889
8889
  };
8890
8890
 
8891
- function finRenderOrders(list) {
8891
+ function finRenderOrders(list, err) {
8892
8892
  if (!els.finOrdList) return;
8893
8893
  els.finOrdList.textContent = '';
8894
8894
  if (els.finOrdCount) els.finOrdCount.textContent = list && list.length ? '(' + list.length + ')' : '';
8895
8895
  if (!list || !list.length) {
8896
8896
  const d = document.createElement('div');
8897
8897
  d.className = 'fin-empty';
8898
- d.textContent = 'Bekleyen emir yok';
8898
+ d.textContent = err ? 'Emir listesi alınamadı: ' + err : 'Bekleyen emir yok';
8899
8899
  els.finOrdList.appendChild(d);
8900
8900
  return;
8901
8901
  }
@@ -8994,89 +8994,60 @@ function finTraderInputsSet(cfg) {
8994
8994
  if (els.finTraderModel && ae !== els.finTraderModel && cfg.traderSel) els.finTraderModel.value = cfg.traderSel;
8995
8995
  }
8996
8996
 
8997
- /* ANALİZ EKİBİ: trader yanında koşacak uzman ajan rolleri — İKİ MOD:
8998
- (1) OTOMATİK: sadece SAYI gir → gereklı ajanları sistem kendisi ata;
8999
- (2) ELLE SEÇ: rol kutucukları (Risk / Teknik / Haber-Makro) çoklu seçilir.
9000
- Katalog sunucudan (finance snapshot/state.roles) gelir, yerel yedek var. */
8997
+ /* ANALİZ EKİBİ: SADECE SAYI seçilir — rolleri sistem otomatik atar
8998
+ (FIN_ROLES_AUTO sırası: Teknik → Risk → Haber). Elle rol kutucukları
8999
+ kaldırıldı; analysisAuto sunucuda daima açık. Katalog sunucudan gelir. */
9001
9000
  let finRolesCatalog = [
9002
9001
  { id: 'risk', label: 'Risk Ajanı', desc: 'marj/kaldıraç/SL disiplini, exposure ve günlük kayıp hızı denetimi' },
9003
9002
  { id: 'technic', label: 'Teknik Analiz', desc: 'trend/yapı/destek-direnç/momentum okuma, AL-SAT-BEKLE önerileri' },
9004
9003
  { id: 'macro', label: 'Haber / Makro', desc: 'haber akışı + ekonomik takvim, DXY/emtia bağıntıları, yön eğilimi' },
9005
9004
  ];
9005
+ let finRolesAuto = ['technic', 'risk', 'macro'];
9006
9006
  let finRolesDirty = false; /* tık→kaydet arası snapshot ezmesin */
9007
9007
  let finRolesSyncTimer = null;
9008
9008
 
9009
- function finRolesSel() {
9010
- const box = els.finRoles;
9011
- return box ? [...box.querySelectorAll('input[data-role]:checked')].map((cb) => cb.dataset.role) : [];
9009
+ function finRoleLabel(id) {
9010
+ const d = (finRolesCatalog || []).find((x) => x.id === String(id || ''));
9011
+ return d ? d.label : String(id || '');
9012
9012
  }
9013
9013
 
9014
9014
  function finRenderRoles(cfg) {
9015
9015
  const box = els.finRoles;
9016
9016
  if (!box) return;
9017
9017
  if (finRolesDirty) return; /* bekleyen kullanıcı değişikliği korunur */
9018
- const auto = !!(cfg && cfg.analysisAuto);
9019
- const count = Math.max(0, Math.round(Number(cfg && cfg.analysisCount) || 0));
9020
- const sel = cfg && Array.isArray(cfg.analysisTeam) ? cfg.analysisTeam : [];
9018
+ const max = Math.max(1, (finRolesAuto || []).length || 3);
9019
+ const count = Math.max(0, Math.min(max, Math.round(Number(cfg && cfg.analysisCount) || 0)));
9021
9020
  box.innerHTML = '';
9022
-
9023
- /* OTOMATİK çipi + sayı girişi */
9024
- const autoLab = document.createElement('label');
9025
- autoLab.className = 'fin-role fin-role-auto';
9026
- autoLab.title = 'Rol seçmeden SAYI gir — gereklı ajanları sistem otomatik atar (teknik → risk → haber sırası)';
9027
- const autoCb = document.createElement('input');
9028
- autoCb.type = 'checkbox';
9029
- autoCb.checked = auto;
9030
- autoLab.appendChild(autoCb);
9031
- autoLab.appendChild(document.createTextNode('⚙ Otomatik'));
9032
- autoCb.addEventListener('change', () => {
9033
- finRolesDirty = true;
9034
- finSaveCfg({ analysisAuto: autoCb.checked });
9035
- toast(autoCb.checked ? 'Analiz ekibi OTOMATİK — sayı kadar gereklı ajan atanır' : 'Analiz ekibi ELLE SEÇİM moduna geçti');
9036
- clearTimeout(finRolesSyncTimer);
9037
- finRolesSyncTimer = setTimeout(() => { finRolesDirty = false; finSnapshot(); }, 900);
9038
- });
9039
- box.appendChild(autoLab);
9040
-
9021
+ const wrap = document.createElement('div');
9022
+ wrap.className = 'fin-team';
9041
9023
  const cnt = document.createElement('input');
9042
9024
  cnt.type = 'number';
9043
9025
  cnt.className = 'fin-role-count';
9044
9026
  cnt.min = '0';
9045
- cnt.max = String(finRolesCatalog.length);
9027
+ cnt.max = String(max);
9046
9028
  cnt.step = '1';
9047
- cnt.value = String(count || 0);
9048
- cnt.title = 'Otomatik mod: kaç uzman ajan koşacak (0 = ekip yok)';
9049
- cnt.disabled = !auto;
9029
+ cnt.value = String(count);
9030
+ cnt.title = 'Kaç uzman ajan koşacak (0 = ekip yok, en fazla ' + max + '). Roller otomatik atanır.';
9031
+ const hint = document.createElement('span');
9032
+ hint.className = 'fin-team-hint';
9033
+ const names = (n) => finRolesAuto.slice(0, n).map(finRoleLabel);
9034
+ const paint = (n) => {
9035
+ hint.textContent = n > 0 ? 'otomatik: ' + names(n).join(' · ') : 'ekip kapalı — sadece trader koşar';
9036
+ };
9050
9037
  cnt.addEventListener('change', () => {
9038
+ const n = Math.max(0, Math.min(max, Math.round(Number(cnt.value) || 0)));
9039
+ cnt.value = String(n);
9051
9040
  finRolesDirty = true;
9052
- finSaveCfg({ analysisCount: Math.max(0, Math.round(Number(cnt.value) || 0)) });
9053
- toast('Analiz ekibi: ' + (Math.round(Number(cnt.value) || 0) || 'kapalı') + ' uzman ajan (otomatik)');
9041
+ finSaveCfg({ analysisAuto: true, analysisCount: n });
9042
+ paint(n);
9043
+ toast(n ? 'Analiz ekibi: ' + n + ' ajan — ' + names(n).join(', ') : 'Analiz ekibi kapatıldı');
9054
9044
  clearTimeout(finRolesSyncTimer);
9055
9045
  finRolesSyncTimer = setTimeout(() => { finRolesDirty = false; finSnapshot(); }, 900);
9056
9046
  });
9057
- box.appendChild(cnt);
9058
-
9059
- /* rol kutucukları — otomatik moddayken pasif */
9060
- for (const r of finRolesCatalog) {
9061
- const lab = document.createElement('label');
9062
- lab.className = 'fin-role';
9063
- const cb = document.createElement('input');
9064
- cb.type = 'checkbox';
9065
- cb.dataset.role = r.id;
9066
- cb.checked = sel.includes(r.id);
9067
- cb.disabled = auto;
9068
- cb.title = r.desc + ' — tüm skill + mt5 erişimli, işlem açmaz';
9069
- lab.appendChild(cb);
9070
- lab.appendChild(document.createTextNode(r.label));
9071
- cb.addEventListener('change', () => {
9072
- finRolesDirty = true;
9073
- finSaveCfg({ analysisTeam: finRolesSel() });
9074
- toast(r.label + (cb.checked ? ' ekibe eklendi — sonraki başlatışta koşar' : ' ekipten çıkarıldı'));
9075
- clearTimeout(finRolesSyncTimer);
9076
- finRolesSyncTimer = setTimeout(() => { finRolesDirty = false; finSnapshot(); }, 900);
9077
- });
9078
- box.appendChild(lab);
9079
- }
9047
+ paint(count);
9048
+ wrap.appendChild(cnt);
9049
+ wrap.appendChild(hint);
9050
+ box.appendChild(wrap);
9080
9051
  }
9081
9052
 
9082
9053
  function finRenderTrader(trader, cfg) {
@@ -9141,9 +9112,10 @@ async function finSnapshot() {
9141
9112
  finSetDot(b.connected ? true : b.running ? 'busy' : false, b);
9142
9113
  finRenderAccount(r.account);
9143
9114
  finRenderPositions(r.positions || []);
9144
- finRenderOrders(r.orders || []);
9115
+ finRenderOrders(r.orders || [], r.ordersError || '');
9145
9116
  finRenderSymbols(r.symbols || []);
9146
9117
  if (Array.isArray(r.roles) && r.roles.length) finRolesCatalog = r.roles;
9118
+ if (Array.isArray(r.rolesAuto) && r.rolesAuto.length) finRolesAuto = r.rolesAuto;
9147
9119
  finTraderInputsSet(r.cfg);
9148
9120
  finRenderRoles(r.cfg);
9149
9121
  finRenderTrader(r.trader, r.cfg);
@@ -9258,9 +9230,7 @@ if (els.finTraderBtn) {
9258
9230
  else if (r && r.ok) {
9259
9231
  const cfg = (await beast.financeState().catch(() => null));
9260
9232
  const c = (cfg && cfg.cfg) || {};
9261
- const team = c.analysisAuto
9262
- ? Math.round(Number(c.analysisCount) || 0)
9263
- : finRolesSel().length;
9233
+ const team = Math.round(Number(c.analysisCount) || 0);
9264
9234
  toast(team ? 'Trade ajanı + analiz ekibi (' + team + ' uzman) başladı — turlar panelde izlenir' : 'Trade ajanı başladı — turlar panelde izlenir');
9265
9235
  }
9266
9236
  }
@@ -4833,6 +4833,49 @@ body.finance-mode #composerWrap { margin-right: var(--finW, 400px); }
4833
4833
  }
4834
4834
  .fin-row input:focus, .fin-row select:focus { border-color: var(--accent); outline: none; }
4835
4835
 
4836
+ /* TRADE AJANI formu — etiket üstte, kontrol altta; tur/max lot 2 kolon */
4837
+ .fin-field { display: flex; flex-direction: column; gap: 3px; min-width: 0; margin-bottom: 8px; }
4838
+ .fin-field > span { font-size: 10px; color: var(--muted); }
4839
+ .fin-field input, .fin-field select {
4840
+ width: 100%;
4841
+ min-width: 0;
4842
+ background: var(--panel2);
4843
+ border: 1px solid var(--border);
4844
+ color: var(--text);
4845
+ font-size: 12px;
4846
+ padding: 4px 7px;
4847
+ border-radius: 6px;
4848
+ }
4849
+ .fin-field input:focus, .fin-field select:focus { border-color: var(--accent); outline: none; }
4850
+ .fin-field .fin-sym-select { width: 100%; }
4851
+ .fin-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
4852
+ .fin-grid2 .fin-field { margin-bottom: 8px; }
4853
+ .fin-hint { font-style: normal; opacity: 0.75; }
4854
+ /* ekib sayısı + otomatik atama özeti */
4855
+ .fin-team { display: flex; align-items: center; gap: 8px; min-width: 0; }
4856
+ .fin-team-hint {
4857
+ flex: 1;
4858
+ min-width: 0;
4859
+ font-size: 10.5px;
4860
+ color: var(--muted);
4861
+ white-space: nowrap;
4862
+ overflow: hidden;
4863
+ text-overflow: ellipsis;
4864
+ }
4865
+ /* POZİSYONLAR kartı içi bölüm başlığı (bekleyen emirler) */
4866
+ .fin-sect-title {
4867
+ display: flex;
4868
+ align-items: center;
4869
+ gap: 6px;
4870
+ margin: 9px 0 6px;
4871
+ padding-top: 8px;
4872
+ border-top: 1px dashed var(--border);
4873
+ font-size: 10px;
4874
+ font-weight: 800;
4875
+ letter-spacing: 1px;
4876
+ color: var(--muted);
4877
+ }
4878
+
4836
4879
  /* TRADE AJANI sembol seçme düğmesi — tıklayınca MT5 sembol seçici açılır */
4837
4880
  .fin-sym-select {
4838
4881
  flex: 1;
@@ -4887,15 +4930,15 @@ body.finance-mode #composerWrap { margin-right: var(--finW, 400px); }
4887
4930
  .fin-role input:disabled { opacity: 0.45; cursor: default; }
4888
4931
  .fin-role-auto { font-weight: 700; }
4889
4932
  /* Otomatik moddaki SAYI girişi */
4890
- .fin-role-count {
4891
- flex: none; width: 44px;
4933
+ .fin-field .fin-role-count {
4934
+ flex: none; width: 52px;
4892
4935
  background: var(--panel2); color: var(--text);
4893
4936
  border: 1px solid var(--border); border-radius: 8px;
4894
- font-size: 11px; font-weight: 700; text-align: center;
4895
- padding: 2px 3px;
4937
+ font-size: 12px; font-weight: 700; text-align: center;
4938
+ padding: 3px 3px;
4896
4939
  }
4897
- .fin-role-count:focus { border-color: var(--accent); outline: none; }
4898
- .fin-role-count:disabled { opacity: 0.45; }
4940
+ .fin-field .fin-role-count:focus { border-color: var(--accent); outline: none; }
4941
+ .fin-field .fin-role-count:disabled { opacity: 0.45; }
4899
4942
  .fin-start {
4900
4943
  flex: none;
4901
4944
  background: var(--accent);