beast-agent 2.38.3 → 2.39.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.
- package/package.json +1 -1
- package/src/agent/bots.js +66 -0
- package/src/agent/customtools.js +1 -1
- package/src/agent/engine.js +222 -45
- package/src/agent/financetools.js +52 -0
- package/src/agent/mt5/BeastFinance.mq5 +290 -0
- package/src/agent/mt5setup.js +520 -0
- package/src/agent/scripts/mt5_bridge.py +112 -0
- package/src/agent/seeds/mql5/SKILL.md +25 -2
- package/src/agent/seeds/tool-yazma/SKILL.md +6 -4
- package/src/main.js +232 -12
- package/src/preload.js +1 -0
- package/src/renderer/index.html +20 -4
- package/src/renderer/renderer.js +178 -35
- package/src/renderer/style.css +30 -3
package/src/renderer/renderer.js
CHANGED
|
@@ -194,6 +194,8 @@ const els = {
|
|
|
194
194
|
finPlanTime: $('#finPlanTime'),
|
|
195
195
|
finReviewTime: $('#finReviewTime'),
|
|
196
196
|
finShadow: $('#finShadow'),
|
|
197
|
+
finAdvWrap: $('#finAdvWrap'),
|
|
198
|
+
finAdvToggle: $('#finAdvToggle'),
|
|
197
199
|
finSymBtn: $('#finSymBtn'),
|
|
198
200
|
finRoles: $('#finRoles'),
|
|
199
201
|
finWatchClear: $('#finWatchClear'),
|
|
@@ -209,6 +211,11 @@ const els = {
|
|
|
209
211
|
finSymAdd: $('#finSymAdd'),
|
|
210
212
|
finSymOverlay: $('#finSymOverlay'),
|
|
211
213
|
finSymClose: $('#finSymClose'),
|
|
214
|
+
finTeamOverlay: $('#finTeamOverlay'),
|
|
215
|
+
finTeamClose: $('#finTeamClose'),
|
|
216
|
+
finTeamPick: $('#finTeamPick'),
|
|
217
|
+
finTeamCount: $('#finTeamCount'),
|
|
218
|
+
finSetupBtn: $('#finSetupBtn'),
|
|
212
219
|
finSkillsBtn: $('#finSkillsBtn'),
|
|
213
220
|
finSkillsOverlay: $('#finSkillsOverlay'),
|
|
214
221
|
finSkillsClose: $('#finSkillsClose'),
|
|
@@ -9355,15 +9362,31 @@ function finTraderInputsSet(cfg) {
|
|
|
9355
9362
|
if (els.finTraderModel && ae !== els.finTraderModel && cfg.traderSel) els.finTraderModel.value = cfg.traderSel;
|
|
9356
9363
|
}
|
|
9357
9364
|
|
|
9358
|
-
/* ANALİZ EKİBİ:
|
|
9359
|
-
(
|
|
9360
|
-
|
|
9365
|
+
/* ANALİZ EKİBİ: tek satır çoklu seçim picker'ı — hangi uzman ajanların
|
|
9366
|
+
koşacağını seçersin (Risk / Teknik / Haber / Görsel); sayaç rozeti seçili
|
|
9367
|
+
ajan sayısını gösterir. Katalog sunucudan gelir (finance:state roles). */
|
|
9368
|
+
/* Ekip düğmesi ikonu: emoji yerine çizgi SVG (beyin) — tema rengiyle uyumlu */
|
|
9369
|
+
const FIN_TEAM_SVG =
|
|
9370
|
+
'<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">' +
|
|
9371
|
+
'<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"/>' +
|
|
9372
|
+
'<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"/>' +
|
|
9373
|
+
'<path d="M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4"/>' +
|
|
9374
|
+
'<path d="M17.599 6.5a3 3 0 0 0 .399-1.375"/>' +
|
|
9375
|
+
'<path d="M6.003 5.125A3 3 0 0 0 6.401 6.5"/>' +
|
|
9376
|
+
'<path d="M3.477 10.896a4 4 0 0 1 .585-.396"/>' +
|
|
9377
|
+
'<path d="M19.938 10.5a4 4 0 0 1 .585.396"/>' +
|
|
9378
|
+
'<path d="M6 18a4 4 0 0 1-1.967-.516"/>' +
|
|
9379
|
+
'<path d="M19.967 17.484A4 4 0 0 1 18 18"/></svg>';
|
|
9380
|
+
function finTeamBtnPaint(btn, n) {
|
|
9381
|
+
if (btn) btn.innerHTML = FIN_TEAM_SVG + '<span>Ekip: ' + n + ' ajan</span>';
|
|
9382
|
+
}
|
|
9361
9383
|
let finRolesCatalog = [
|
|
9362
9384
|
{ id: 'risk', label: 'Risk Ajanı', desc: 'marj/kaldıraç/SL disiplini, exposure ve günlük kayıp hızı denetimi' },
|
|
9363
9385
|
{ id: 'technic', label: 'Teknik Analiz', desc: 'trend/yapı/destek-direnç/momentum okuma, AL-SAT-BEKLE önerileri' },
|
|
9364
9386
|
{ id: 'macro', label: 'Haber / Makro', desc: 'haber akışı + ekonomik takvim, DXY/emtia bağıntıları, yön eğilimi' },
|
|
9387
|
+
{ 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' },
|
|
9365
9388
|
];
|
|
9366
|
-
let finRolesAuto = ['technic', 'risk', 'macro'];
|
|
9389
|
+
let finRolesAuto = ['technic', 'risk', 'macro', 'visual'];
|
|
9367
9390
|
let finRolesDirty = false; /* tık→kaydet arası snapshot ezmesin */
|
|
9368
9391
|
let finRolesSyncTimer = null;
|
|
9369
9392
|
|
|
@@ -9372,45 +9395,93 @@ function finRoleLabel(id) {
|
|
|
9372
9395
|
return d ? d.label : String(id || '');
|
|
9373
9396
|
}
|
|
9374
9397
|
|
|
9398
|
+
/* Etkin ekip listesi: oto modda ilk N rol, elle modda seçilen roller */
|
|
9399
|
+
function finTeamSelectedIds(cfg) {
|
|
9400
|
+
const c = cfg || finCfgCache || {};
|
|
9401
|
+
if (c.analysisAuto !== false) {
|
|
9402
|
+
const n = Math.max(0, Math.min((finRolesAuto || []).length || 4, Math.round(Number(c.analysisCount) || 0)));
|
|
9403
|
+
return (finRolesAuto || []).slice(0, n);
|
|
9404
|
+
}
|
|
9405
|
+
return (Array.isArray(c.analysisTeam) ? c.analysisTeam : []).filter((id) =>
|
|
9406
|
+
(finRolesCatalog || []).some((d) => d.id === id)
|
|
9407
|
+
);
|
|
9408
|
+
}
|
|
9409
|
+
|
|
9410
|
+
/* tek satır: buton (seçili sayı) + seçili rol adları özeti */
|
|
9375
9411
|
function finRenderRoles(cfg) {
|
|
9376
9412
|
const box = els.finRoles;
|
|
9377
9413
|
if (!box) return;
|
|
9378
9414
|
if (finRolesDirty) return; /* bekleyen kullanıcı değişikliği korunur */
|
|
9379
|
-
const
|
|
9380
|
-
const count = Math.max(0, Math.min(max, Math.round(Number(cfg && cfg.analysisCount) || 0)));
|
|
9415
|
+
const selected = finTeamSelectedIds(cfg);
|
|
9381
9416
|
box.innerHTML = '';
|
|
9382
9417
|
const wrap = document.createElement('div');
|
|
9383
9418
|
wrap.className = 'fin-team';
|
|
9384
|
-
const
|
|
9385
|
-
|
|
9386
|
-
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
cnt.step = '1';
|
|
9390
|
-
cnt.value = String(count);
|
|
9391
|
-
cnt.title = 'Kaç uzman ajan koşacak (0 = ekip yok, en fazla ' + max + '). Roller otomatik atanır.';
|
|
9419
|
+
const btn = document.createElement('button');
|
|
9420
|
+
btn.type = 'button';
|
|
9421
|
+
btn.className = 'fin-sym-select fin-team-btn';
|
|
9422
|
+
finTeamBtnPaint(btn, selected.length);
|
|
9423
|
+
btn.title = 'Uzman ajanları çoktan seç — seçilen her rol AYRI sürekli ajan olarak koşar (işlem açmaz)';
|
|
9392
9424
|
const hint = document.createElement('span');
|
|
9393
9425
|
hint.className = 'fin-team-hint';
|
|
9394
|
-
|
|
9395
|
-
|
|
9396
|
-
|
|
9397
|
-
|
|
9398
|
-
|
|
9399
|
-
const n = Math.max(0, Math.min(max, Math.round(Number(cnt.value) || 0)));
|
|
9400
|
-
cnt.value = String(n);
|
|
9401
|
-
finRolesDirty = true;
|
|
9402
|
-
finSaveCfg({ analysisAuto: true, analysisCount: n });
|
|
9403
|
-
paint(n);
|
|
9404
|
-
toast(n ? 'Analiz ekibi: ' + n + ' ajan — ' + names(n).join(', ') : 'Analiz ekibi kapatıldı');
|
|
9405
|
-
clearTimeout(finRolesSyncTimer);
|
|
9406
|
-
finRolesSyncTimer = setTimeout(() => { finRolesDirty = false; finSnapshot(); }, 900);
|
|
9407
|
-
});
|
|
9408
|
-
paint(count);
|
|
9409
|
-
wrap.appendChild(cnt);
|
|
9426
|
+
hint.textContent = selected.length
|
|
9427
|
+
? ((cfg && cfg.analysisAuto !== false) ? 'oto: ' : '') + selected.map(finRoleLabel).join(', ')
|
|
9428
|
+
: 'ekip kapalı — sadece trader koşar';
|
|
9429
|
+
btn.addEventListener('click', finTeamPickerOpen);
|
|
9430
|
+
wrap.appendChild(btn);
|
|
9410
9431
|
wrap.appendChild(hint);
|
|
9411
9432
|
box.appendChild(wrap);
|
|
9412
9433
|
}
|
|
9413
9434
|
|
|
9435
|
+
/* picker modalı: çoklu checkbox listesi — her değişiklik ANINDA kaydedilir */
|
|
9436
|
+
function finTeamPickerPaint() {
|
|
9437
|
+
const pick = els.finTeamPick;
|
|
9438
|
+
if (!pick) return;
|
|
9439
|
+
const sel = new Set(finTeamSelectedIds());
|
|
9440
|
+
if (els.finTeamCount) els.finTeamCount.textContent = sel.size ? sel.size + ' seçili' : 'kapalı';
|
|
9441
|
+
pick.innerHTML = '';
|
|
9442
|
+
for (const d of finRolesCatalog || []) {
|
|
9443
|
+
const row = document.createElement('label');
|
|
9444
|
+
row.className = 'fin-team-item';
|
|
9445
|
+
row.title = d.desc || '';
|
|
9446
|
+
const cb = document.createElement('input');
|
|
9447
|
+
cb.type = 'checkbox';
|
|
9448
|
+
cb.checked = sel.has(d.id);
|
|
9449
|
+
cb.dataset.role = d.id;
|
|
9450
|
+
cb.addEventListener('change', () => {
|
|
9451
|
+
const ids = [...pick.querySelectorAll('input[data-role]')].filter((x) => x.checked).map((x) => x.dataset.role);
|
|
9452
|
+
finRolesDirty = true;
|
|
9453
|
+
finCfgCache = finCfgCache || {};
|
|
9454
|
+
finCfgCache.analysisAuto = false;
|
|
9455
|
+
finCfgCache.analysisTeam = ids;
|
|
9456
|
+
finSaveCfg({ analysisAuto: false, analysisTeam: ids });
|
|
9457
|
+
if (els.finTeamCount) els.finTeamCount.textContent = ids.length ? ids.length + ' seçili' : 'kapalı';
|
|
9458
|
+
const btn = els.finRoles && els.finRoles.querySelector('.fin-team-btn');
|
|
9459
|
+
const hint = els.finRoles && els.finRoles.querySelector('.fin-team-hint');
|
|
9460
|
+
finTeamBtnPaint(btn, ids.length);
|
|
9461
|
+
if (hint) hint.textContent = ids.length ? ids.map(finRoleLabel).join(', ') : 'ekip kapalı — sadece trader koşar';
|
|
9462
|
+
toast(ids.length ? 'Analiz ekibi: ' + ids.length + ' ajan — ' + ids.map(finRoleLabel).join(', ') : 'Analiz ekibi kapatıldı');
|
|
9463
|
+
clearTimeout(finRolesSyncTimer);
|
|
9464
|
+
finRolesSyncTimer = setTimeout(() => { finRolesDirty = false; finSnapshot(); }, 900);
|
|
9465
|
+
});
|
|
9466
|
+
const txt = document.createElement('span');
|
|
9467
|
+
txt.className = 'fin-team-txt';
|
|
9468
|
+
txt.innerHTML = '<b>' + escapeHtml(d.label) + '</b><i>' + escapeHtml(d.desc || '') + '</i>';
|
|
9469
|
+
row.appendChild(cb);
|
|
9470
|
+
row.appendChild(txt);
|
|
9471
|
+
pick.appendChild(row);
|
|
9472
|
+
}
|
|
9473
|
+
}
|
|
9474
|
+
|
|
9475
|
+
function finTeamPickerOpen() {
|
|
9476
|
+
if (!els.finTeamOverlay) return;
|
|
9477
|
+
finTeamPickerPaint();
|
|
9478
|
+
els.finTeamOverlay.hidden = false;
|
|
9479
|
+
}
|
|
9480
|
+
|
|
9481
|
+
function finTeamPickerClose() {
|
|
9482
|
+
if (els.finTeamOverlay) els.finTeamOverlay.hidden = true;
|
|
9483
|
+
}
|
|
9484
|
+
|
|
9414
9485
|
function finRenderTrader(trader, cfg) {
|
|
9415
9486
|
if (!els.finTraderBtn) return;
|
|
9416
9487
|
const on = !!(trader && trader.on);
|
|
@@ -9958,6 +10029,27 @@ if (els.finShadow) {
|
|
|
9958
10029
|
: 'Shadow mod kapalı — gerçek emirler aktif');
|
|
9959
10030
|
});
|
|
9960
10031
|
}
|
|
10032
|
+
/* GELİŞMİŞ SEÇENEKLER: disiplin + shadow bloğu varsayılan KAPALI; durum hatırlanır */
|
|
10033
|
+
const finAdvKey = 'beast.financeAdvanced';
|
|
10034
|
+
function finAdvPaint() {
|
|
10035
|
+
const on = (() => { try { return localStorage.getItem(finAdvKey) === '1'; } catch { return false; } })();
|
|
10036
|
+
if (els.finAdvWrap) els.finAdvWrap.hidden = !on;
|
|
10037
|
+
if (els.finAdvToggle) {
|
|
10038
|
+
els.finAdvToggle.classList.toggle('on', on);
|
|
10039
|
+
els.finAdvToggle.setAttribute('aria-expanded', on ? 'true' : 'false');
|
|
10040
|
+
els.finAdvToggle.title = on
|
|
10041
|
+
? 'Gelişmiş açık — disiplin kuralları + shadow mod (kapat)'
|
|
10042
|
+
: 'Gelişmiş — disiplin kuralları + shadow mod';
|
|
10043
|
+
}
|
|
10044
|
+
}
|
|
10045
|
+
if (els.finAdvToggle) {
|
|
10046
|
+
els.finAdvToggle.addEventListener('click', () => {
|
|
10047
|
+
const on = (() => { try { return localStorage.getItem(finAdvKey) === '1'; } catch { return false; } })();
|
|
10048
|
+
try { localStorage.setItem(finAdvKey, on ? '0' : '1'); } catch {}
|
|
10049
|
+
finAdvPaint();
|
|
10050
|
+
});
|
|
10051
|
+
}
|
|
10052
|
+
finAdvPaint();
|
|
9961
10053
|
if (els.finDailyLossAction) {
|
|
9962
10054
|
els.finDailyLossAction.addEventListener('change', () => {
|
|
9963
10055
|
finSaveCfg({ dailyLossAction: els.finDailyLossAction.value });
|
|
@@ -10029,6 +10121,20 @@ if (els.finModelRefreshBtn) {
|
|
|
10029
10121
|
}
|
|
10030
10122
|
});
|
|
10031
10123
|
}
|
|
10124
|
+
if (els.finSetupBtn) {
|
|
10125
|
+
els.finSetupBtn.addEventListener('click', async () => {
|
|
10126
|
+
els.finSetupBtn.disabled = true;
|
|
10127
|
+
const r = await beast.financeMt5Setup().catch((e) => ({ ok: false, error: String((e && e.message) || e) }));
|
|
10128
|
+
els.finSetupBtn.disabled = false;
|
|
10129
|
+
if (r && r.ok) {
|
|
10130
|
+
toast(r.changed
|
|
10131
|
+
? 'MT5 kurulumu uygulandı' + (r.restartRequired ? ' — MT5 yeniden başlatılınca etkin' : '')
|
|
10132
|
+
: 'MT5 kurulumu zaten güncel');
|
|
10133
|
+
} else {
|
|
10134
|
+
toast('MT5 kurulumu: ' + ((r && r.error) || 'başarısız'));
|
|
10135
|
+
}
|
|
10136
|
+
});
|
|
10137
|
+
}
|
|
10032
10138
|
if (els.finTraderBtn) {
|
|
10033
10139
|
els.finTraderBtn.addEventListener('click', async () => {
|
|
10034
10140
|
if (els.finTraderBtn.classList.contains('stop')) {
|
|
@@ -10040,8 +10146,12 @@ if (els.finTraderBtn) {
|
|
|
10040
10146
|
else if (r && r.ok) {
|
|
10041
10147
|
const cfg = (await beast.financeState().catch(() => null));
|
|
10042
10148
|
const c = (cfg && cfg.cfg) || {};
|
|
10043
|
-
const team =
|
|
10149
|
+
const team = c.analysisAuto === false
|
|
10150
|
+
? (Array.isArray(c.analysisTeam) ? c.analysisTeam.length : 0)
|
|
10151
|
+
: Math.round(Number(c.analysisCount) || 0);
|
|
10044
10152
|
toast(team ? 'Trade ajanı + analiz ekibi (' + team + ' uzman) başladı — turlar panelde izlenir' : 'Trade ajanı başladı — turlar panelde izlenir');
|
|
10153
|
+
/* ajanlar arası konuşma için AJAN DM konsolu da açılır */
|
|
10154
|
+
try { toggleDmRail(false); } catch {}
|
|
10045
10155
|
}
|
|
10046
10156
|
}
|
|
10047
10157
|
finSnapshot();
|
|
@@ -10208,7 +10318,7 @@ function finRenderSkills() {
|
|
|
10208
10318
|
const map = cfg.roleSkills && typeof cfg.roleSkills === 'object' ? cfg.roleSkills : {};
|
|
10209
10319
|
/* ANA KARAR VERİCİ (trader) da bir satır: playbook skill'i zorunlu tek seçim */
|
|
10210
10320
|
const roles = [
|
|
10211
|
-
{ 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
|
|
10321
|
+
{ 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)' },
|
|
10212
10322
|
].concat(Array.isArray(finRolesCatalog) ? finRolesCatalog : []);
|
|
10213
10323
|
box.innerHTML = '';
|
|
10214
10324
|
if (!roles.length) {
|
|
@@ -10229,10 +10339,34 @@ function finRenderSkills() {
|
|
|
10229
10339
|
'<span>' + escapeHtml(String(r.desc || '').slice(0, 110)) + '</span>';
|
|
10230
10340
|
const cur = Array.isArray(map[r.id]) ? map[r.id].map((x) => String(x || '').trim()).filter(Boolean) : [];
|
|
10231
10341
|
const active = cur.length ? cur[0] : '';
|
|
10342
|
+
/* ÇÖP: rolün skill atamasını kaldır — boş bırakmak da geçerli bir seçim
|
|
10343
|
+
(o zaman ajan skill'i göreve göre SKILLS kataloğundan kendi seçer) */
|
|
10344
|
+
const clearBtn = document.createElement('button');
|
|
10345
|
+
clearBtn.type = 'button';
|
|
10346
|
+
clearBtn.className = 'fin-skill-clear';
|
|
10347
|
+
clearBtn.title = active
|
|
10348
|
+
? 'Skill atamasını kaldır (' + active + ') — boş kalırsa ajan göreve göre kendi seçer'
|
|
10349
|
+
: 'Atama yok — boş bırakılabilir';
|
|
10350
|
+
clearBtn.innerHTML =
|
|
10351
|
+
'<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>';
|
|
10352
|
+
clearBtn.addEventListener('click', (e) => {
|
|
10353
|
+
e.preventDefault();
|
|
10354
|
+
e.stopPropagation();
|
|
10355
|
+
const was = active;
|
|
10356
|
+
finCfgCache = finCfgCache || {};
|
|
10357
|
+
finCfgCache.roleSkills = finCfgCache.roleSkills || {};
|
|
10358
|
+
finCfgCache.roleSkills[r.id] = [];
|
|
10359
|
+
finSaveCfg({ roleSkills: { [r.id]: [] } });
|
|
10360
|
+
toast(was
|
|
10361
|
+
? (r.label || r.id) + ' → ' + was + ' ataması kaldırıldı — ajan göreve göre kendi seçer'
|
|
10362
|
+
: (r.label || r.id) + ' → atama zaten boş');
|
|
10363
|
+
finRenderSkills();
|
|
10364
|
+
});
|
|
10365
|
+
head.appendChild(clearBtn);
|
|
10232
10366
|
if (!active) {
|
|
10233
10367
|
const warn = document.createElement('span');
|
|
10234
10368
|
warn.className = 'fin-skill-req';
|
|
10235
|
-
warn.textContent = '
|
|
10369
|
+
warn.textContent = 'atama yok — ajan göreve göre kendi seçer';
|
|
10236
10370
|
head.appendChild(warn);
|
|
10237
10371
|
}
|
|
10238
10372
|
row.appendChild(head);
|
|
@@ -10247,7 +10381,7 @@ function finRenderSkills() {
|
|
|
10247
10381
|
cb.type = 'radio';
|
|
10248
10382
|
cb.name = 'fin-skill-role-' + r.id;
|
|
10249
10383
|
cb.checked = on;
|
|
10250
|
-
/* TEK
|
|
10384
|
+
/* TEK seçim: yeni skill seçilir; kaldırmak için çöp ikonu kullanılır */
|
|
10251
10385
|
cb.addEventListener('change', () => {
|
|
10252
10386
|
if (!cb.checked) return;
|
|
10253
10387
|
const next = [s.name];
|
|
@@ -10260,7 +10394,7 @@ function finRenderSkills() {
|
|
|
10260
10394
|
const w = head.querySelector('.fin-skill-req');
|
|
10261
10395
|
if (w) w.remove();
|
|
10262
10396
|
finSaveCfg({ roleSkills: { [r.id]: next } });
|
|
10263
|
-
toast((r.label || r.id) + ' → ' + s.name + ' (
|
|
10397
|
+
toast((r.label || r.id) + ' → ' + s.name + ' (tek skill)');
|
|
10264
10398
|
});
|
|
10265
10399
|
chip.appendChild(cb);
|
|
10266
10400
|
chip.appendChild(document.createTextNode(s.name));
|
|
@@ -10315,6 +10449,15 @@ if (els.finSymOverlay) {
|
|
|
10315
10449
|
if (e.key === 'Escape') { e.stopPropagation(); finSymPickerClose(); }
|
|
10316
10450
|
});
|
|
10317
10451
|
}
|
|
10452
|
+
if (els.finTeamClose) els.finTeamClose.addEventListener('click', finTeamPickerClose);
|
|
10453
|
+
if (els.finTeamOverlay) {
|
|
10454
|
+
els.finTeamOverlay.addEventListener('click', (e) => {
|
|
10455
|
+
if (e.target === els.finTeamOverlay) finTeamPickerClose();
|
|
10456
|
+
});
|
|
10457
|
+
els.finTeamOverlay.addEventListener('keydown', (e) => {
|
|
10458
|
+
if (e.key === 'Escape') { e.stopPropagation(); finTeamPickerClose(); }
|
|
10459
|
+
});
|
|
10460
|
+
}
|
|
10318
10461
|
if (els.finSymSearch) {
|
|
10319
10462
|
els.finSymSearch.addEventListener('input', () => {
|
|
10320
10463
|
clearTimeout(finSymSearchTimer);
|
package/src/renderer/style.css
CHANGED
|
@@ -4912,6 +4912,17 @@ body.finance-mode #composerWrap { margin-right: var(--finW, 400px); }
|
|
|
4912
4912
|
.fin-alert .fa-note { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
4913
4913
|
/* ekib sayısı + otomatik atama özeti */
|
|
4914
4914
|
.fin-team { display: flex; align-items: center; gap: 8px; min-width: 0; }
|
|
4915
|
+
.fin-team-btn { font-weight: 600; display: inline-flex; align-items: center; gap: 5px; }
|
|
4916
|
+
.fin-team-item {
|
|
4917
|
+
display: flex; align-items: flex-start; gap: 8px;
|
|
4918
|
+
padding: 6px 8px; border-radius: 6px;
|
|
4919
|
+
cursor: pointer;
|
|
4920
|
+
}
|
|
4921
|
+
.fin-team-item:hover { background: var(--panel2); }
|
|
4922
|
+
.fin-team-item input { flex: none; width: auto; margin: 2px 0 0 0; }
|
|
4923
|
+
.fin-team-txt { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
|
|
4924
|
+
.fin-team-txt b { font-size: 12px; color: var(--text); }
|
|
4925
|
+
.fin-team-txt i { font-size: 10.5px; font-style: normal; color: var(--muted); }
|
|
4915
4926
|
.fin-team-hint {
|
|
4916
4927
|
flex: 1;
|
|
4917
4928
|
min-width: 0;
|
|
@@ -5016,10 +5027,11 @@ body.finance-mode #composerWrap { margin-right: var(--finW, 400px); }
|
|
|
5016
5027
|
.fin-start:hover { filter: brightness(1.08); box-shadow: 0 1px 6px rgba(0, 0, 0, 0.22); }
|
|
5017
5028
|
.fin-start:active { transform: translateY(1px); filter: brightness(0.96); }
|
|
5018
5029
|
.fin-start.stop {
|
|
5019
|
-
background: #
|
|
5020
|
-
border-color: #
|
|
5030
|
+
background: #b91c1c;
|
|
5031
|
+
border-color: #b91c1c;
|
|
5021
5032
|
color: #fff; /* kırmızı zeminde beyaz her iki temada da okunur */
|
|
5022
5033
|
}
|
|
5034
|
+
.fin-start.stop:hover { background: #991b1b; border-color: #991b1b; }
|
|
5023
5035
|
|
|
5024
5036
|
/* TRADE AJANI kartı — vurgulu görünüm (accent çerçeve + yumuşak zemin) */
|
|
5025
5037
|
.fin-card-trader {
|
|
@@ -5134,6 +5146,7 @@ body.finance-mode #composerWrap { margin-right: var(--finW, 400px); }
|
|
|
5134
5146
|
border-radius: 5px;
|
|
5135
5147
|
}
|
|
5136
5148
|
.fin-card-title button:hover { background: var(--accent-dim); color: var(--accent); }
|
|
5149
|
+
.fin-card-title button.on { background: var(--accent-dim); color: var(--accent); }
|
|
5137
5150
|
|
|
5138
5151
|
/* MT5 sembol seçici modalı */
|
|
5139
5152
|
.fin-sym-dialog { width: 460px; max-width: calc(100vw - 40px); }
|
|
@@ -5219,6 +5232,7 @@ body.finance-mode #composerWrap { margin-right: var(--finW, 400px); }
|
|
|
5219
5232
|
gap: 10px;
|
|
5220
5233
|
}
|
|
5221
5234
|
.fin-skill-role {
|
|
5235
|
+
position: relative;
|
|
5222
5236
|
border: 1px solid var(--border);
|
|
5223
5237
|
border-radius: 8px;
|
|
5224
5238
|
padding: 8px 9px;
|
|
@@ -5227,13 +5241,26 @@ body.finance-mode #composerWrap { margin-right: var(--finW, 400px); }
|
|
|
5227
5241
|
.fin-skill-role-head { display: flex; flex-direction: column; gap: 1px; margin-bottom: 7px; }
|
|
5228
5242
|
.fin-skill-role-head b { font-size: 11.5px; color: var(--text); }
|
|
5229
5243
|
.fin-skill-role-head span { font-size: 10px; color: var(--muted); }
|
|
5244
|
+
.fin-skill-clear {
|
|
5245
|
+
position: absolute;
|
|
5246
|
+
top: 6px;
|
|
5247
|
+
right: 6px;
|
|
5248
|
+
background: none;
|
|
5249
|
+
border: none;
|
|
5250
|
+
color: var(--muted);
|
|
5251
|
+
line-height: 0;
|
|
5252
|
+
padding: 3px 5px;
|
|
5253
|
+
border-radius: 6px;
|
|
5254
|
+
cursor: pointer;
|
|
5255
|
+
}
|
|
5256
|
+
.fin-skill-clear:hover { color: #ef4444; background: var(--accent-dim); }
|
|
5230
5257
|
.fin-skill-req {
|
|
5231
5258
|
align-self: flex-start;
|
|
5232
5259
|
margin-top: 2px;
|
|
5233
5260
|
font-size: 9.5px;
|
|
5234
5261
|
font-weight: 800;
|
|
5235
5262
|
letter-spacing: 0.5px;
|
|
5236
|
-
color:
|
|
5263
|
+
color: var(--muted);
|
|
5237
5264
|
}
|
|
5238
5265
|
.fin-skill-chips { display: flex; flex-wrap: wrap; gap: 4px; }
|
|
5239
5266
|
.fin-skill-chip {
|