beast-agent 2.30.3 → 2.30.4
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/engine.js +20 -3
- package/src/agent/seeds/haber-duygu/SKILL.md +49 -0
- package/src/agent/seeds/mql5/SKILL.md +129 -0
- package/src/agent/seeds/price-action/SKILL.md +59 -0
- package/src/agent/seeds/risk-yonetimi/SKILL.md +50 -0
- package/src/agent/seeds/tool-yazma/SKILL.md +77 -0
- package/src/main.js +24 -0
- package/src/renderer/index.html +14 -1
- package/src/renderer/renderer.js +97 -0
- package/src/renderer/style.css +44 -0
package/package.json
CHANGED
package/src/agent/engine.js
CHANGED
|
@@ -1894,6 +1894,18 @@ class Engine {
|
|
|
1894
1894
|
macro:
|
|
1895
1895
|
'ROL: MAKRO AJANI 🌍 — büyük resim uzmanısın, İşlem AÇMAZSIN (mt5_trade/mt5_pending/mt5_close KULLANMA). Her turda web_search ile güncel makro manşetleri + ekonomik takvim riskleri (faiz, CPI, jeopolitik); DXY/altın/petrol bağıntılarını odak sembollere çevir; sembol başına yön eğilimi + TEMKİN/BEKLE notu ver.',
|
|
1896
1896
|
})[String((session && session.financeRole) || '')] || '';
|
|
1897
|
+
/* ROL → SKILL eşleştirmesi (ayarlar modalı): rolün okuması gereken skill'ler
|
|
1898
|
+
prompta gömülür; ayar boşsa satır eklenmez. Skill adları kurulu katalogdan
|
|
1899
|
+
seçilir — yeni skill eklendiğinde modalda görünür ve buraya yansır. */
|
|
1900
|
+
const roleSkills = Array.isArray(session && session.financeRoleSkills)
|
|
1901
|
+
? session.financeRoleSkills.map((s) => String(s || '').trim()).filter(Boolean).slice(0, 8)
|
|
1902
|
+
: [];
|
|
1903
|
+
const roleBlockFull = roleBlock
|
|
1904
|
+
? roleBlock +
|
|
1905
|
+
(roleSkills.length
|
|
1906
|
+
? ` ÖNCE şu skill'leri skill aracıyla oku ve prosedürüne göre uygula: ${roleSkills.map((n) => `skill("${n}")`).join(', ')}.`
|
|
1907
|
+
: '')
|
|
1908
|
+
: '';
|
|
1897
1909
|
/* FİNANS EKİBİ: tüm finance ajanları tek DM grubundadır — sohbet grup
|
|
1898
1910
|
thread'inde toplanır (ayrı ayrı 1:1 thread'lere dağılmaz) */
|
|
1899
1911
|
const finJob = this._bgJobs && this._bgJobs.get(String(session && session.id));
|
|
@@ -1903,11 +1915,16 @@ class Engine {
|
|
|
1903
1915
|
'Sen BEAST FİNANS\u2019sın — bilgisayardaki MetaTrader 5 (MT5) terminaline köprüyle bağlı trading ajanı.\n' +
|
|
1904
1916
|
'ORTAM: Beast Finance uygulamasındasın — solda sohbet geçmişi + izleyiciler, ortada bu sohbet, SAĞ panelde MT5 işlem panosu (hesap, pozisyonlar, piyasa, AKIŞ) var.\n' +
|
|
1905
1917
|
'KÖPRÜ: MT5 terminaline Python stdio köprüsüyle bağlısın; panel 3 saniyede bir hesap/pozisyon/piyasa verisini tazeler. mt5_* araç çağrıların ve işlem hareketlerin (açılan/kapanan pozisyonlar) SAĞ paneldeki AKIŞ akışına canlı düşer — panelin orayı izlediğini bil.\n' +
|
|
1906
|
-
'GÖREV ALANI: piyasa verisi okuma (fiyat/hesap/pozisyon/geçmiş), teknik değerlendirme, pozisyon yönetimi (aç/kapat/SL/TP), risk disiplini ve kısa karar raporları.
|
|
1918
|
+
'GÖREV ALANI: piyasa verisi okuma (fiyat/hesap/pozisyon/geçmiş), teknik değerlendirme, pozisyon yönetimi (aç/kapat/SL/TP), risk disiplini ve kısa karar raporları. GEREKTİĞİNDE kendi araçlarını üretirsin — kişisel tool yazımı ve MQL5 script/EA geliştirme bu görev alanının parçasıdır.\n' +
|
|
1907
1919
|
modeBlock2 + '\n' +
|
|
1908
|
-
(
|
|
1920
|
+
(roleBlockFull ? roleBlockFull + '\n' : '') +
|
|
1909
1921
|
(teamLine || '') +
|
|
1910
1922
|
'MT5 ARAÇLARI: mt5_status (bağlantı), mt5_account (hesap), mt5_market (canlı fiyat), mt5_positions (açık pozisyonlar), mt5_orders (bekleyen emirler), mt5_history (kapanan işlemler), mt5_trade (piyasa emri), mt5_close (kapat), mt5_modify (SL/TP), mt5_pending (bekleyen emir), mt5_cancel (emir iptal).\n' +
|
|
1923
|
+
'YETKİLERİN (AÇIK — çekinmeden kullan):\n' +
|
|
1924
|
+
'- skill: kurulu SKILL.md kataloğunu oku ve uygula — tool yazmadan ÖNCE skill("tool-yazma"), MT5 tarafı işlerden ÖNCE skill("mql5") oku ve prosedürüne birebir uy.\n' +
|
|
1925
|
+
'- Kişisel tool yazma: %APPDATA%\\beast\\tools\\<slug>\\ içine tool.json + run.js yaz (write_file/edit_file); run_command ile çıktısını (JSON, ok alanlı) doğrula → tool__<slug> ANINDA tüm finance ajanlarında çağrılabilir olur.\n' +
|
|
1926
|
+
'- MQL5: MT5 tarafında script/gösterge/EA yaz (write_file), metaeditor64.exe /compile ile derle, MQL5\\Files dosya köprüsüyle veriyi Beast\'e taşı; kullanıcıya çalıştırma adımını açıkça söyle.\n' +
|
|
1927
|
+
'- Yerleşik araçlar: run_command, python_run, read_file/write_file/edit_file, web_search/deep_search, browser_* — hepsi açık.\n' +
|
|
1911
1928
|
'VERİ AKIŞI (her değerlendirmede): mt5_account + mt5_positions + mt5_market çağrılarını AYNI turda PARALEL ver; gerekiyorsa mt5_history ile son işlemleri gör.\n' +
|
|
1912
1929
|
'PARALEL + KOORDİNASYON: uzun araştırma/işleri run_background ile paralel finance işçisine devret (parent finance olduğu için işçi mt5 okuma araçlarını görür); koşan ajanlarla konuşmak için agent_dm (to: ajan başlığındaki anahtar kelime, örn "GOLD"; ortak karar için group: "İSİM" ile grup sohbeti kur — mesaj tüm üyelere düşer). Görevin bitince DM/grup sohbetleri otomatik KAPANIR (geçmiş panelde kalır).\n' +
|
|
1913
1930
|
(symbols ? `İZLEME LİSTESİ: ${symbols}\n` : '') +
|
|
@@ -1921,7 +1938,7 @@ class Engine {
|
|
|
1921
1938
|
(mem.user ? `# USER\n${mem.user}\n` : '') +
|
|
1922
1939
|
(rules.length ? `# KURALLAR (sahibinin kalıcı talimatları — daima uy)\n${rules.map((r) => '- ' + r).join('\n')}\n` : '') +
|
|
1923
1940
|
(skList.length
|
|
1924
|
-
? '# SKILLS\nKurulu skill kataloğu: görev bir skill\u2019in tanımına uyarsa skill aracıyla gövdesini (SKILL.md) yükleyip uygula — tekerleği yeniden icat etme. Analysis/rapor/PDF gibi işlerde skill\u2019in prosedürüne uy.\n' +
|
|
1941
|
+
? '# SKILLS\nKurulu skill kataloğu: görev bir skill\u2019in tanımına uyarsa skill aracıyla gövdesini (SKILL.md) yükleyip uygula — tekerleği yeniden icat etme. Analysis/rapor/PDF gibi işlerde skill\u2019in prosedürüne uy. Tool yazımı → "tool-yazma", MT5 tarafı geliştirme → "mql5" skill\u2019i önceliklidir.\n' +
|
|
1925
1942
|
skList.map((s) => `- ${s.name}: ${s.description} [${s.path}]`).join('\n') + '\n'
|
|
1926
1943
|
: '') +
|
|
1927
1944
|
'RAPOR DİSİPLİNİ: kısa ve sayısal — sembol, yön, lot, giriş, SL/TP, sebep tek satırda. Uzun fal açma; tablo/liste kullanabilirsin.\n' +
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: haber-duygu
|
|
3
|
+
description: Haber ve piyasa duyarlılığı rehberi — ekonomik takvim riskleri (NFP/CPI/FOMC/faiz), haber öncesi-sonrası pozisyon disiplini, DXY/faiz/VIX/Fear&Greed okuma, risk-on/risk-off ve emtia bağıntıları. Makro/haber ajanı veya trader haber etkisi değerlendirirken ÖNCE bu skill'i okur.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Haber & Piyasa Duyarlılığı
|
|
8
|
+
|
|
9
|
+
## TEMEL İLKE
|
|
10
|
+
|
|
11
|
+
Haber yön tahmini için değil, **risk zamanlaması** için kullanılır. Yüksek etkili veri saatinde piyasa spreadi genişler ve yön belirsizdir; çoğu zaman en iyi işlem beklemektir.
|
|
12
|
+
|
|
13
|
+
## 1) EKONOMİK TAKVİM
|
|
14
|
+
|
|
15
|
+
- Yüksek etkili: FOMC/faiz kararları, NFP (tarım dışı istihdam), CPI/PPI, GDP, işsizlik, ECB/BOE/BOJ kararları, jeopolitik başlıklar.
|
|
16
|
+
- Kural: yüksek etkili veriden **15–30 dk önce yeni pozisyon açma**; mevcut pozisyonu gözden geçir (SL sabit, panik kapatma yok).
|
|
17
|
+
- Veri sonrası: ilk 5–15 dk fitil/spike olur; kapanış teyidi gelmeden işlem açma.
|
|
18
|
+
- Takvimi `web_search`/`deep_search` ile teyit et; tarih/saati yerel saatle yaz (sunucu saati farkını belirt).
|
|
19
|
+
|
|
20
|
+
## 2) DUYGU GÖSTERGELERİ
|
|
21
|
+
|
|
22
|
+
- **DXY**: dolar gücü — yükselirse altın ve EURUSD genelde baskılanır (ters korelasyon).
|
|
23
|
+
- **ABD 10Y tahvil faizi**: faiz yükseliyorsa risk iştahı azalabilir, altın baskılanabilir.
|
|
24
|
+
- **VIX**: yükseliyorsa risk-off; düşüyorsa risk-on.
|
|
25
|
+
- **Kripto Fear & Greed**: yalnız BTC/ETH gibi kripto pozisyonlarında; hisse/emtia için ana referans değil.
|
|
26
|
+
- Aşırı iyimserlik (greed) ve aşırı korku (fear) uçlarda dönüş riskidir; trend takipçisi için tek başına sinyal değildir.
|
|
27
|
+
|
|
28
|
+
## 3) RİSK-ON / RİSK-OFF
|
|
29
|
+
|
|
30
|
+
- Risk-on: hisse ↑, emtia ↑, dolar/altın baskılı olabilir.
|
|
31
|
+
- Risk-off: DXY/altın/tahvil ↑, hisse/kripto ↓.
|
|
32
|
+
- Makro başlık bölgeyi tersine çevirdiyse mevcut teknik planı **güncelle**, körlemesine uygulama.
|
|
33
|
+
|
|
34
|
+
## 4) HABER DOĞRULAMA
|
|
35
|
+
|
|
36
|
+
- Tek kaynağa güvenme; 2+ bağımsız kaynak teyidi ara.
|
|
37
|
+
- Manşet ile içerik çelişirse içeriği esas al; tarih/saat eski haberi taze sanma.
|
|
38
|
+
- Söylenti (rumor) ve resmi açıklamayı ayır; söylentiye işlem açma.
|
|
39
|
+
|
|
40
|
+
## 5) BAĞINTI NOTLARI
|
|
41
|
+
|
|
42
|
+
- XAUUSD ile DXY ters korele; aynı yönde iki korelasyonlu pozisyon açma (bkz. risk-yonetimi).
|
|
43
|
+
- Petrol haberleri (OPEC, arz kesintisi) enerji sembollerini ve genel risk iştahını etkiler.
|
|
44
|
+
- Emtia sembollerinde broker sembol adını kullan (ör. "GOLD", "XAUUSD" değil) — `mt5_market` ile doğrula.
|
|
45
|
+
|
|
46
|
+
## 6) RAPOR FORMATI
|
|
47
|
+
|
|
48
|
+
`Takvim: <saat> <veri> (yüksek) | duygu: risk-on/off | DXY yön | sembol etkisi: <yön/temkin> | aksiyon: bekle/azalt/normal`
|
|
49
|
+
Veri saatine 30 dk'dan az varsa bunu raporda AÇIKÇA belirt.
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mql5
|
|
3
|
+
description: MetaTrader 5 tarafında MQL5 (script / indicator / Expert Advisor) yazma-derleme rehberi — mt5_* araçlarının yapamadığı işleri (özel hesap, olay yakalama, EA ile otomatik yürütme, dosya köprüsü) MQL5 ile çözmek gerektiğinde ÖNCE bu skill'i oku. Veri klasörünü bulma, MetaEditor ile derleme, MQL5\Files köprüsü ve hazır kod iskeletleri burada.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# MQL5 Tool Yazma (MetaTrader 5)
|
|
8
|
+
|
|
9
|
+
## NE ZAMAN KULLANILIR
|
|
10
|
+
|
|
11
|
+
- `mt5_*` araçları yetmiyorsa: tick/olay anında tepki, çok koşullu emir yönetimi, özel gösterge hesabı, hesap istatistiği, broker'a özel alanlar.
|
|
12
|
+
- Beast tarafında tekrarlı bir rutini MQL5 ile terminalin İÇİNDE çalıştırmak gerekiyorsa.
|
|
13
|
+
- Basit işi Python/Node ile yapabiliyorsan ÖNCE `python_run` / `run_command` / `mt5_*` dene — MQL5 son çare değil ama en ağır seçenektir.
|
|
14
|
+
|
|
15
|
+
## 1) VERİ KLASÖRÜNÜ BUL (ilk adım)
|
|
16
|
+
|
|
17
|
+
1. `mt5_status` çağır → dönen `terminal.data_path` = MT5 veri klasörü (en güvenilir yol).
|
|
18
|
+
2. Bulamazsan `%APPDATA%\MetaQuotes\Terminal\<hash>\` altındaki klasörlerde `MQL5` dizinini ara; hash'i `origin.txt` içeriğiyle (kurulum yolu) eşleştir.
|
|
19
|
+
3. Klasör düzeni:
|
|
20
|
+
|
|
21
|
+
| Klasör | Ne konur |
|
|
22
|
+
|---|---|
|
|
23
|
+
| `<data_path>\MQL5\Experts\` | Expert Advisor (EA) — chart'a iliştirilir |
|
|
24
|
+
| `<data_path>\MQL5\Indicators\` | Özel gösterge |
|
|
25
|
+
| `<data_path>\MQL5\Scripts\` | Tek seferlik script — elle bir kez çalıştırılır |
|
|
26
|
+
| `<data_path>\MQL5\Include\` | Paylaşılan `.mqh` başlıkları |
|
|
27
|
+
| `<data_path>\MQL5\Files\` | MQL5 program sandbox'ı — Beast buradan `read_file` ile okur |
|
|
28
|
+
|
|
29
|
+
## 2) YAZMA
|
|
30
|
+
|
|
31
|
+
- Kod `write_file` ile `.mq5` olarak yazılır (UTF-8). `edit_file`, `read_file`, `run_command`, `python_run` yetkilerin açık.
|
|
32
|
+
- MQL5 C++ benzeridir; Python paketi yoktur, yalnız MetaTrader standart kütüphanesi vardır.
|
|
33
|
+
- Hazır sınıflar: `#include <Trade\Trade.mqh>` (CTrade), `#include <Trade\PositionInfo.mqh>`, `#include <Trade\SymbolInfo.mqh>`.
|
|
34
|
+
- Türkçe karakteri yalnız string/yorum içinde kullan; değişken adlarında kullanma.
|
|
35
|
+
|
|
36
|
+
## 3) DERLEME (MetaEditor)
|
|
37
|
+
|
|
38
|
+
`metaeditor64.exe`, `terminal64.exe` ile aynı klasördedir (genelde `C:\Program Files\MetaTrader 5\` veya broker kurulum klasörü).
|
|
39
|
+
|
|
40
|
+
```powershell
|
|
41
|
+
& "C:\Program Files\MetaTrader 5\metaeditor64.exe" /compile:"<data_path>\MQL5\Scripts\beast_script.mq5" /log:"<data_path>\MQL5\Scripts\beast_script.log"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
- Derleme logu **UTF-16**'dır:
|
|
45
|
+
```powershell
|
|
46
|
+
Get-Content -Encoding Unicode "<log>" | Select-String "error|warning"
|
|
47
|
+
```
|
|
48
|
+
- "0 errors" görmeden işi bitti sayma. Hata varsa kodu düzelt, yeniden derle.
|
|
49
|
+
- Terminalin açık olması derleme için gerekmez; metaeditor yolunu bulamazsan `Get-Command metaeditor64.exe` veya `Get-ChildItem "C:\Program Files" -Recurse -Filter metaeditor64.exe` ile ara.
|
|
50
|
+
|
|
51
|
+
## 4) ÇALIŞTIRMA + BEAST KÖPRÜSÜ
|
|
52
|
+
|
|
53
|
+
- **Script**: MT5 → Navigator → Scripts → çift tık (kullanıcı) — Python API'den MQL5 tetiklenemez.
|
|
54
|
+
- **EA**: chart'a iliştirilir; AutoTrading düğmesi açık olmalıdır.
|
|
55
|
+
- **Dosya köprüsü (önerilen)**:
|
|
56
|
+
- MQL5 → Beast: program `MQL5\Files\beast_signal.json` yazar; ajan `read_file` ile `<data_path>\MQL5\Files\beast_signal.json` okur.
|
|
57
|
+
- Beast → MQL5: ajan `beast_cmd.json` yazar; EA `FileRead` ile komutu çeker (polling).
|
|
58
|
+
- Kullanıcıya EA/script'i nasıl iliştireceğini net söyle; "otomatik çalışıyor" varsayma.
|
|
59
|
+
|
|
60
|
+
## 5) KOD İSKELETLERİ
|
|
61
|
+
|
|
62
|
+
### Script → dosyaya veri yaz (Beast okur)
|
|
63
|
+
|
|
64
|
+
```mql5
|
|
65
|
+
#property version "1.00"
|
|
66
|
+
#property script_show_inputs
|
|
67
|
+
input string OutFile = "beast_signal.json";
|
|
68
|
+
|
|
69
|
+
void OnStart()
|
|
70
|
+
{
|
|
71
|
+
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
|
72
|
+
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
|
73
|
+
int h = FileOpen(OutFile, FILE_WRITE | FILE_TXT | FILE_ANSI);
|
|
74
|
+
if(h == INVALID_HANDLE)
|
|
75
|
+
{
|
|
76
|
+
Print("dosya acilamadi: ", GetLastError());
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
FileWriteString(h, StringFormat("{\"symbol\":\"%s\",\"bid\":%.5f,\"ask\":%.5f,\"time\":\"%s\"}",
|
|
80
|
+
_Symbol, bid, ask, TimeToString(TimeCurrent(), TIME_DATE | TIME_SECONDS)));
|
|
81
|
+
FileClose(h);
|
|
82
|
+
Print("beast_signal yazildi: ", bid, " / ", ask);
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### EA iskeleti (CTrade)
|
|
87
|
+
|
|
88
|
+
```mql5
|
|
89
|
+
#property version "1.00"
|
|
90
|
+
#include <Trade\Trade.mqh>
|
|
91
|
+
CTrade trade;
|
|
92
|
+
|
|
93
|
+
int OnInit()
|
|
94
|
+
{
|
|
95
|
+
trade.SetExpertMagicNumber(20260910);
|
|
96
|
+
return INIT_SUCCEEDED;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
void OnTick()
|
|
100
|
+
{
|
|
101
|
+
/* sinyal + risk: lot hesabı, SL/TP zorunlu; martingale YOK */
|
|
102
|
+
/* trade.Buy(lot, _Symbol, 0.0, sl, tp, "beast"); */
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
void OnDeinit(const int reason) {}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Ters yön: komut dosyası oku
|
|
109
|
+
|
|
110
|
+
```mql5
|
|
111
|
+
bool ReadCmd(string &out)
|
|
112
|
+
{
|
|
113
|
+
if(!FileIsExist("beast_cmd.json")) return false;
|
|
114
|
+
int h = FileOpen("beast_cmd.json", FILE_READ | FILE_TXT | FILE_ANSI);
|
|
115
|
+
if(h == INVALID_HANDLE) return false;
|
|
116
|
+
out = FileReadString(h);
|
|
117
|
+
FileClose(h);
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## 6) KURALLAR
|
|
123
|
+
|
|
124
|
+
- SL'siz işlem/EA yazma; martingale/kademeli lot artışı YASAK.
|
|
125
|
+
- Sembol adını `mt5_market` ile doğrula — broker'da neyse o (örn "GOLD", "XAUUSD" değil).
|
|
126
|
+
- `TimeCurrent()` broker sunucu saatidir; raporda saat dilimini belirt.
|
|
127
|
+
- Ağ/DLL kullanacaksan kullanıcıdan onay iste (`#import` varsayılan kapalıdır).
|
|
128
|
+
- Şifre/API anahtarını koda, loga, rapora YAZMA.
|
|
129
|
+
- Derlenmemiş/çalıştırılmamış kodu "bitti" diye raporlama; kullanıcıya çalıştırma adımını açıkça söyle.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: price-action
|
|
3
|
+
description: Fiyat yapısı / price action analiz rehberi — market structure (HH/LL, BOS, CHoCH), destek-direnç bölgeleri, likidite süpürme, çoklu zaman dilimi teyidi, giriş/SL/TP yerleşimi. Teknik analiz ajanı veya trader bir sembolde yön/giriş kararı verirken ÖNCE bu skill'i okur.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Price Action / Fiyat Yapısı
|
|
8
|
+
|
|
9
|
+
## TEMEL İLKE
|
|
10
|
+
|
|
11
|
+
Yön kararı YAPIDAN gelir, göstergeden değil. MA kesişimi tek başına gürültüdür; teyit yoksa işlem yok.
|
|
12
|
+
|
|
13
|
+
## 1) MARKET STRUCTURE (önce bu)
|
|
14
|
+
|
|
15
|
+
- Swing high / swing low'ları işaretle (lookback: son 50-100 mum yeterli).
|
|
16
|
+
- Yükseliş yapısı: **HH + HL** (higher high, higher low). Düşüş: **LH + LL**.
|
|
17
|
+
- **BOS (Break of Structure)**: trend yönündeki son swing seviyesinin kapanışla kırılması = trend devam teyidi.
|
|
18
|
+
- **CHoCH (Change of Character)**: karşı yöndeki ilk yapı kırılması = olası dönüş sinyali; BOS ile karıştırma.
|
|
19
|
+
- Yapı belirsizse (range) → BEKLE; range'de sadece sınırlardan işlem düşünülür.
|
|
20
|
+
|
|
21
|
+
## 2) DESTEK / DİRENÇ + LİKİDİTE
|
|
22
|
+
|
|
23
|
+
- Bölgeyi çizgi değil **alan** olarak al (mum gövdeleri + fitiller).
|
|
24
|
+
- Önem sırası: HTF (H4/D1) > LTF (M15/M5). HTF seviyesi LTF'de daha güçlüdür.
|
|
25
|
+
- Eşit tepeler/dipler likidite havuzudur; fitil ile "süpürülme" (stop hunt) sık olur — kırılımda **kapanış teyidi** ara.
|
|
26
|
+
- Yuvarlak rakamlar (2400, 1.1000) ve önceki günün high/low'u doğal seviyedir.
|
|
27
|
+
|
|
28
|
+
## 3) ÇOKLU ZAMAN DİLİMİ (MTF)
|
|
29
|
+
|
|
30
|
+
1. HTF (H4/D1): yön ve ana bölge.
|
|
31
|
+
2. MTF (H1/M15): yapı + BOS/CHoCH.
|
|
32
|
+
3. LTF (M5/M1): giriş tetiği (retest, engulfing, iğne).
|
|
33
|
+
Kural: LTF sinyali HTF yönüne tersse işlem açma.
|
|
34
|
+
|
|
35
|
+
## 4) MOMENTUM / VOLATİLİTE
|
|
36
|
+
|
|
37
|
+
- ATR: SL mesafesi ve pozisyon boyutu için (sabit pip değil, ATR bazlı).
|
|
38
|
+
- RSI divergence sadece **teyit** olarak kullanılır; tek başına giriş sebebi değildir.
|
|
39
|
+
- Hacim/range daralması sıkışma (squeeze) → kırılım yaklaşıyor; yön teyidi bekle.
|
|
40
|
+
|
|
41
|
+
## 5) GİRİŞ / SL / TP
|
|
42
|
+
|
|
43
|
+
- Giriş: BOS sonrası geri çekilme (pullback) + retest teyidi; kovalama yok.
|
|
44
|
+
- SL: yapının arkasına (son swing low/high'ın ötesi) + spread/ATR payı. Yapının İÇİNE SL koyma.
|
|
45
|
+
- Geniş SL tercih ediliyorsa: ~4×ATR SL, ~2×ATR'de BE (break-even) taşıma.
|
|
46
|
+
- TP: bir sonraki HTF bölgesi; R:R en az 1.5–2. Kısmi kâr alımı serbest.
|
|
47
|
+
- BE'e çekmeden SL'siz/işlemsiz kalma; her pozisyonun SL'si olsun.
|
|
48
|
+
|
|
49
|
+
## 6) YASAKLAR
|
|
50
|
+
|
|
51
|
+
- Teyitsiz (BOS/CHoCH olmadan) giriş.
|
|
52
|
+
- Zarara ekleme (averaging down) ve martingale.
|
|
53
|
+
- Haber anında spread genişken piyasa emri (bkz. haber-duygu skill'i).
|
|
54
|
+
- Yapıya ters, sırf "ucuz/pahalı" diye işlem.
|
|
55
|
+
|
|
56
|
+
## 7) RAPOR FORMATI
|
|
57
|
+
|
|
58
|
+
Tek satır: `SEMBOL | yön | giriş | SL | TP | yapı gerekçesi (BOS/CHoCH/bölge) | R:R`
|
|
59
|
+
Belirsizse net yaz: `BEKLE: <sebep>`.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: risk-yonetimi
|
|
3
|
+
description: Pozisyon boyutlandırma ve risk disiplini rehberi — hesap yüzdesiyle lot hesabı, marj/kaldıraç denetimi, max eşzamanlı pozisyon, korelasyon/tek yön birikme, günlük kayıp limiti, SL/BE/trailing kuralları. Risk ajanı veya trader her turda ve her işlemden önce bu skill'e göre kontrol yapar.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Risk Yönetimi
|
|
8
|
+
|
|
9
|
+
## TEMEL KURAL
|
|
10
|
+
|
|
11
|
+
Önce kaybı sınırla, kârı piyasa versin. İşlem başına risk sabittir; lot, SL mesafesine göre hesaplanır.
|
|
12
|
+
|
|
13
|
+
## 1) POZİSYON BOYUTU
|
|
14
|
+
|
|
15
|
+
- İşlem başına risk: hesabın **%0.5–1'i** (agresif değilse %0.25–0.5).
|
|
16
|
+
- Lot hesabı: `lot = (bakiye × risk%) / (SL_mesafesi × sembolün pip değeri)`.
|
|
17
|
+
- SL mesafesi ATR/yapıdan gelir; önce SL belirle, sonra lotu küçült — tersini yapma.
|
|
18
|
+
- Broker limitleri: panel `max lot` ve `max eşzamanlı pozisyon` ayarlarına uy; sistem reddederse zorlama.
|
|
19
|
+
|
|
20
|
+
## 2) MARJ / KALDIRAÇ
|
|
21
|
+
|
|
22
|
+
- Serbest marjın tamamını tek işleme bağlama; toplam açık risk serbest marjın küçük bir kısmı olsun.
|
|
23
|
+
- Kaldıraç yüksekse lotu düşür; kaldıraç = risk değil, imkândır.
|
|
24
|
+
- Marj seviyesi düşerken yeni pozisyon AÇMA; önce riski azalt.
|
|
25
|
+
|
|
26
|
+
## 3) PORTFÖY DENETİMİ (her turda)
|
|
27
|
+
|
|
28
|
+
- Açık pozisyonların toplam riskini hesapla (SL'lere göre kayıp potansiyeli).
|
|
29
|
+
- **Tek yön birikme**: aynı yönde üst üste pozisyon = tek işlem gibi davranır; toplam riski tek işlem limiti gibi say.
|
|
30
|
+
- **Korelasyon**: XAUUSD/EURUSD ile DXY ters koreledir; aynı yönde iki korelasyonlu pozisyon riski katlar.
|
|
31
|
+
- SL'siz pozisyon varsa ilk iş: SL tamamla veya kapat.
|
|
32
|
+
- Hedefine ulaşan/kâra geçen pozisyonda BE veya kısmi kâr; trailing ATR bazlı.
|
|
33
|
+
|
|
34
|
+
## 4) KAYIP LİMİTLERİ
|
|
35
|
+
|
|
36
|
+
- Günlük kayıp limiti belirle (ör. hesabın %2–3'ü). Limit dolduysa **o gün yeni işlem yok**; raporla.
|
|
37
|
+
- Üst üste 2-3 kayıptan sonra lotu artırma (revenge trade YASAK); aksine küçült veya dur.
|
|
38
|
+
- Drawdown artıyorsa tur sıklığını/agresifliği azalt, sadece A+ setuplara gir.
|
|
39
|
+
|
|
40
|
+
## 5) YASAKLAR
|
|
41
|
+
|
|
42
|
+
- Martingale / kademeli lot artışı.
|
|
43
|
+
- SL taşımayı kaybı büyütecek yönde yapmak (SL genişletme).
|
|
44
|
+
- Marjı zorlayan "son işlem" kumarı.
|
|
45
|
+
- Aynı anda korelasyonlu 3+ pozisyonla tek yön yığmak.
|
|
46
|
+
|
|
47
|
+
## 6) RAPOR FORMATI
|
|
48
|
+
|
|
49
|
+
`Risk: toplam açık R%X | marj kullanımı %Y | en riskli pozisyon: ... | öneri: SL/BE/küçült/kapat`
|
|
50
|
+
Sınır aşımı varsa öncelikli ve net yaz.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tool-yazma
|
|
3
|
+
description: Kişisel TOOL yazma/düzenleme rehberi — %APPDATA%\beast\tools\<ad>\ altına tool.json + run.js yazılacak veya mevcut bir tool editlenecekse ÖNCE bu skill'i oku. Tool'un sözleşmesi: stdin JSON argüman → stdout JSON sonuç; ajan tool__<ad> olarak çağırır (Beast Finance dahil tüm oturumlarda çalışır).
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Kişisel TOOL Yazma
|
|
8
|
+
|
|
9
|
+
## TOOL NEDİR / NE ZAMAN YAZILIR
|
|
10
|
+
|
|
11
|
+
Kişisel tool = modelin alet çantasına GİREN gerçek bir araçtır: %APPDATA%\beast\tools\<slug>\ klasöründe **tool.json** (tanım) + **run.js** (kod) bulunur. Tüm oturumlarda — Beast Finance chat/trader/işçiler dahil — `tool__<slug>` adıyla çağrılır.
|
|
12
|
+
|
|
13
|
+
Yaz ZAMAN: mevcut araçlar işi görmüyorsa (örn. broker sembol adlandırması mt5_trade'i düşürüyorsa), özel bir API'ye bağlanman, tekrarlı bir hesap/işlem rutini gerekiyorsa. Basit işler için YAZMA — önce yerleşik araçları (mt5_*, web_search, python_run, run_command) dene.
|
|
14
|
+
|
|
15
|
+
## SÖZLEŞME (birebir uygula)
|
|
16
|
+
|
|
17
|
+
- **stdin**: JSON argümanlar (tek satırda, güvenli parse)
|
|
18
|
+
- **stdout**: SADECE JSON sonuç — son satır JSON'a çevrilmeye çalışılır; günlük/metin yazarsan JSON bozulur, `console.error` kullan
|
|
19
|
+
- **çalışma klasörü**: tool'un kendi klasörü (yanına dosya yazabilirsin)
|
|
20
|
+
- **zaman aşımı**: 90 sn — uzun işleri kendin parçalama, `run_background`'a devret
|
|
21
|
+
- **sonuç biçimi**: `{ "ok": true, ... }` ya da `{ "ok": false, "error": "sebep" }` — ok alanı ZORUNLU
|
|
22
|
+
|
|
23
|
+
## YENİ TOOL OLUŞTURMA (2 dosya, write_file ile)
|
|
24
|
+
|
|
25
|
+
`%APPDATA%\beast\tools\<slug>\tool.json`:
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"name": "gold_emir",
|
|
29
|
+
"description": "GOLD için özel emir açar — side (buy/sell), lot, sl, tp alır; sonucu ticket ile döndürür.",
|
|
30
|
+
"parameters": {
|
|
31
|
+
"type": "object",
|
|
32
|
+
"properties": {
|
|
33
|
+
"side": { "type": "string", "description": "buy | sell" },
|
|
34
|
+
"lot": { "type": "number", "description": "0.01-1.0" },
|
|
35
|
+
"sl": { "type": "number" },
|
|
36
|
+
"tp": { "type": "number" }
|
|
37
|
+
},
|
|
38
|
+
"required": ["side", "lot"]
|
|
39
|
+
},
|
|
40
|
+
"updatedAt": "2026-09-09T00:00:00.000Z"
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`%APPDATA%\beast\tools\<slug>\run.js`:
|
|
45
|
+
```javascript
|
|
46
|
+
'use strict';
|
|
47
|
+
// stdin: JSON args · stdout: JSON sonuç (SADECE JSON yaz!)
|
|
48
|
+
const fs = require('fs');
|
|
49
|
+
let args = {};
|
|
50
|
+
try { args = JSON.parse(fs.readFileSync(0, 'utf8') || '{}'); } catch {}
|
|
51
|
+
(function main() {
|
|
52
|
+
const { side, lot, sl, tp } = args;
|
|
53
|
+
if (!side || !lot) {
|
|
54
|
+
console.log(JSON.stringify({ ok: false, error: 'side ve lot zorunlu' }));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
// --- kendi işin burada: HTTP çağrısı, MT5 köprüsü, dosya, hesap... ---
|
|
58
|
+
// Örn: https modülüyle özel endpoint'e istek at, sonucu ok alanıyla sar.
|
|
59
|
+
console.log(JSON.stringify({ ok: true, side, lot, sl: sl || 0, tp: tp || 0, ticket: 0 }));
|
|
60
|
+
})();
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Slug kuralları: a-z, 0-9, alt çizgi, tire — 2-24 karakter (örn: gold_emir, haber_ozet). Hazır taslak: %APPDATA%\beast\tools\ornek_echo klasörünü referans al; yeni tool'u o biçimle yaz.
|
|
64
|
+
|
|
65
|
+
## DÜZENLEME / DOĞRULAMA
|
|
66
|
+
|
|
67
|
+
1. Mevcut toolu değiştirme: `edit_file` ile tool.json / run.js düzenle — ASLA tüm klasörü silip baştan yazma.
|
|
68
|
+
2. Kayıttan sonra tool ANINDA aktifleşir (yeniden başlatma gerekmez) — bir sonraki turda `tool__<slug>` çağrılabilir.
|
|
69
|
+
3. Doğrula: `run_command` ile `echo "{\"mesaj\":\"test\"}" | node "%APPDATA%\beast\tools\<slug>\run.js"` — çıktı JSON olmalı ve `ok` alanı içermeli.
|
|
70
|
+
4. Hata çıktısı `ok:false + error` olsun — model hatayı okuyup düzeltir; çıplak stack yasak.
|
|
71
|
+
|
|
72
|
+
## GÜVENLİK + STİL
|
|
73
|
+
|
|
74
|
+
- Şifre/API anahtarını ASLA stdout'a, log'a, skill'e yazma.
|
|
75
|
+
- Ağ çağrılarında timeout kullan (`https` modülü + `req.setTimeout` veya fetch); sonsuz bekleyen script yazma.
|
|
76
|
+
- Tek sorumluluk: bir tool = bir iş. Çok işli dev tool yazma — parçala.
|
|
77
|
+
- Kullanıcıya tool'u nasıl yöneteceğini söyle: sol panelde TOOLLAR kutusunda test/düzenle/sil + 📂 klasör.
|
package/src/main.js
CHANGED
|
@@ -8329,6 +8329,12 @@ function finCfg() {
|
|
|
8329
8329
|
f.analysisAuto = true;
|
|
8330
8330
|
if (!Number.isFinite(Number(f.analysisCount))) f.analysisCount = 2;
|
|
8331
8331
|
f.analysisCount = Math.max(0, Math.min(FIN_ROLES_AUTO.length, Math.round(Number(f.analysisCount) || 0)));
|
|
8332
|
+
/* ROL → SKILL eşleştirmesi: rol başına en fazla 8 skill adı */
|
|
8333
|
+
if (!f.roleSkills || typeof f.roleSkills !== 'object') f.roleSkills = {};
|
|
8334
|
+
for (const d of FIN_ROLES) {
|
|
8335
|
+
const cur = Array.isArray(f.roleSkills[d.id]) ? f.roleSkills[d.id] : ROLE_SKILL_DEFAULTS[d.id] || [];
|
|
8336
|
+
f.roleSkills[d.id] = cur.map((s) => String(s || '').trim()).filter(Boolean).slice(0, 8);
|
|
8337
|
+
}
|
|
8332
8338
|
if (!Number(f.intervalSec)) f.intervalSec = 120;
|
|
8333
8339
|
if (!Number(f.maxLot)) f.maxLot = 0.1;
|
|
8334
8340
|
if (f.maxPositions == null) f.maxPositions = 3;
|
|
@@ -8345,6 +8351,14 @@ const FIN_ROLES = [
|
|
|
8345
8351
|
{ id: 'macro', label: 'Haber / Makro', desc: 'haber akışı + ekonomik takvim, DXY/emtia bağıntıları, yön eğilimi' },
|
|
8346
8352
|
];
|
|
8347
8353
|
const FIN_ROLES_AUTO = ['technic', 'risk', 'macro'];
|
|
8354
|
+
/* ROL → SKILL varsayılanları: her rolün tur başında okuması gereken skill'ler.
|
|
8355
|
+
TRADE AJANI kartındaki ⚙ modalından değiştirilebilir; liste kurulu skill
|
|
8356
|
+
kataloğundan beslenir, yeni skill eklenince modalda otomatik görünür. */
|
|
8357
|
+
const ROLE_SKILL_DEFAULTS = {
|
|
8358
|
+
technic: ['price-action'],
|
|
8359
|
+
risk: ['risk-yonetimi'],
|
|
8360
|
+
macro: ['haber-duygu'],
|
|
8361
|
+
};
|
|
8348
8362
|
function finRolesValid(list) {
|
|
8349
8363
|
return (Array.isArray(list) ? list : [])
|
|
8350
8364
|
.map((r) => String(r || '').trim())
|
|
@@ -8567,6 +8581,8 @@ function finApplyTraderFields(s, symbolsOverride, role) {
|
|
|
8567
8581
|
s.financeSymbols = Array.isArray(symbolsOverride) && symbolsOverride.length ? symbolsOverride : f.symbols;
|
|
8568
8582
|
s.financeStrategy = String(f.strategy || '');
|
|
8569
8583
|
s.financeLimits = { maxLot: f.maxLot, maxPositions: f.maxPositions };
|
|
8584
|
+
/* rolün okuması gereken skill'ler (modal eşleştirmesi) — promptta role eklenir */
|
|
8585
|
+
s.financeRoleSkills = (f.roleSkills && f.roleSkills[r]) || [];
|
|
8570
8586
|
engine.cache.set(String(s.id), s);
|
|
8571
8587
|
}
|
|
8572
8588
|
|
|
@@ -8884,6 +8900,14 @@ ipcMain.handle('finance:settings', async (_e, patch) => {
|
|
|
8884
8900
|
if (p.analysisTeam !== undefined) f.analysisTeam = finRolesValid(p.analysisTeam);
|
|
8885
8901
|
if (p.analysisAuto !== undefined) f.analysisAuto = !!p.analysisAuto;
|
|
8886
8902
|
if (p.analysisCount !== undefined) f.analysisCount = Math.max(0, Math.min(FIN_ROLES_AUTO.length, Math.round(Number(p.analysisCount) || 0)));
|
|
8903
|
+
/* ROL → SKILL eşleştirmesi güncellemesi (modal) */
|
|
8904
|
+
if (p.roleSkills !== undefined && p.roleSkills && typeof p.roleSkills === 'object') {
|
|
8905
|
+
for (const d of FIN_ROLES) {
|
|
8906
|
+
if (p.roleSkills[d.id] === undefined) continue;
|
|
8907
|
+
f.roleSkills[d.id] = (Array.isArray(p.roleSkills[d.id]) ? p.roleSkills[d.id] : [])
|
|
8908
|
+
.map((s) => String(s || '').trim()).filter(Boolean).slice(0, 8);
|
|
8909
|
+
}
|
|
8910
|
+
}
|
|
8887
8911
|
if (p.pythonPath !== undefined) f.pythonPath = String(p.pythonPath || '').trim();
|
|
8888
8912
|
if (p.terminalPath !== undefined) f.terminalPath = String(p.terminalPath || '').trim();
|
|
8889
8913
|
if (p.traderSel !== undefined) {
|
package/src/renderer/index.html
CHANGED
|
@@ -162,7 +162,7 @@
|
|
|
162
162
|
</div>
|
|
163
163
|
</div>
|
|
164
164
|
<div class="fin-card fin-card-trader">
|
|
165
|
-
<div class="fin-card-title">TRADE AJANI <span id="finTraderDot" class="fin-dot off" title="Trader durumu"></span></div>
|
|
165
|
+
<div class="fin-card-title">TRADE AJANI <span id="finTraderDot" class="fin-dot off" title="Trader durumu"></span><span class="file-spacer"></span><button id="finSkillsBtn" title="Rol → skill eşleştirmesi — hangi rol hangi skill'i okur">⚙</button></div>
|
|
166
166
|
<div class="fin-field">
|
|
167
167
|
<span>Model</span>
|
|
168
168
|
<select id="finTraderModel" title="Trader ajanının modeli — farklı API/model seçilebilir"></select>
|
|
@@ -648,6 +648,19 @@
|
|
|
648
648
|
</div>
|
|
649
649
|
</div>
|
|
650
650
|
|
|
651
|
+
<div id="finSkillsOverlay" class="mini-overlay" hidden>
|
|
652
|
+
<div class="mini-dialog fin-skills-dialog">
|
|
653
|
+
<div class="mini-head">
|
|
654
|
+
<span class="mini-title">ROL → SKILL EŞLEŞTİRME</span>
|
|
655
|
+
<button class="mini-close" id="finSkillsClose" title="Kapat">×</button>
|
|
656
|
+
</div>
|
|
657
|
+
<div class="mini-body">
|
|
658
|
+
<div id="finSkillsList" class="mini-list"></div>
|
|
659
|
+
<div class="fin-sym-hint">Her rolün okuması gereken skill'leri seç — liste kurulu katalogdan gelir; yeni skill eklersen burada otomatik görünür.</div>
|
|
660
|
+
</div>
|
|
661
|
+
</div>
|
|
662
|
+
</div>
|
|
663
|
+
|
|
651
664
|
<div id="cronOverlay" class="mini-overlay" hidden>
|
|
652
665
|
<div class="mini-dialog">
|
|
653
666
|
<div class="mini-head">
|
package/src/renderer/renderer.js
CHANGED
|
@@ -187,6 +187,10 @@ const els = {
|
|
|
187
187
|
finSymAdd: $('#finSymAdd'),
|
|
188
188
|
finSymOverlay: $('#finSymOverlay'),
|
|
189
189
|
finSymClose: $('#finSymClose'),
|
|
190
|
+
finSkillsBtn: $('#finSkillsBtn'),
|
|
191
|
+
finSkillsOverlay: $('#finSkillsOverlay'),
|
|
192
|
+
finSkillsClose: $('#finSkillsClose'),
|
|
193
|
+
finSkillsList: $('#finSkillsList'),
|
|
190
194
|
finSymSearch: $('#finSymSearch'),
|
|
191
195
|
finSymPick: $('#finSymPick'),
|
|
192
196
|
finSymCount: $('#finSymCount'),
|
|
@@ -8792,6 +8796,7 @@ function financeModeOn() {
|
|
|
8792
8796
|
let finPollTimer = null;
|
|
8793
8797
|
let finModelsFilled = false;
|
|
8794
8798
|
let finLastPrices = new Map(); /* sembol → son bid (renk için) */
|
|
8799
|
+
let finCfgCache = null; /* son snapshot cfg — rol→skill modalı bundan okur */
|
|
8795
8800
|
const FIN_COLOR_UP = 'fs-up';
|
|
8796
8801
|
const FIN_COLOR_DOWN = 'fs-down';
|
|
8797
8802
|
|
|
@@ -9099,6 +9104,7 @@ async function finSnapshot() {
|
|
|
9099
9104
|
return;
|
|
9100
9105
|
}
|
|
9101
9106
|
const b = r.bridge || {};
|
|
9107
|
+
finCfgCache = r.cfg || null;
|
|
9102
9108
|
finSetDot(b.connected ? true : b.running ? 'busy' : false, b);
|
|
9103
9109
|
finRenderAccount(r.account);
|
|
9104
9110
|
finRenderPositions(r.positions || []);
|
|
@@ -9372,6 +9378,97 @@ function finSymPickerClose() {
|
|
|
9372
9378
|
if (els.finSymOverlay) els.finSymOverlay.hidden = true;
|
|
9373
9379
|
}
|
|
9374
9380
|
|
|
9381
|
+
/* ---------- ROL → SKILL eşleştirme modalı ----------
|
|
9382
|
+
Roller sunucudan (snapshot.roles), skill listesi KURULU katalogdan gelir —
|
|
9383
|
+
yeni skill eklendiğinde modalda otomatik görünür. Seçim finance ayarına
|
|
9384
|
+
(roleSkills) yazılır; rol ajanı her turda o skill'leri okumakla yükümlüdür. */
|
|
9385
|
+
let finSkillNames = [];
|
|
9386
|
+
|
|
9387
|
+
async function finSkillsOpen() {
|
|
9388
|
+
if (!els.finSkillsOverlay) return;
|
|
9389
|
+
els.finSkillsOverlay.hidden = false;
|
|
9390
|
+
if (els.finSkillsList) els.finSkillsList.innerHTML = '<div class="fin-empty">Skill kataloğu yükleniyor…</div>';
|
|
9391
|
+
let list = [];
|
|
9392
|
+
try { list = (await beast.listSkills()) || []; } catch {}
|
|
9393
|
+
finSkillNames = (Array.isArray(list) ? list : [])
|
|
9394
|
+
.map((s) => ({ name: String((s && s.name) || ''), description: String((s && s.description) || '') }))
|
|
9395
|
+
.filter((s) => s.name);
|
|
9396
|
+
try { await finSnapshot(); } catch {}
|
|
9397
|
+
finRenderSkills();
|
|
9398
|
+
}
|
|
9399
|
+
|
|
9400
|
+
function finRenderSkills() {
|
|
9401
|
+
const box = els.finSkillsList;
|
|
9402
|
+
if (!box) return;
|
|
9403
|
+
const cfg = finCfgCache || {};
|
|
9404
|
+
const map = cfg.roleSkills && typeof cfg.roleSkills === 'object' ? cfg.roleSkills : {};
|
|
9405
|
+
const roles = Array.isArray(finRolesCatalog) ? finRolesCatalog : [];
|
|
9406
|
+
box.innerHTML = '';
|
|
9407
|
+
if (!roles.length) {
|
|
9408
|
+
box.innerHTML = '<div class="fin-empty">Rol kataloğu yok</div>';
|
|
9409
|
+
return;
|
|
9410
|
+
}
|
|
9411
|
+
if (!finSkillNames.length) {
|
|
9412
|
+
box.innerHTML = '<div class="fin-empty">Kurulu skill bulunamadı — %APPDATA%\\beast\\skills klasörüne SKILL.md ekle</div>';
|
|
9413
|
+
return;
|
|
9414
|
+
}
|
|
9415
|
+
for (const r of roles) {
|
|
9416
|
+
const row = document.createElement('div');
|
|
9417
|
+
row.className = 'fin-skill-role';
|
|
9418
|
+
const head = document.createElement('div');
|
|
9419
|
+
head.className = 'fin-skill-role-head';
|
|
9420
|
+
head.innerHTML =
|
|
9421
|
+
'<b>' + escapeHtml(String(r.label || r.id)) + '</b>' +
|
|
9422
|
+
'<span>' + escapeHtml(String(r.desc || '').slice(0, 110)) + '</span>';
|
|
9423
|
+
row.appendChild(head);
|
|
9424
|
+
const chips = document.createElement('div');
|
|
9425
|
+
chips.className = 'fin-skill-chips';
|
|
9426
|
+
for (const s of finSkillNames) {
|
|
9427
|
+
const cur = Array.isArray(map[r.id]) ? map[r.id] : [];
|
|
9428
|
+
const chip = document.createElement('label');
|
|
9429
|
+
chip.className = 'fin-skill-chip' + (cur.includes(s.name) ? ' on' : '');
|
|
9430
|
+
chip.title = s.description || s.name;
|
|
9431
|
+
const cb = document.createElement('input');
|
|
9432
|
+
cb.type = 'checkbox';
|
|
9433
|
+
cb.checked = cur.includes(s.name);
|
|
9434
|
+
cb.addEventListener('change', () => {
|
|
9435
|
+
const liveBase = finCfgCache && finCfgCache.roleSkills && Array.isArray(finCfgCache.roleSkills[r.id])
|
|
9436
|
+
? finCfgCache.roleSkills[r.id]
|
|
9437
|
+
: [];
|
|
9438
|
+
const set = new Set(liveBase);
|
|
9439
|
+
if (cb.checked) set.add(s.name); else set.delete(s.name);
|
|
9440
|
+
const next = [...set];
|
|
9441
|
+
/* yerel önbelleğe anında yaz — 3 sn'lik snapshot eski değeri geri getirmesin */
|
|
9442
|
+
finCfgCache = finCfgCache || {};
|
|
9443
|
+
finCfgCache.roleSkills = finCfgCache.roleSkills || {};
|
|
9444
|
+
finCfgCache.roleSkills[r.id] = next;
|
|
9445
|
+
chip.classList.toggle('on', cb.checked);
|
|
9446
|
+
finSaveCfg({ roleSkills: { [r.id]: next } });
|
|
9447
|
+
toast((r.label || r.id) + ' → ' + (next.length ? next.join(', ') : 'skill kapalı'));
|
|
9448
|
+
});
|
|
9449
|
+
chip.appendChild(cb);
|
|
9450
|
+
chip.appendChild(document.createTextNode(s.name));
|
|
9451
|
+
chips.appendChild(chip);
|
|
9452
|
+
}
|
|
9453
|
+
row.appendChild(chips);
|
|
9454
|
+
box.appendChild(row);
|
|
9455
|
+
}
|
|
9456
|
+
}
|
|
9457
|
+
|
|
9458
|
+
function finSkillsCloseModal() {
|
|
9459
|
+
if (els.finSkillsOverlay) els.finSkillsOverlay.hidden = true;
|
|
9460
|
+
}
|
|
9461
|
+
if (els.finSkillsBtn) els.finSkillsBtn.addEventListener('click', () => { finSkillsOpen(); });
|
|
9462
|
+
if (els.finSkillsClose) els.finSkillsClose.addEventListener('click', finSkillsCloseModal);
|
|
9463
|
+
if (els.finSkillsOverlay) {
|
|
9464
|
+
els.finSkillsOverlay.addEventListener('click', (e) => {
|
|
9465
|
+
if (e.target === els.finSkillsOverlay) finSkillsCloseModal();
|
|
9466
|
+
});
|
|
9467
|
+
els.finSkillsOverlay.addEventListener('keydown', (e) => {
|
|
9468
|
+
if (e.key === 'Escape') { e.stopPropagation(); finSkillsCloseModal(); }
|
|
9469
|
+
});
|
|
9470
|
+
}
|
|
9471
|
+
|
|
9375
9472
|
if (els.finSymAdd) els.finSymAdd.addEventListener('click', finSymPickerOpen);
|
|
9376
9473
|
if (els.finWatchClear) {
|
|
9377
9474
|
els.finWatchClear.addEventListener('click', async () => {
|
package/src/renderer/style.css
CHANGED
|
@@ -5122,3 +5122,47 @@ body.finance-mode #composerWrap { margin-right: var(--finW, 400px); }
|
|
|
5122
5122
|
color: var(--muted);
|
|
5123
5123
|
text-align: center;
|
|
5124
5124
|
}
|
|
5125
|
+
|
|
5126
|
+
/* ROL → SKILL eşleştirme modalı (TRADE AJANI ⚙) */
|
|
5127
|
+
.fin-skills-dialog { width: 540px; max-width: calc(100vw - 40px); }
|
|
5128
|
+
.fin-skills-dialog .mini-body {
|
|
5129
|
+
flex: 1;
|
|
5130
|
+
min-height: 0;
|
|
5131
|
+
display: flex;
|
|
5132
|
+
flex-direction: column;
|
|
5133
|
+
overflow: hidden;
|
|
5134
|
+
}
|
|
5135
|
+
#finSkillsList {
|
|
5136
|
+
flex: 1;
|
|
5137
|
+
min-height: 0;
|
|
5138
|
+
overflow-y: auto;
|
|
5139
|
+
display: flex;
|
|
5140
|
+
flex-direction: column;
|
|
5141
|
+
gap: 10px;
|
|
5142
|
+
}
|
|
5143
|
+
.fin-skill-role {
|
|
5144
|
+
border: 1px solid var(--border);
|
|
5145
|
+
border-radius: 8px;
|
|
5146
|
+
padding: 8px 9px;
|
|
5147
|
+
background: var(--panel2);
|
|
5148
|
+
}
|
|
5149
|
+
.fin-skill-role-head { display: flex; flex-direction: column; gap: 1px; margin-bottom: 7px; }
|
|
5150
|
+
.fin-skill-role-head b { font-size: 11.5px; color: var(--text); }
|
|
5151
|
+
.fin-skill-role-head span { font-size: 10px; color: var(--muted); }
|
|
5152
|
+
.fin-skill-chips { display: flex; flex-wrap: wrap; gap: 4px; }
|
|
5153
|
+
.fin-skill-chip {
|
|
5154
|
+
display: inline-flex;
|
|
5155
|
+
align-items: center;
|
|
5156
|
+
gap: 4px;
|
|
5157
|
+
font-size: 10.5px;
|
|
5158
|
+
color: var(--text);
|
|
5159
|
+
background: var(--panel);
|
|
5160
|
+
border: 1px solid var(--border);
|
|
5161
|
+
border-radius: 8px;
|
|
5162
|
+
padding: 2px 8px 2px 5px;
|
|
5163
|
+
cursor: pointer;
|
|
5164
|
+
user-select: none;
|
|
5165
|
+
}
|
|
5166
|
+
.fin-skill-chip:hover { border-color: var(--accent); }
|
|
5167
|
+
.fin-skill-chip.on { border-color: var(--accent); color: var(--accent); background: var(--accent-dim); }
|
|
5168
|
+
.fin-skill-chip input { flex: none; width: auto; margin: 0; }
|