beast-agent 2.38.4 → 2.40.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 +66 -0
  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 +259 -47
  30. package/src/agent/financetools.js +52 -0
  31. package/src/agent/mt5/BeastFinance.mq5 +427 -0
  32. package/src/agent/mt5/BeastShot.tpl +0 -0
  33. package/src/agent/mt5setup.js +542 -0
  34. package/src/agent/scripts/mt5_bridge.py +112 -0
  35. package/src/agent/seeds/mql5/SKILL.md +27 -2
  36. package/src/agent/seeds/tool-yazma/SKILL.md +6 -4
  37. package/src/main.js +233 -13
  38. package/src/preload.js +1 -0
  39. package/src/renderer/index.html +18 -5
  40. package/src/renderer/renderer.js +170 -37
  41. package/src/renderer/style.css +45 -17
@@ -211,6 +211,11 @@ const els = {
211
211
  finSymAdd: $('#finSymAdd'),
212
212
  finSymOverlay: $('#finSymOverlay'),
213
213
  finSymClose: $('#finSymClose'),
214
+ finTeamOverlay: $('#finTeamOverlay'),
215
+ finTeamClose: $('#finTeamClose'),
216
+ finTeamPick: $('#finTeamPick'),
217
+ finTeamCount: $('#finTeamCount'),
218
+ finSetupBtn: $('#finSetupBtn'),
214
219
  finSkillsBtn: $('#finSkillsBtn'),
215
220
  finSkillsOverlay: $('#finSkillsOverlay'),
216
221
  finSkillsClose: $('#finSkillsClose'),
@@ -5248,9 +5253,17 @@ function dmMsgHtml(m) {
5248
5253
  const who = m.group
5249
5254
  ? dmName(m.fromTitle, m.from)
5250
5255
  : `${dmName(m.fromTitle, m.from)} → ${dmName(m.toTitle, m.to)}`;
5256
+ const rawImg = String(m.image || '');
5257
+ const img = /^data:image\//i.test(rawImg)
5258
+ ? `<img class="dmt-img" src="${escapeHtml(rawImg)}" alt="görsel" loading="lazy">`
5259
+ : m.imageOmitted
5260
+ ? '<div class="dmt-img-note">görsel (bütçe) kaydedilmedi</div>'
5261
+ : '';
5251
5262
  return (
5252
5263
  `<div class="dmt-msg"><span class="dm-who">${who}</span>` +
5253
- `${escapeHtml(String(m.text || ''))}<span class="dm-at">${dmTime(m.at)}</span></div>`
5264
+ `${escapeHtml(String(m.text || ''))}` +
5265
+ img +
5266
+ `<span class="dm-at">${dmTime(m.at)}</span></div>`
5254
5267
  );
5255
5268
  }
5256
5269
 
@@ -5783,6 +5796,8 @@ function onEvent(ev) {
5783
5796
  toTitle: ev.toTitle,
5784
5797
  topic: ev.topic,
5785
5798
  text: ev.text,
5799
+ ...(ev.image ? { image: ev.image } : {}),
5800
+ ...(ev.imageOmitted ? { imageOmitted: true } : {}),
5786
5801
  ...(ev.group ? { group: ev.group, groupTitle: ev.groupTitle } : {}),
5787
5802
  ...(ev.closed ? { closed: true, closedAt: ev.closedAt } : {}),
5788
5803
  };
@@ -9357,15 +9372,31 @@ function finTraderInputsSet(cfg) {
9357
9372
  if (els.finTraderModel && ae !== els.finTraderModel && cfg.traderSel) els.finTraderModel.value = cfg.traderSel;
9358
9373
  }
9359
9374
 
9360
- /* ANALİZ EKİBİ: SADECE SAYI seçilir — rolleri sistem otomatik atar
9361
- (FIN_ROLES_AUTO sırası: Teknik → Risk → Haber). Elle rol kutucukları
9362
- kaldırıldı; analysisAuto sunucuda daima açık. Katalog sunucudan gelir. */
9375
+ /* ANALİZ EKİBİ: tek satır çoklu seçim picker'ı — hangi uzman ajanların
9376
+ koşacağını seçersin (Risk / Teknik / Haber / Görsel); sayaç rozeti seçili
9377
+ ajan sayısını gösterir. Katalog sunucudan gelir (finance:state roles). */
9378
+ /* Ekip düğmesi ikonu: emoji yerine çizgi SVG (beyin) — tema rengiyle uyumlu */
9379
+ const FIN_TEAM_SVG =
9380
+ '<svg viewBox="0 0 24 24" width="12" height="12" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px">' +
9381
+ '<path d="M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z"/>' +
9382
+ '<path d="M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z"/>' +
9383
+ '<path d="M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4"/>' +
9384
+ '<path d="M17.599 6.5a3 3 0 0 0 .399-1.375"/>' +
9385
+ '<path d="M6.003 5.125A3 3 0 0 0 6.401 6.5"/>' +
9386
+ '<path d="M3.477 10.896a4 4 0 0 1 .585-.396"/>' +
9387
+ '<path d="M19.938 10.5a4 4 0 0 1 .585.396"/>' +
9388
+ '<path d="M6 18a4 4 0 0 1-1.967-.516"/>' +
9389
+ '<path d="M19.967 17.484A4 4 0 0 1 18 18"/></svg>';
9390
+ function finTeamBtnPaint(btn, n) {
9391
+ if (btn) btn.innerHTML = FIN_TEAM_SVG + '<span>Ekip: ' + n + ' ajan</span>';
9392
+ }
9363
9393
  let finRolesCatalog = [
9364
9394
  { id: 'risk', label: 'Risk Ajanı', desc: 'marj/kaldıraç/SL disiplini, exposure ve günlük kayıp hızı denetimi' },
9365
9395
  { id: 'technic', label: 'Teknik Analiz', desc: 'trend/yapı/destek-direnç/momentum okuma, AL-SAT-BEKLE önerileri' },
9366
9396
  { id: 'macro', label: 'Haber / Makro', desc: 'haber akışı + ekonomik takvim, DXY/emtia bağıntıları, yön eğilimi' },
9397
+ { id: 'visual', label: 'Görsel Ajan', desc: 'MT5 grafiği/ekran görüntüsü — trend, formasyon, seviye ve mum yapısını görsel doğrulama' },
9367
9398
  ];
9368
- let finRolesAuto = ['technic', 'risk', 'macro'];
9399
+ let finRolesAuto = ['technic', 'risk', 'macro', 'visual'];
9369
9400
  let finRolesDirty = false; /* tık→kaydet arası snapshot ezmesin */
9370
9401
  let finRolesSyncTimer = null;
9371
9402
 
@@ -9374,45 +9405,93 @@ function finRoleLabel(id) {
9374
9405
  return d ? d.label : String(id || '');
9375
9406
  }
9376
9407
 
9408
+ /* Etkin ekip listesi: oto modda ilk N rol, elle modda seçilen roller */
9409
+ function finTeamSelectedIds(cfg) {
9410
+ const c = cfg || finCfgCache || {};
9411
+ if (c.analysisAuto !== false) {
9412
+ const n = Math.max(0, Math.min((finRolesAuto || []).length || 4, Math.round(Number(c.analysisCount) || 0)));
9413
+ return (finRolesAuto || []).slice(0, n);
9414
+ }
9415
+ return (Array.isArray(c.analysisTeam) ? c.analysisTeam : []).filter((id) =>
9416
+ (finRolesCatalog || []).some((d) => d.id === id)
9417
+ );
9418
+ }
9419
+
9420
+ /* tek satır: buton (seçili sayı) + seçili rol adları özeti */
9377
9421
  function finRenderRoles(cfg) {
9378
9422
  const box = els.finRoles;
9379
9423
  if (!box) return;
9380
9424
  if (finRolesDirty) return; /* bekleyen kullanıcı değişikliği korunur */
9381
- const max = Math.max(1, (finRolesAuto || []).length || 3);
9382
- const count = Math.max(0, Math.min(max, Math.round(Number(cfg && cfg.analysisCount) || 0)));
9425
+ const selected = finTeamSelectedIds(cfg);
9383
9426
  box.innerHTML = '';
9384
9427
  const wrap = document.createElement('div');
9385
9428
  wrap.className = 'fin-team';
9386
- const cnt = document.createElement('input');
9387
- cnt.type = 'number';
9388
- cnt.className = 'fin-role-count';
9389
- cnt.min = '0';
9390
- cnt.max = String(max);
9391
- cnt.step = '1';
9392
- cnt.value = String(count);
9393
- cnt.title = 'Kaç uzman ajan koşacak (0 = ekip yok, en fazla ' + max + '). Roller otomatik atanır.';
9429
+ const btn = document.createElement('button');
9430
+ btn.type = 'button';
9431
+ btn.className = 'fin-sym-select fin-team-btn';
9432
+ finTeamBtnPaint(btn, selected.length);
9433
+ btn.title = 'Uzman ajanları çoktan seç — seçilen her rol AYRI sürekli ajan olarak koşar (işlem açmaz)';
9394
9434
  const hint = document.createElement('span');
9395
9435
  hint.className = 'fin-team-hint';
9396
- const names = (n) => finRolesAuto.slice(0, n).map(finRoleLabel);
9397
- const paint = (n) => {
9398
- hint.textContent = n > 0 ? 'otomatik: ' + names(n).join(' · ') : 'ekip kapalı — sadece trader koşar';
9399
- };
9400
- cnt.addEventListener('change', () => {
9401
- const n = Math.max(0, Math.min(max, Math.round(Number(cnt.value) || 0)));
9402
- cnt.value = String(n);
9403
- finRolesDirty = true;
9404
- finSaveCfg({ analysisAuto: true, analysisCount: n });
9405
- paint(n);
9406
- toast(n ? 'Analiz ekibi: ' + n + ' ajan — ' + names(n).join(', ') : 'Analiz ekibi kapatıldı');
9407
- clearTimeout(finRolesSyncTimer);
9408
- finRolesSyncTimer = setTimeout(() => { finRolesDirty = false; finSnapshot(); }, 900);
9409
- });
9410
- paint(count);
9411
- wrap.appendChild(cnt);
9436
+ hint.textContent = selected.length
9437
+ ? ((cfg && cfg.analysisAuto !== false) ? 'oto: ' : '') + selected.map(finRoleLabel).join(', ')
9438
+ : 'ekip kapalı — sadece trader koşar';
9439
+ btn.addEventListener('click', finTeamPickerOpen);
9440
+ wrap.appendChild(btn);
9412
9441
  wrap.appendChild(hint);
9413
9442
  box.appendChild(wrap);
9414
9443
  }
9415
9444
 
9445
+ /* picker modalı: çoklu checkbox listesi — her değişiklik ANINDA kaydedilir */
9446
+ function finTeamPickerPaint() {
9447
+ const pick = els.finTeamPick;
9448
+ if (!pick) return;
9449
+ const sel = new Set(finTeamSelectedIds());
9450
+ if (els.finTeamCount) els.finTeamCount.textContent = sel.size ? sel.size + ' seçili' : 'kapalı';
9451
+ pick.innerHTML = '';
9452
+ for (const d of finRolesCatalog || []) {
9453
+ const row = document.createElement('label');
9454
+ row.className = 'fin-team-item';
9455
+ row.title = d.desc || '';
9456
+ const cb = document.createElement('input');
9457
+ cb.type = 'checkbox';
9458
+ cb.checked = sel.has(d.id);
9459
+ cb.dataset.role = d.id;
9460
+ cb.addEventListener('change', () => {
9461
+ const ids = [...pick.querySelectorAll('input[data-role]')].filter((x) => x.checked).map((x) => x.dataset.role);
9462
+ finRolesDirty = true;
9463
+ finCfgCache = finCfgCache || {};
9464
+ finCfgCache.analysisAuto = false;
9465
+ finCfgCache.analysisTeam = ids;
9466
+ finSaveCfg({ analysisAuto: false, analysisTeam: ids });
9467
+ if (els.finTeamCount) els.finTeamCount.textContent = ids.length ? ids.length + ' seçili' : 'kapalı';
9468
+ const btn = els.finRoles && els.finRoles.querySelector('.fin-team-btn');
9469
+ const hint = els.finRoles && els.finRoles.querySelector('.fin-team-hint');
9470
+ finTeamBtnPaint(btn, ids.length);
9471
+ if (hint) hint.textContent = ids.length ? ids.map(finRoleLabel).join(', ') : 'ekip kapalı — sadece trader koşar';
9472
+ toast(ids.length ? 'Analiz ekibi: ' + ids.length + ' ajan — ' + ids.map(finRoleLabel).join(', ') : 'Analiz ekibi kapatıldı');
9473
+ clearTimeout(finRolesSyncTimer);
9474
+ finRolesSyncTimer = setTimeout(() => { finRolesDirty = false; finSnapshot(); }, 900);
9475
+ });
9476
+ const txt = document.createElement('span');
9477
+ txt.className = 'fin-team-txt';
9478
+ txt.innerHTML = '<b>' + escapeHtml(d.label) + '</b><i>' + escapeHtml(d.desc || '') + '</i>';
9479
+ row.appendChild(cb);
9480
+ row.appendChild(txt);
9481
+ pick.appendChild(row);
9482
+ }
9483
+ }
9484
+
9485
+ function finTeamPickerOpen() {
9486
+ if (!els.finTeamOverlay) return;
9487
+ finTeamPickerPaint();
9488
+ els.finTeamOverlay.hidden = false;
9489
+ }
9490
+
9491
+ function finTeamPickerClose() {
9492
+ if (els.finTeamOverlay) els.finTeamOverlay.hidden = true;
9493
+ }
9494
+
9416
9495
  function finRenderTrader(trader, cfg) {
9417
9496
  if (!els.finTraderBtn) return;
9418
9497
  const on = !!(trader && trader.on);
@@ -9966,8 +10045,11 @@ function finAdvPaint() {
9966
10045
  const on = (() => { try { return localStorage.getItem(finAdvKey) === '1'; } catch { return false; } })();
9967
10046
  if (els.finAdvWrap) els.finAdvWrap.hidden = !on;
9968
10047
  if (els.finAdvToggle) {
9969
- els.finAdvToggle.textContent = (on ? '\u25BE' : '\u25B8') + ' Gelişmiş';
10048
+ els.finAdvToggle.classList.toggle('on', on);
9970
10049
  els.finAdvToggle.setAttribute('aria-expanded', on ? 'true' : 'false');
10050
+ els.finAdvToggle.title = on
10051
+ ? 'Gelişmiş açık — disiplin kuralları + shadow mod (kapat)'
10052
+ : 'Gelişmiş — disiplin kuralları + shadow mod';
9971
10053
  }
9972
10054
  }
9973
10055
  if (els.finAdvToggle) {
@@ -10049,6 +10131,20 @@ if (els.finModelRefreshBtn) {
10049
10131
  }
10050
10132
  });
10051
10133
  }
10134
+ if (els.finSetupBtn) {
10135
+ els.finSetupBtn.addEventListener('click', async () => {
10136
+ els.finSetupBtn.disabled = true;
10137
+ const r = await beast.financeMt5Setup().catch((e) => ({ ok: false, error: String((e && e.message) || e) }));
10138
+ els.finSetupBtn.disabled = false;
10139
+ if (r && r.ok) {
10140
+ toast(r.changed
10141
+ ? 'MT5 kurulumu uygulandı' + (r.restartRequired ? ' — MT5 yeniden başlatılınca etkin' : '')
10142
+ : 'MT5 kurulumu zaten güncel');
10143
+ } else {
10144
+ toast('MT5 kurulumu: ' + ((r && r.error) || 'başarısız'));
10145
+ }
10146
+ });
10147
+ }
10052
10148
  if (els.finTraderBtn) {
10053
10149
  els.finTraderBtn.addEventListener('click', async () => {
10054
10150
  if (els.finTraderBtn.classList.contains('stop')) {
@@ -10060,8 +10156,12 @@ if (els.finTraderBtn) {
10060
10156
  else if (r && r.ok) {
10061
10157
  const cfg = (await beast.financeState().catch(() => null));
10062
10158
  const c = (cfg && cfg.cfg) || {};
10063
- const team = Math.round(Number(c.analysisCount) || 0);
10159
+ const team = c.analysisAuto === false
10160
+ ? (Array.isArray(c.analysisTeam) ? c.analysisTeam.length : 0)
10161
+ : Math.round(Number(c.analysisCount) || 0);
10064
10162
  toast(team ? 'Trade ajanı + analiz ekibi (' + team + ' uzman) başladı — turlar panelde izlenir' : 'Trade ajanı başladı — turlar panelde izlenir');
10163
+ /* ajanlar arası konuşma için AJAN DM konsolu da açılır */
10164
+ try { toggleDmRail(false); } catch {}
10065
10165
  }
10066
10166
  }
10067
10167
  finSnapshot();
@@ -10228,7 +10328,7 @@ function finRenderSkills() {
10228
10328
  const map = cfg.roleSkills && typeof cfg.roleSkills === 'object' ? cfg.roleSkills : {};
10229
10329
  /* ANA KARAR VERİCİ (trader) da bir satır: playbook skill'i zorunlu tek seçim */
10230
10330
  const roles = [
10231
- { id: 'trader', label: 'TRADER (Ana Karar Verici)', desc: 'playbook: hangi setup\'lar serbest, giriş/çıkış/iptal kuralları, seans ve risk disiplini — asıl karar vericinin zorunlu skill\'i' },
10331
+ { id: 'trader', label: 'TRADER (Ana Karar Verici)', desc: 'playbook: hangi setup\'lar serbest, giriş/çıkış/iptal kuralları, seans ve risk disiplini — asıl karar vericinin skill\'i (boş = ajan kendi seçer)' },
10232
10332
  ].concat(Array.isArray(finRolesCatalog) ? finRolesCatalog : []);
10233
10333
  box.innerHTML = '';
10234
10334
  if (!roles.length) {
@@ -10249,10 +10349,34 @@ function finRenderSkills() {
10249
10349
  '<span>' + escapeHtml(String(r.desc || '').slice(0, 110)) + '</span>';
10250
10350
  const cur = Array.isArray(map[r.id]) ? map[r.id].map((x) => String(x || '').trim()).filter(Boolean) : [];
10251
10351
  const active = cur.length ? cur[0] : '';
10352
+ /* ÇÖP: rolün skill atamasını kaldır — boş bırakmak da geçerli bir seçim
10353
+ (o zaman ajan skill'i göreve göre SKILLS kataloğundan kendi seçer) */
10354
+ const clearBtn = document.createElement('button');
10355
+ clearBtn.type = 'button';
10356
+ clearBtn.className = 'fin-skill-clear';
10357
+ clearBtn.title = active
10358
+ ? 'Skill atamasını kaldır (' + active + ') — boş kalırsa ajan göreve göre kendi seçer'
10359
+ : 'Atama yok — boş bırakılabilir';
10360
+ clearBtn.innerHTML =
10361
+ '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px"><path d="M3 6h18"/><path d="M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6"/><path d="M14 11v6"/></svg>';
10362
+ clearBtn.addEventListener('click', (e) => {
10363
+ e.preventDefault();
10364
+ e.stopPropagation();
10365
+ const was = active;
10366
+ finCfgCache = finCfgCache || {};
10367
+ finCfgCache.roleSkills = finCfgCache.roleSkills || {};
10368
+ finCfgCache.roleSkills[r.id] = [];
10369
+ finSaveCfg({ roleSkills: { [r.id]: [] } });
10370
+ toast(was
10371
+ ? (r.label || r.id) + ' → ' + was + ' ataması kaldırıldı — ajan göreve göre kendi seçer'
10372
+ : (r.label || r.id) + ' → atama zaten boş');
10373
+ finRenderSkills();
10374
+ });
10375
+ head.appendChild(clearBtn);
10252
10376
  if (!active) {
10253
10377
  const warn = document.createElement('span');
10254
10378
  warn.className = 'fin-skill-req';
10255
- warn.textContent = 'ZORUNLU — skill seçilmedi';
10379
+ warn.textContent = 'atama yok — ajan göreve göre kendi seçer';
10256
10380
  head.appendChild(warn);
10257
10381
  }
10258
10382
  row.appendChild(head);
@@ -10267,7 +10391,7 @@ function finRenderSkills() {
10267
10391
  cb.type = 'radio';
10268
10392
  cb.name = 'fin-skill-role-' + r.id;
10269
10393
  cb.checked = on;
10270
- /* TEK + ZORUNLU: yeni skill seçilir; mevcut seçim kaldırılamaz */
10394
+ /* TEK seçim: yeni skill seçilir; kaldırmak için çöp ikonu kullanılır */
10271
10395
  cb.addEventListener('change', () => {
10272
10396
  if (!cb.checked) return;
10273
10397
  const next = [s.name];
@@ -10280,7 +10404,7 @@ function finRenderSkills() {
10280
10404
  const w = head.querySelector('.fin-skill-req');
10281
10405
  if (w) w.remove();
10282
10406
  finSaveCfg({ roleSkills: { [r.id]: next } });
10283
- toast((r.label || r.id) + ' → ' + s.name + ' (zorunlu tek skill)');
10407
+ toast((r.label || r.id) + ' → ' + s.name + ' (tek skill)');
10284
10408
  });
10285
10409
  chip.appendChild(cb);
10286
10410
  chip.appendChild(document.createTextNode(s.name));
@@ -10335,6 +10459,15 @@ if (els.finSymOverlay) {
10335
10459
  if (e.key === 'Escape') { e.stopPropagation(); finSymPickerClose(); }
10336
10460
  });
10337
10461
  }
10462
+ if (els.finTeamClose) els.finTeamClose.addEventListener('click', finTeamPickerClose);
10463
+ if (els.finTeamOverlay) {
10464
+ els.finTeamOverlay.addEventListener('click', (e) => {
10465
+ if (e.target === els.finTeamOverlay) finTeamPickerClose();
10466
+ });
10467
+ els.finTeamOverlay.addEventListener('keydown', (e) => {
10468
+ if (e.key === 'Escape') { e.stopPropagation(); finTeamPickerClose(); }
10469
+ });
10470
+ }
10338
10471
  if (els.finSymSearch) {
10339
10472
  els.finSymSearch.addEventListener('input', () => {
10340
10473
  clearTimeout(finSymSearchTimer);
@@ -2224,6 +2224,21 @@ body.browser-open #settingsDialog { width: min(70vw, calc(100vw - var(--bw, 480p
2224
2224
  color: var(--muted);
2225
2225
  margin-top: 2px;
2226
2226
  }
2227
+ /* ajan DM görseli (mt5_shot / ekran görüntüsü paylaşımı) */
2228
+ .dmt-msg .dmt-img {
2229
+ display: block;
2230
+ max-width: 100%;
2231
+ max-height: 260px;
2232
+ border-radius: 6px;
2233
+ margin-top: 5px;
2234
+ border: 1px solid var(--border, rgba(255,255,255,0.12));
2235
+ }
2236
+ .dmt-msg .dmt-img-note {
2237
+ font-size: 10px;
2238
+ color: var(--muted);
2239
+ font-style: italic;
2240
+ margin-top: 3px;
2241
+ }
2227
2242
  /* ajan adının yanındaki KOD rozeti (oturum id) */
2228
2243
  .dm-code {
2229
2244
  font-size: 9px; font-weight: 700; letter-spacing: 0.5px;
@@ -4875,20 +4890,6 @@ body.finance-mode #composerWrap { margin-right: var(--finW, 400px); }
4875
4890
  .fin-field input:focus, .fin-field select:focus, .fin-field textarea:focus { border-color: var(--accent); outline: none; }
4876
4891
  .fin-time-row { display: flex; gap: 6px; }
4877
4892
  .fin-time-row input { flex: 1; min-width: 0; }
4878
- .fin-adv-toggle {
4879
- display: block;
4880
- width: 100%;
4881
- text-align: left;
4882
- background: none;
4883
- border: none;
4884
- color: var(--muted);
4885
- font-size: 10px;
4886
- font-weight: 800;
4887
- letter-spacing: 0.6px;
4888
- padding: 2px 0 8px;
4889
- cursor: pointer;
4890
- }
4891
- .fin-adv-toggle:hover { color: var(--accent); }
4892
4893
  /* Ajan talimatı: çok satırlı not alanı (dikey büyütülebilir) */
4893
4894
  .fin-field textarea {
4894
4895
  resize: vertical;
@@ -4926,6 +4927,17 @@ body.finance-mode #composerWrap { margin-right: var(--finW, 400px); }
4926
4927
  .fin-alert .fa-note { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
4927
4928
  /* ekib sayısı + otomatik atama özeti */
4928
4929
  .fin-team { display: flex; align-items: center; gap: 8px; min-width: 0; }
4930
+ .fin-team-btn { font-weight: 600; display: inline-flex; align-items: center; gap: 5px; }
4931
+ .fin-team-item {
4932
+ display: flex; align-items: flex-start; gap: 8px;
4933
+ padding: 6px 8px; border-radius: 6px;
4934
+ cursor: pointer;
4935
+ }
4936
+ .fin-team-item:hover { background: var(--panel2); }
4937
+ .fin-team-item input { flex: none; width: auto; margin: 2px 0 0 0; }
4938
+ .fin-team-txt { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
4939
+ .fin-team-txt b { font-size: 12px; color: var(--text); }
4940
+ .fin-team-txt i { font-size: 10.5px; font-style: normal; color: var(--muted); }
4929
4941
  .fin-team-hint {
4930
4942
  flex: 1;
4931
4943
  min-width: 0;
@@ -5030,10 +5042,11 @@ body.finance-mode #composerWrap { margin-right: var(--finW, 400px); }
5030
5042
  .fin-start:hover { filter: brightness(1.08); box-shadow: 0 1px 6px rgba(0, 0, 0, 0.22); }
5031
5043
  .fin-start:active { transform: translateY(1px); filter: brightness(0.96); }
5032
5044
  .fin-start.stop {
5033
- background: #ef4444;
5034
- border-color: #ef4444;
5045
+ background: #b91c1c;
5046
+ border-color: #b91c1c;
5035
5047
  color: #fff; /* kırmızı zeminde beyaz her iki temada da okunur */
5036
5048
  }
5049
+ .fin-start.stop:hover { background: #991b1b; border-color: #991b1b; }
5037
5050
 
5038
5051
  /* TRADE AJANI kartı — vurgulu görünüm (accent çerçeve + yumuşak zemin) */
5039
5052
  .fin-card-trader {
@@ -5148,6 +5161,7 @@ body.finance-mode #composerWrap { margin-right: var(--finW, 400px); }
5148
5161
  border-radius: 5px;
5149
5162
  }
5150
5163
  .fin-card-title button:hover { background: var(--accent-dim); color: var(--accent); }
5164
+ .fin-card-title button.on { background: var(--accent-dim); color: var(--accent); }
5151
5165
 
5152
5166
  /* MT5 sembol seçici modalı */
5153
5167
  .fin-sym-dialog { width: 460px; max-width: calc(100vw - 40px); }
@@ -5233,6 +5247,7 @@ body.finance-mode #composerWrap { margin-right: var(--finW, 400px); }
5233
5247
  gap: 10px;
5234
5248
  }
5235
5249
  .fin-skill-role {
5250
+ position: relative;
5236
5251
  border: 1px solid var(--border);
5237
5252
  border-radius: 8px;
5238
5253
  padding: 8px 9px;
@@ -5241,13 +5256,26 @@ body.finance-mode #composerWrap { margin-right: var(--finW, 400px); }
5241
5256
  .fin-skill-role-head { display: flex; flex-direction: column; gap: 1px; margin-bottom: 7px; }
5242
5257
  .fin-skill-role-head b { font-size: 11.5px; color: var(--text); }
5243
5258
  .fin-skill-role-head span { font-size: 10px; color: var(--muted); }
5259
+ .fin-skill-clear {
5260
+ position: absolute;
5261
+ top: 6px;
5262
+ right: 6px;
5263
+ background: none;
5264
+ border: none;
5265
+ color: var(--muted);
5266
+ line-height: 0;
5267
+ padding: 3px 5px;
5268
+ border-radius: 6px;
5269
+ cursor: pointer;
5270
+ }
5271
+ .fin-skill-clear:hover { color: #ef4444; background: var(--accent-dim); }
5244
5272
  .fin-skill-req {
5245
5273
  align-self: flex-start;
5246
5274
  margin-top: 2px;
5247
5275
  font-size: 9.5px;
5248
5276
  font-weight: 800;
5249
5277
  letter-spacing: 0.5px;
5250
- color: #ef4444;
5278
+ color: var(--muted);
5251
5279
  }
5252
5280
  .fin-skill-chips { display: flex; flex-wrap: wrap; gap: 4px; }
5253
5281
  .fin-skill-chip {