beast-agent 2.30.2 → 2.30.3

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.2",
4
+ "version": "2.30.3",
5
5
  "description": "Ultra-fast local agent shell for Windows.",
6
6
  "author": "algokodcom (AlgoKod)",
7
7
  "license": "MIT",
@@ -6372,34 +6372,37 @@ Engine.prototype._agentDmSend = function (fromSid, args) {
6372
6372
  groupName verilmemişse ama iki taraf da AYNI AÇIK grubun üyesiyse mesaj
6373
6373
  YİNE GRUBA düşer — üye üyeye 1:1 thread'lere ayrı ayrı dağılmaz; ekibin
6374
6374
  tüm iç trafiği TEK grup sohbetinde canlı toplanır. */
6375
- const shared = groupName || !target ? null : this._agentDmSharedGroup(fromSid, target);
6375
+ /* TEK İŞ = TEK GRUP: taraflar AÇIK bir ekip/grup üyesiyse mesaj HER ZAMAN o
6376
+ gruba düşer — group: verilse bile yeni grup AÇILMAZ. Ayrıca group adı
6377
+ mevcut bir grubun başlığıyla eşleşiyorsa (ör. "Beast Finance EKİP" →
6378
+ team:finance) o grup kullanılır; aynı iş için ikinci grup oluşmaz. */
6379
+ const shared = target ? this._agentDmSharedGroup(fromSid, target) : null;
6376
6380
  let gid = '';
6377
- if (groupName || shared) {
6378
- let g;
6379
- if (groupName) {
6380
- /* gid Türkçe-kararsız normalize: ALTIN/Altın/altın aynı grup */
6381
- gid =
6382
- 'grp:' +
6383
- groupName
6384
- .toLowerCase()
6385
- .replace(/\u0307/g, '')
6386
- .replace(/ı/g, 'i')
6387
- .replace(/ğ/g, 'g')
6388
- .replace(/ü/g, 'u')
6389
- .replace(/ş/g, 's')
6390
- .replace(/ö/g, 'o')
6391
- .replace(/ç/g, 'c');
6392
- g = this._agentGroups.get(gid);
6393
- if (!g) {
6394
- if (!target) return { ok: false, error: 'yeni grup için to ile en az bir ajan belirt' };
6395
- g = { id: gid, title: groupName, members: [], titles: {}, createdAt: at, closed: false };
6396
- this._agentGroups.set(gid, g);
6381
+ let g = null;
6382
+ if (shared) {
6383
+ g = shared;
6384
+ gid = String(g.id || '');
6385
+ } else if (groupName) {
6386
+ gid = 'grp:' + this._agentGroupKey(groupName);
6387
+ g = this._agentGroups.get(gid) || null;
6388
+ if (!g) {
6389
+ const want = this._agentGroupKey(groupName);
6390
+ for (const [, cand] of this._agentGroups || new Map()) {
6391
+ if (!cand || cand.closed) continue;
6392
+ if (this._agentGroupKey(cand.title) === want) {
6393
+ g = cand;
6394
+ gid = String(cand.id || '');
6395
+ break;
6396
+ }
6397
6397
  }
6398
- } else {
6399
- g = shared;
6400
- gid = String(g.id || '');
6401
6398
  }
6402
- g.titles = g.titles || {};
6399
+ if (!g) {
6400
+ if (!target) return { ok: false, error: 'yeni grup için to ile en az bir ajan belirt' };
6401
+ g = { id: gid, title: groupName, members: [], titles: {}, createdAt: at, closed: false };
6402
+ this._agentGroups.set(gid, g);
6403
+ }
6404
+ }
6405
+ if (g) { g.titles = g.titles || {};
6403
6406
  const addMember = (sid, title) => {
6404
6407
  sid = String(sid);
6405
6408
  if (!g.members.includes(sid)) g.members.push(sid);
@@ -6478,6 +6481,20 @@ Engine.prototype._agentDmSharedGroup = function (a, b) {
6478
6481
  return null;
6479
6482
  };
6480
6483
 
6484
+ /* Grup adı anahtarı: Türkçe-kararsız normalize — ALTIN/Altın/altın aynı gruba
6485
+ iner; başlık eşleştirmede de kullanılır (ör. "Beast Finance EKİP"). */
6486
+ Engine.prototype._agentGroupKey = function (name) {
6487
+ return String(name || '')
6488
+ .toLowerCase()
6489
+ .replace(/\u0307/g, '')
6490
+ .replace(/ı/g, 'i')
6491
+ .replace(/ğ/g, 'g')
6492
+ .replace(/ü/g, 'u')
6493
+ .replace(/ş/g, 's')
6494
+ .replace(/ö/g, 'o')
6495
+ .replace(/ç/g, 'c');
6496
+ };
6497
+
6481
6498
  Engine.prototype._pushAgentDm = function (dm) {
6482
6499
  this._agentDms = this._agentDms || [];
6483
6500
  this._agentDms.push(dm);
@@ -6517,6 +6534,12 @@ Engine.prototype._agentTeamJoin = function (job) {
6517
6534
  g.closed = false;
6518
6535
  delete g.closedAt;
6519
6536
  g.titles = g.titles || {};
6537
+ /* durdurulmuş eski üyeler aktif kadrodan düşer — yeniden başlayan ekipte
6538
+ kapanmış ajanlar üye listesinde görünmez (geçmiş mesajlar korunur) */
6539
+ g.members = (g.members || []).filter((m) => {
6540
+ const j = this._bgJobs && this._bgJobs.get(String(m));
6541
+ return !j || j.status === 'running';
6542
+ });
6520
6543
  const add = (id, title) => {
6521
6544
  id = String(id);
6522
6545
  if (!g.members.includes(id)) g.members.push(id);
package/src/main.js CHANGED
@@ -8609,6 +8609,9 @@ function finAgentStop(sid, reason) {
8609
8609
  engine._bgEmit();
8610
8610
  }
8611
8611
  } catch {}
8612
+ /* AJAN DM: duran ajanın birebir sohbetleri kapanır; grupta KOŞAN üye
8613
+ kalmadıysa ekip sohbeti de GEÇMİŞE düşer (aktif listede kalmaz) */
8614
+ try { if (engine && engine._agentDmClose) engine._agentDmClose(sid); } catch {}
8612
8615
  finPush('trader', { state: 'idle', rounds: financeState.traderRounds });
8613
8616
  return true;
8614
8617
  }
@@ -8856,8 +8859,24 @@ ipcMain.handle('finance:settings', async (_e, patch) => {
8856
8859
  }
8857
8860
  f.symbolHistory = hist.slice(-40);
8858
8861
  f.symbols = next;
8862
+ /* KOŞAN ajanlar DURDURULMADAN yeni listeyi alır: ana trader + analiz ekibi
8863
+ sonraki turda güncel sembollere odaklanır (sembol işçileri kendi
8864
+ sembolünde kalır — onlar tek sembole özeldir). */
8865
+ for (const [, a] of financeState.agents) {
8866
+ if (a && (a.main || a.role)) a.symbols = next.slice(0, 20);
8867
+ }
8859
8868
  }
8860
8869
  if (p.intervalSec !== undefined) f.intervalSec = Math.max(30, Math.min(3600, Math.round(Number(p.intervalSec) || 120)));
8870
+ /* TUR ARALIĞI CANLI: bekleyen zamanlayıcılar yeni aralıkla yeniden kurulur —
8871
+ koşan tur bitince zaten finFlushOnDone yeni aralığı okur. */
8872
+ if (p.intervalSec !== undefined && financeState.agents) {
8873
+ const iv = Math.max(30, Math.round(Number(f.intervalSec) || 120)) * 1000;
8874
+ for (const [sid, a] of financeState.agents) {
8875
+ if (!a || !engine || engine.isBusy(sid)) continue;
8876
+ clearTimeout(a.timer);
8877
+ a.timer = setTimeout(() => { try { finAgentRound(String(sid)); } catch {} }, iv);
8878
+ }
8879
+ }
8861
8880
  if (p.maxLot !== undefined) f.maxLot = Math.max(0.01, Math.min(100, Number(p.maxLot) || 0.1));
8862
8881
  if (p.maxPositions !== undefined) f.maxPositions = Math.max(1, Math.min(20, Math.round(Number(p.maxPositions) || 3)));
8863
8882
  /* allowTrading artık AYARLANMAZ — daima true (finCfg zorlar) */
@@ -167,7 +167,7 @@
167
167
  <span>Model</span>
168
168
  <select id="finTraderModel" title="Trader ajanının modeli — farklı API/model seçilebilir"></select>
169
169
  </div>
170
- <div class="fin-grid2">
170
+ <div class="fin-grid2" title="Değişiklik anında kaydedilir — ajanı DURDURMADAN sonraki tura uygulanır">
171
171
  <div class="fin-field">
172
172
  <span>Tur (sn)</span>
173
173
  <input id="finInterval" type="number" min="30" max="3600" step="10" />
@@ -8949,17 +8949,7 @@ function finRenderSymbols(list) {
8949
8949
  row.innerHTML =
8950
8950
  '<span class="fs-name">' + (s.symbol || '?') + '</span>' +
8951
8951
  '<span class="fs-price ' + cls + '">' + bid.toFixed(digits) + '</span>' +
8952
- '<span class="fs-spread">sp ' + (s.spread != null ? s.spread : '—') + '</span>' +
8953
- '<button class="fs-agent" title="' + escapeHtml(s.symbol || '') + ' için AYRI finance ajanı başlat (paralel koşar)">&#9654;&#xFE0E;</button>';
8954
- const spawnBtn = row.querySelector('.fs-agent');
8955
- if (spawnBtn) {
8956
- spawnBtn.addEventListener('click', async (e) => {
8957
- e.stopPropagation();
8958
- const r = await beast.financeAgentSpawn(s.symbol).catch((err) => ({ ok: false, error: String((err && err.message) || err) }));
8959
- if (r && r.ok) toast(s.symbol + ' için ajan başladı — Paralel Ajanlar panelinde izle');
8960
- else toast((r && r.error) || 'Ajan başlatılamadı');
8961
- });
8962
- }
8952
+ '<span class="fs-spread">sp ' + (s.spread != null ? s.spread : '—') + '</span>';
8963
8953
  els.finSymList.appendChild(row);
8964
8954
  }
8965
8955
  }
@@ -9210,8 +9200,18 @@ function finSaveCfg(patch) {
9210
9200
  beast.financeSettings(patch).then(() => { finWatchDirty = false; }).catch(() => { finWatchDirty = false; });
9211
9201
  }, 400);
9212
9202
  }
9213
- if (els.finInterval) els.finInterval.addEventListener('change', () => finSaveCfg({ intervalSec: Number(els.finInterval.value) || 120 }));
9214
- if (els.finMaxLot) els.finMaxLot.addEventListener('change', () => finSaveCfg({ maxLot: Number(els.finMaxLot.value) || 0.1 }));
9203
+ if (els.finInterval) els.finInterval.addEventListener('change', () => {
9204
+ const v = Math.max(30, Math.min(3600, Math.round(Number(els.finInterval.value) || 120)));
9205
+ els.finInterval.value = v;
9206
+ finSaveCfg({ intervalSec: v });
9207
+ toast('Tur aralığı: ' + v + ' sn — durdurmadan sonraki tura uygulanır');
9208
+ });
9209
+ if (els.finMaxLot) els.finMaxLot.addEventListener('change', () => {
9210
+ const v = Math.max(0.01, Math.min(100, Number(els.finMaxLot.value) || 0.1));
9211
+ els.finMaxLot.value = v;
9212
+ finSaveCfg({ maxLot: v });
9213
+ toast('Max lot: ' + v + ' — sonraki turdan itibaren geçerli');
9214
+ });
9215
9215
  if (els.finSymBtn) els.finSymBtn.addEventListener('click', finSymPickerOpen);
9216
9216
  /* OTOMATİK İŞLEM onay kutusu KALDIRILDI — trade ajanı daima işlem açabilir */
9217
9217
  if (els.finTraderModel) {
@@ -9256,11 +9256,18 @@ function finToggleWatch(sym) {
9256
9256
  const i = finWatch.indexOf(s);
9257
9257
  if (i >= 0) finWatch.splice(i, 1);
9258
9258
  else finWatch.push(s);
9259
+ const added = i < 0; /* true = eklendi */
9259
9260
  finSaveCfg({ symbols: [...finWatch] });
9260
9261
  finSymBtnUpdate(); /* TRADE AJANI düğmesi anında güncellensin */
9261
9262
  clearTimeout(finSymRefreshTimer);
9262
9263
  finSymRefreshTimer = setTimeout(() => finSnapshot(), 700); /* PİYASA kartı tazelensin */
9263
- return i < 0; /* true = eklendi */
9264
+ /* canlı geri bildirim: değişiklik koşan ajanı DURDURMADAN sonraki tura girer */
9265
+ toast(
9266
+ added
9267
+ ? s + ' izleme listesine eklendi — koşan ajan sonraki turda kullanır'
9268
+ : s + ' izleme listesinden çıkarıldı — koşan ajan sonraki turda görmez'
9269
+ );
9270
+ return added;
9264
9271
  }
9265
9272
 
9266
9273
  function finRenderPickRows(rows, q) {
@@ -2290,25 +2290,6 @@ body.browser-open #settingsDialog { width: min(70vw, calc(100vw - var(--bw, 480p
2290
2290
  letter-spacing: 0.4px;
2291
2291
  }
2292
2292
 
2293
- /* PİYASA satırındaki ▶ ajan butonu */
2294
- .fin-sym { position: relative; }
2295
- .fin-sym .fs-agent {
2296
- position: absolute;
2297
- right: 4px;
2298
- top: 50%;
2299
- transform: translateY(-50%);
2300
- border: none;
2301
- background: none;
2302
- color: var(--muted);
2303
- cursor: pointer;
2304
- font-size: 11px;
2305
- padding: 2px 4px;
2306
- border-radius: 4px;
2307
- visibility: hidden;
2308
- }
2309
- .fin-sym:hover .fs-agent { visibility: visible; color: var(--accent); }
2310
- .fin-sym .fs-agent:hover { background: var(--accent-dim); }
2311
-
2312
2293
  /* sembol seçicide bölüm başlıkları (geçmiş / tüm semboller) */
2313
2294
  .fin-sym-sec {
2314
2295
  font-size: 10px;