beast-agent 2.68.0 → 2.70.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "beast-agent",
3
3
  "productName": "Beast Agent",
4
- "version": "2.68.0",
4
+ "version": "2.70.0",
5
5
  "description": "Ultra-fast local agent shell for Windows.",
6
6
  "author": "algokodcom (AlgoKod)",
7
7
  "license": "MIT",
@@ -99,7 +99,9 @@ function plan(pos, meta, st, cfg) {
99
99
  }
100
100
 
101
101
  /* ---- kısmi TP ---- */
102
- if (partialR > 0 && partialPct > 0 && partialPct < 100 && r > 0 && !(st && st.partial) && profit >= partialR * r) {
102
+ /* partial = kısmi kapatma GERÇEKTEN yapıldı (Jev/kod); partialNotified =
103
+ yalnız bildirim gitti — ikisi de tekrar üretimi engeller */
104
+ if (partialR > 0 && partialPct > 0 && partialPct < 100 && r > 0 && !(st && (st.partial || st.partialNotified)) && profit >= partialR * r) {
103
105
  const step = num(meta.volume_step, 0.01);
104
106
  const vmin = num(meta.volume_min, 0.01);
105
107
  const vmax = num(meta.volume_max, 100);
package/src/main.js CHANGED
@@ -3632,12 +3632,12 @@ function reloadBackend() {
3632
3632
  try {
3633
3633
  let txt = '';
3634
3634
  if (ev.type === 'error') {
3635
- txt = '⚠️ [cron: ' + String((cjob && cjob.name) || 'görev') + ']\nHata: ' + String(ev.error || '').slice(0, 200);
3635
+ txt = '⚠️ [cronjob ' + String((cjob && cjob.id) || '?') + ']\nHata: ' + String(ev.error || '').slice(0, 200);
3636
3636
  } else {
3637
3637
  const s = engine.openSession(ev.sessionId);
3638
3638
  const lastA = [...s.messages].reverse().find((m) => m.role === 'assistant' && m.content);
3639
3639
  txt = typeof (lastA && lastA.content) === 'string' ? lastA.content : '';
3640
- if (txt.trim()) txt = '⏰ [cron: ' + String((cjob && cjob.name) || 'görev') + ']\n' + txt;
3640
+ if (txt.trim()) txt = '⏰ [cronjob ' + String((cjob && cjob.id) || '?') + ']\n' + txt;
3641
3641
  }
3642
3642
  if (!txt.trim()) return;
3643
3643
  for (const m of cronMirrorTargets(String(ev.sessionId))) {
@@ -8265,7 +8265,7 @@ function cronPump() {
8265
8265
  let sent = false;
8266
8266
  try {
8267
8267
  sent = engine.send(sid, {
8268
- text: `[cron: ${job.name}]\n${job.prompt}`,
8268
+ text: `[cronjob ${job.id}]\n${job.prompt}`,
8269
8269
  });
8270
8270
  } catch {}
8271
8271
  if (!sent) {
@@ -8278,7 +8278,7 @@ function cronPump() {
8278
8278
  return;
8279
8279
  }
8280
8280
  toastNotify(
8281
- `Cron: ${job.name}`,
8281
+ `cronjob ${job.id}`,
8282
8282
  isReminderJob(job) ? 'Hatırlatma zamanı geldi' : String(job.prompt || '').slice(0, 160),
8283
8283
  'cron'
8284
8284
  );
@@ -10146,17 +10146,12 @@ function finHoursPause(reason) {
10146
10146
  /* Duraklatılan tek ajanı geri aç (ekip rolü ya da sembol işçisi). */
10147
10147
  function finHoursSpawn(role, symbol) {
10148
10148
  if (!engine) return false;
10149
- const f = finCfg();
10150
10149
  try {
10151
10150
  const created = role ? finAgentCreate([], false, role) : finAgentCreate([symbol], false);
10152
- try { engine.setSessionModel(created.s.id, f.traderSel || null); } catch {}
10153
- const ok = engine.send(created.s.id, finTraderBrief(created.agent), { userAction: true });
10154
- if (!ok) {
10155
- finAgentStop(String(created.s.id), 'saat açılışı — oturum meşgul');
10156
- return false;
10157
- }
10151
+ /* JEV-ONLY: LLM turu YOK — TypeSafe turu hemen kuyruğa girer */
10152
+ finTypeSafeKick(String(created.s.id), created.agent);
10158
10153
  const roleDef = role ? finRoleDef(role) : null;
10159
- financeLog('[saat] ' + (roleDef ? roleDef.label : symbol) + ' geri başlatıldı');
10154
+ financeLog('[saat] ' + (roleDef ? roleDef.label : symbol) + ' geri başlatıldı (JEV)');
10160
10155
  return true;
10161
10156
  } catch {
10162
10157
  return false;
@@ -11156,8 +11151,8 @@ function finWakeAgentDm(sid, text) {
11156
11151
  finTradeHoursBlockedLog('olay uyandırması');
11157
11152
  return false;
11158
11153
  }
11159
- /* TYPESAFE-ONLY: LLM turu BAŞLATILMAZ — olay TS turunu öne çeker; prompt/
11160
- pendingReports hattı (engine.send) bu modda hiç kullanılmaz */
11154
+ /* JEV-ONLY: LLM turu BAŞLATILMAZ — olay TS turunu öne çeker; prompt/
11155
+ pendingReports hattı (engine.send) finance ajanlarında hiç kullanılmaz */
11161
11156
  if (finTsAgentMode(agent)) {
11162
11157
  if (!agent.tsBusy) finTypeSafeKick(id, agent);
11163
11158
  return true;
@@ -11201,6 +11196,13 @@ function finWakeAgents(text, meta) {
11201
11196
  engine._agentTeamPost('team:finance', 'finance', 'Beast Finance', body);
11202
11197
  }
11203
11198
  } catch {}
11199
+ /* JEV TURU OLAYI GÖRSÜN: uyanan TypeSafe turunun state'ine (ekip_yanitlari)
11200
+ olay metni de girer — ajan "neden uyandım" bağlamını kaybetmez */
11201
+ try {
11202
+ financeState.tsFeed = Array.isArray(financeState.tsFeed) ? financeState.tsFeed : [];
11203
+ financeState.tsFeed.push({ at: Date.now(), sid: 'finance', who: 'Beast Finance', text: body });
11204
+ while (financeState.tsFeed.length > 30) financeState.tsFeed.shift();
11205
+ } catch {}
11204
11206
  if (!financeState.agents.size) {
11205
11207
  financeLog('[olay] koşan finance ajanı yok — uyarı yalnız günlük/bildirimde' + (meta && meta.kind ? ' (' + meta.kind + ')' : ''));
11206
11208
  return 0;
@@ -11503,10 +11505,11 @@ async function finWatchTick() {
11503
11505
  finJournal({ kind: 'watchdog', action: 'sl-move', ticket, symbol: p.symbol, sl: act.sl });
11504
11506
  }
11505
11507
  } else if (act.kind === 'partial') {
11506
- /* OTOMATİK KAPATMA YOK — kısmi TP/stop kararını AJAN verir: seviye
11507
- gelince ajanlar TUR BEKLEMEDEN uyandırılır; uygun görürse
11508
- mt5_close {percent, kind:"partial_tp"} ile kısmi kâr alır. */
11509
- st.partial = true;
11508
+ /* OTOMATİK KAPATMA YOK — kısmi kapatma kararını JEV verir: seviye
11509
+ gelince Jev turu TUR BEKLEMEDEN uyanır ve tur içinde karar verir.
11510
+ primary flag 'partial' GERÇEK kapatmaya ayrıldı; burada yalnız
11511
+ bildirim tekrarını engelleyen 'partialNotified' işaretlenir. */
11512
+ st.partialNotified = true;
11510
11513
  const rNow = decision.r > 0
11511
11514
  ? Math.round(((Number(p.type) === 0 ? Number(p.price_current) - Number(p.price_open) : Number(p.price_open) - Number(p.price_current)) / decision.r) * 10) / 10
11512
11515
  : 0;
@@ -11654,18 +11657,9 @@ async function finWeeklyReport(manual) {
11654
11657
  capture: mfeSumMfe > 0 ? Math.round((mfeSumNet / mfeSumMfe) * 100) : null,
11655
11658
  avgMaeLoss: mfeLoss.length ? Math.round((mfeLoss.reduce((a, e) => a + Math.abs(Number(e.mae)), 0) / mfeLoss.length) * 100) / 100 : null,
11656
11659
  } : null;
11657
- let review = '';
11658
- if (engine) {
11659
- try {
11660
- const task =
11661
- 'Beast Finance haftalık performans değerlendirmesi: aşağıdaki istatistik ve işlem günlüğünü ELEŞTİREL yorumla. ' +
11662
- 'Ne iyi gitti, hangi hatalar tekrarlandı, gelecek hafta ne değişmeli? En fazla 12 satır, madde madde, Türkçe.';
11663
- const ctx = JSON.stringify({ stats, drawdown, journal: journal.slice(-20) }).slice(0, 12000);
11664
- const signal = typeof AbortSignal !== 'undefined' && AbortSignal.timeout ? AbortSignal.timeout(120000) : undefined;
11665
- const res = await engine._subagent(task, ctx, signal, null, '');
11666
- review = String(res || '').trim().slice(0, 4000);
11667
- } catch {}
11668
- }
11660
+ /* JEV-ONLY: haftalık yorum LLM'e YAZDIRILMAZ — rapor tamamen kod
11661
+ istatistiklerinden (finstats) üretilir. */
11662
+ const review = '';
11669
11663
  const md = finstats.buildWeeklyReport({ stats, drawdown, equity, journal, account, positions, fromTs, toTs: now, review, mfe });
11670
11664
  const day = finstats.dayKey(now);
11671
11665
  const file = path.join(financeDir(), 'reports', 'weekly-' + day + '.md');
@@ -12270,6 +12264,8 @@ function finLearnSummaryPrompt(sym, e, oldNotes) {
12270
12264
  /* Bir sembolü özetle: snapshot'taki ESKİ dersleri modele özetlet, onları düş,
12271
12265
  yerine kalıcı özet yaz. Model çalışırken gelen YENİ dersler ham kalır. */
12272
12266
  async function finLearnCompactSymbol(symbol, force) {
12267
+ /* JEV-ONLY: finance hafıza özetlemesi LLM İLE YAPILMAZ (kapı) */
12268
+ return { ok: false, error: 'LLM özetleme JEV-ONLY modunda kapalı' };
12273
12269
  const sym = String(symbol || '').trim().toUpperCase();
12274
12270
  if (!sym) return { ok: false, error: 'symbol gerekli' };
12275
12271
  if (finLearnCompacting.has(sym)) return { ok: false, error: 'bu sembol şu an özetleniyor' };
@@ -12321,9 +12317,10 @@ async function finLearnCompactSymbol(symbol, force) {
12321
12317
  }
12322
12318
  }
12323
12319
 
12324
- /* Arka plan tetikleyici: ajanı BEKLETMEDEN özetler (notlar birikince) */
12320
+ /* Arka plan tetikleyici: Beast Finance = JEV-ONLY olduğu için LLM özetleme
12321
+ KAPALI; ham dersler tavan (60) + TTL (30 gün) ile kendiliğinden sadeleşir. */
12325
12322
  function finLearnCompactAuto(sym) {
12326
- try { finLearnCompactSymbol(sym, false).catch(() => {}); } catch {}
12323
+ void sym;
12327
12324
  }
12328
12325
 
12329
12326
  function finLearnSym(symbol) {
@@ -12667,12 +12664,12 @@ function finLearnApi() {
12667
12664
  if (r.notes || r.trades || r.symbols) finLearnSave();
12668
12665
  return { ok: true, ...r };
12669
12666
  },
12670
- compact: ({ symbol } = {}) => {
12671
- /* OPENCODE TARZI ÖZETLEME (elle): eski dersleri modele özetlet,
12672
- ham yalnız son dersler kalsın */
12673
- const sym = norm(symbol);
12674
- if (!sym) return Promise.resolve({ ok: false, error: 'compact için symbol gerekli' });
12675
- return finLearnCompactSymbol(sym, true);
12667
+ compact: () => {
12668
+ /* JEV-ONLY: LLM özetleme KAPATILDI — dersler tavan + TTL ile sadeleşir */
12669
+ return Promise.resolve({
12670
+ ok: false,
12671
+ error: 'LLM özetleme JEV-ONLY modunda kapalı — dersler tavan (60) + 30 gün TTL ile otomatik sadeleşir',
12672
+ });
12676
12673
  },
12677
12674
  };
12678
12675
  }
@@ -13446,16 +13443,19 @@ function finDailyRoutine(mode) {
13446
13443
  const agent = financeState.agents.get(mainSid);
13447
13444
  const s = engine.cache.get(mainSid);
13448
13445
  if (s) finApplyTraderFields(s, agent.symbols, agent.role, true);
13449
- if (engine.isBusy(mainSid)) {
13450
- financeLog('[rutin] trader meşgul — günlük ' + mode + ' atlandı');
13451
- return;
13452
- }
13453
- const digest = finBuildDigest();
13454
- const text = mode === 'plan'
13455
- ? 'GÜNLÜK PLAN (açılış rutini): Bugün için net bir plan yap — izleme listesini ve piyasa koşullarını tara; sembol başına yön eğilimi, izlenecek seviyeler ve risk planı (kaç işlem, hangi setup/kurulum, günlük kayıp sınırı) yaz. Zorunlu işlem yok. Planı mt5_note ile günlüğe kaydet.\n\nİŞLEM GEÇMİŞİN:\n' + digest
13456
- : 'GÜNLÜK REVIEW (kapanış rutini): Bugünün işlemlerini ve performans geçmişini değerlendir — hangi kararlar işledi, hangileri hata; kâr yakalama (MFE) ve MAE verisine bak; açık pozisyonların SL/TP\'lerini kontrol et, korumasız bırakma; yarın için 2-3 somut ders çıkar ve mt5_note ile kaydet.\n\nİŞLEM GEÇMİŞİN:\n' + digest;
13457
- const ok = engine.send(mainSid, text, { userAction: true });
13458
- financeLog('[rutin] günlük ' + mode + (ok ? ' gönderildi' : ' gönderilemedi (meşgul)'));
13446
+ /* JEV-ONLY: günlük plan/review de LLM'SİZ koşar — trader'ın TypeSafe turu
13447
+ hemen tetiklenir (işlem geçmişi/öğrenme digest'i tur state'ine zaten
13448
+ gömülür); AJAN DM'e rutin notu düşer. */
13449
+ try { finTypeSafeKick(mainSid, agent); } catch {}
13450
+ finTsPost(
13451
+ mainSid,
13452
+ agent,
13453
+ mode === 'plan'
13454
+ ? '📅 GÜNLÜK PLAN rutini tetiklendi — TypeSafe turu koşuyor (LLM yok)'
13455
+ : '🧾 GÜNLÜK REVIEW rutini tetiklendi — TypeSafe turu koşuyor (LLM yok)',
13456
+ 'rutin'
13457
+ );
13458
+ financeLog('[rutin] günlük ' + mode + ' TypeSafe turu tetiklendi');
13459
13459
  } catch {}
13460
13460
  }
13461
13461
 
@@ -13484,6 +13484,8 @@ function finSyncScheduleJobs() {
13484
13484
  (_subagent) hesap/pozisyon/strateji bağlamıyla kısa işlem planı üretir.
13485
13485
  Plan, tur mesajına [ANA AJAN PLANI] bloğu olarak eklenir. */
13486
13486
  async function finConsultPlan(f, agent, sid) {
13487
+ /* JEV-ONLY: finance ajanları için LLM danışma planı ÜRETİLMEZ (kapı) */
13488
+ return '';
13487
13489
  if (!engine) return '';
13488
13490
  let account = null;
13489
13491
  let positions = [];
@@ -13581,13 +13583,14 @@ function finTeamWaitTick(sid) {
13581
13583
  finAgentRound(sid, { noTeamWait: true });
13582
13584
  }
13583
13585
 
13584
- /* ---------- TYPESAFE-ONLY FİNANS MODU (LLM'SİZ) ----------
13585
- Rol→Skill eşleştirmesinde "typesafe-ai" seçiliyse ajan LLM HİÇ kullanmaz:
13586
- tur verisi (fiyat/gösterge/pozisyon/öğrenme geçmişi/ekip yanıtları) YALNIZ
13587
- TypeSafe System One'a gider; yanıtlar olasılık olarak döner, kararı KOD
13588
- uygular. Yanıtlar AJAN DM ekip grubuna yazılır — tüm ajanlar birbirinin
13589
- cevabını görür (son yanıtlar sonraki turların state'ine de girer) ve emirler
13590
- YALNIZ market buy/sell olarak açılır (bekleyen emir YOK). */
13586
+ /* ---------- JEV-ONLY FİNANS AJAN MODU (LLM'SİZ, SABİT) ----------
13587
+ TÜM finance ajanları (Trader + analiz ekibi + sembol işçileri) LLM HİÇ
13588
+ kullanmaz: tur verisi (fiyat/gösterge/pozisyon/öğrenme geçmişi/ekip
13589
+ yanıtları) YALNIZ TypeSafe System One'a gider; yanıtlar olasılık olarak
13590
+ döner, kararı KOD uygular. Yanıtlar AJAN DM ekip grubuna yazılır — tüm
13591
+ ajanlar birbirinin cevabını görür (son yanıtlar sonraki turların state'ine
13592
+ de girer) ve emirler YALNIZ market buy/sell olarak açılır (bekleyen emir
13593
+ YOK). LLM yalnız finance SOHBET yardımcısında serbesttir. */
13591
13594
  const FIN_TS_MARGIN_P = 0.12; /* birinci ile ikinci seçenek arası min fark */
13592
13595
  const FIN_TS_CONFIRM_P = 0.55; /* noul teyit eşiği */
13593
13596
  const FIN_TS_EXIT_P = 0.62; /* pozisyon kapatma eşiği */
@@ -13617,15 +13620,11 @@ const FIN_TS_ROLE_CRIT = {
13617
13620
  };
13618
13621
 
13619
13622
  function finTsAgentMode(agent) {
13620
- try {
13621
- const f = finCfg();
13622
- const key = agent && agent.main ? 'trader' : String((agent && agent.role) || '');
13623
- if (!key) return false;
13624
- const list = f.roleSkills && Array.isArray(f.roleSkills[key]) ? f.roleSkills[key] : [];
13625
- return list.some((s) => String(s || '').toLowerCase() === 'typesafe-ai');
13626
- } catch {
13627
- return false;
13628
- }
13623
+ /* BEAST FINANCE = JEV-ONLY (sabit kural): Trader + analiz ekibi + sembol
13624
+ işçileri LLM ASLA kullanmaz — her tur deterministik TypeSafe System One
13625
+ hattıyla koşar (veri koda toplanır, karar Jev'den gelir, emir koda
13626
+ uygulanır). LLM yalnız finance SOHBET yardımcısında serbesttir. */
13627
+ return !!agent;
13629
13628
  }
13630
13629
 
13631
13630
  function finTsWho(agent, extra) {
@@ -13738,6 +13737,131 @@ function finTsIndLine(ind) {
13738
13737
  };
13739
13738
  }
13740
13739
 
13740
+ /* AÇIK POZİSYON ÖZETİ (TypeSafe state girdisi): R mesafesi, kâr R'si, görülen
13741
+ en iyi R ve koruma bayrakları — Jev'in pozisyon yönetimi kararları bunlara
13742
+ dayanır. Saf okuma; hiçbir IO/karar yok. */
13743
+ function finTsPosState(p) {
13744
+ const st = financeState.watch.get(String((p && p.ticket) || '')) || null;
13745
+ const entry = Number(p && p.price_open) || 0;
13746
+ const ref = Number(p && p.price_current) || 0;
13747
+ const sl = Number(p && p.sl) || 0;
13748
+ const isBuy = Number(p && p.type) === 0;
13749
+ let r = Number(st && st.r) || 0;
13750
+ if (!(r > 0) && sl > 0 && entry > 0) r = Math.abs(entry - sl);
13751
+ const profitDist = entry > 0 && ref > 0 ? (isBuy ? ref - entry : entry - ref) : 0;
13752
+ const bestDist = st && isFinite(Number(st.bestProfit)) ? Number(st.bestProfit) : profitDist;
13753
+ const round2 = (v) => Math.round(v * 100) / 100;
13754
+ return {
13755
+ ticket: p.ticket, sembol: p.symbol, yon: isBuy ? 'buy' : 'sell',
13756
+ hacim: p.volume, giris: p.price_open, sl: p.sl, tp: p.tp, kar: p.profit,
13757
+ fiyat: ref || null,
13758
+ r_mesafe: r > 0 ? Math.round(r * 1e6) / 1e6 : null,
13759
+ kz_r: r > 0 && entry > 0 && ref > 0 ? round2(profitDist / r) : null,
13760
+ en_iyi_r: r > 0 && entry > 0 && ref > 0 && isFinite(bestDist) ? round2(bestDist / r) : null,
13761
+ be: !!(st && st.be),
13762
+ kismi_alindi: !!(st && st.partial),
13763
+ };
13764
+ }
13765
+
13766
+ /* AÇIK POZİSYON YÖNETİMİ (JEV): tur yanıtındaki kısmi kapatma + SL/koruma
13767
+ kararını KOD uygular. Seviyeler deterministik (R/ATR tabanlı) hesaplanır,
13768
+ broker min mesafesine kırpılır ve SL ASLA geriye (risk yönüne) taşınmaz.
13769
+ Kısmi kapatma pozisyon başına BİR kez uygulanır (st.partial). */
13770
+ async function finTsManageOpen(sidS, agent, sym, pos, mkt, ans, qi, lines) {
13771
+ const st = financeState.watch.get(String(pos.ticket)) || null;
13772
+ /* kısmi kapatma pozisyon başına BİR kez: watchdog kaydı yoksa ajan üstünde izle */
13773
+ const partialDone = !!(st && st.partial) || !!(agent && agent.tsPartials && agent.tsPartials.has(String(pos.ticket)));
13774
+ const isBuy = Number(pos.type) === 0;
13775
+ const entry = Number(pos.price_open) || 0;
13776
+ const ref = Number(pos.price_current) || 0;
13777
+ const slNow = Number(pos.sl) || 0;
13778
+ const row = (mkt && mkt.row) || {};
13779
+ const digits = Math.max(0, Math.min(8, Number(row.digits) || 2));
13780
+ const rnd = (v) => Number(Number(v).toFixed(digits));
13781
+ const point = Number(row.point) > 0 ? Number(row.point) : Math.pow(10, -digits);
13782
+ const stopsPts = Number(row.trade_stops_level) || 0;
13783
+ const minDist = stopsPts > 0 ? (stopsPts + 1) * point : point;
13784
+ const atr = Number(mkt && mkt.ind && mkt.ind.atr14) || 0;
13785
+ let rDist = Number(st && st.r) || 0;
13786
+ if (!(rDist > 0) && slNow > 0 && entry > 0) rDist = Math.abs(entry - slNow);
13787
+ const base = rDist > 0 ? rDist : atr > 0 ? atr * 1.5 : ref > 0 ? ref * 0.003 : 0;
13788
+ const profitDist = entry > 0 && ref > 0 ? (isBuy ? ref - entry : entry - ref) : 0;
13789
+
13790
+ /* ---- KISMİ KAPATMA (kısmi TP / kısmi stop): karar Jev'in, uygulama kodun */
13791
+ const par = finTsChoice(ans, 'kismi_' + qi);
13792
+ const pct = par && par.p >= FIN_TS_CONFIRM_P && par.p - par.second >= FIN_TS_MARGIN_P
13793
+ ? ({ yuzde25: 25, yuzde50: 50, yuzde75: 75 }[String(par.choice)] || 0)
13794
+ : 0;
13795
+ if (pct > 0 && !partialDone) {
13796
+ const kind = profitDist >= 0 ? 'partial_tp' : 'partial_sl';
13797
+ let r = null;
13798
+ try {
13799
+ r = await financetools.handlers.mt5_close(
13800
+ {
13801
+ ticket: Number(pos.ticket),
13802
+ percent: pct,
13803
+ kind,
13804
+ reason: `TypeSafe: kısmi %${pct} p=${par.p.toFixed(2)} (${kind === 'partial_tp' ? 'kâr al' : 'zarar kes'})`,
13805
+ },
13806
+ { sessionId: sidS }
13807
+ );
13808
+ } catch (e) {
13809
+ r = { ok: false, error: String((e && e.message) || e) };
13810
+ }
13811
+ if (r && r.ok) {
13812
+ if (st) { st.partial = true; finWatchSave(); }
13813
+ if (agent) { agent.tsPartials = agent.tsPartials || new Set(); agent.tsPartials.add(String(pos.ticket)); }
13814
+ lines.push(
13815
+ `- ${sym} #${pos.ticket}: KISMİ %${pct} ${kind === 'partial_tp' ? 'TP ✓' : 'STOP ✓'}` +
13816
+ ` (p=${par.p.toFixed(2)}${r.remaining != null ? ', kalan ' + r.remaining + ' lot' : ''})`
13817
+ );
13818
+ } else {
13819
+ lines.push(`- ${sym} #${pos.ticket}: kısmi %${pct} reddedildi — ${(r && r.error) || 'hata'}`);
13820
+ }
13821
+ } else if (pct > 0 && partialDone) {
13822
+ lines.push(`- ${sym} #${pos.ticket}: kısmi atlandı — daha önce alındı`);
13823
+ }
13824
+
13825
+ /* ---- SL / KORUMA: yalnız İYİLEŞTİRME yönünde, kârsızda mevcut SL'ye dokunma */
13826
+ const slc = finTsChoice(ans, 'sl_' + qi);
13827
+ if (!slc || slc.p < FIN_TS_CONFIRM_P || slc.p - slc.second < FIN_TS_MARGIN_P) return;
13828
+ const choice = String(slc.choice || '');
13829
+ if (choice === 'birak' || !(ref > 0)) return;
13830
+ if (profitDist <= 0 && slNow > 0) {
13831
+ lines.push(`- ${sym} #${pos.ticket}: SL kararı (${choice}) uygulanmadı — kâr yok`);
13832
+ return;
13833
+ }
13834
+ if (!(base > 0)) return;
13835
+ let desired = 0;
13836
+ if (choice === 'be' && rDist > 0) desired = isBuy ? entry + 0.05 * rDist : entry - 0.05 * rDist;
13837
+ else if (choice === 'trail') desired = isBuy ? ref - 0.5 * base : ref + 0.5 * base;
13838
+ else if (choice === 'sikilastir') desired = isBuy ? ref - Math.max(0.3 * base, minDist + point) : ref + Math.max(0.3 * base, minDist + point);
13839
+ else if (choice === 'koru' && slNow <= 0) desired = isBuy ? ref - Math.max(atr > 0 ? atr * 1.5 : base, minDist + point) : ref + Math.max(atr > 0 ? atr * 1.5 : base, minDist + point);
13840
+ if (!(desired > 0)) return;
13841
+ desired = isBuy ? Math.min(desired, ref - minDist) : Math.max(desired, ref + minDist);
13842
+ const improved = slNow <= 0 || (isBuy ? desired > slNow + point * 0.5 : desired < slNow - point * 0.5);
13843
+ if (!improved) {
13844
+ lines.push(`- ${sym} #${pos.ticket}: SL (${choice}) iyileştirme değil — dokunulmadı`);
13845
+ return;
13846
+ }
13847
+ let mod = null;
13848
+ try {
13849
+ mod = await financetools.handlers.mt5_modify(
13850
+ { ticket: Number(pos.ticket), sl: rnd(desired), tp: Number(pos.tp) || 0 },
13851
+ { sessionId: sidS }
13852
+ );
13853
+ } catch (e) {
13854
+ mod = { ok: false, error: String((e && e.message) || e) };
13855
+ }
13856
+ const label = { be: 'breakeven', trail: 'trailing', sikilastir: 'sıkılaştırma', koru: 'koruma' }[choice] || choice;
13857
+ if (mod && mod.ok) {
13858
+ if (st) { st.be = true; finWatchSave(); }
13859
+ lines.push(`- ${sym} #${pos.ticket}: SL ${label} → ${rnd(desired)} ✓ (p=${slc.p.toFixed(2)})`);
13860
+ } else {
13861
+ lines.push(`- ${sym} #${pos.ticket}: SL ${label} reddedildi — ${(mod && mod.error) || 'hata'}`);
13862
+ }
13863
+ }
13864
+
13741
13865
  function finTsSchedule(sid, agent, sec) {
13742
13866
  if (!agent || !financeState.agents.has(String(sid))) return;
13743
13867
  clearTimeout(agent.timer);
@@ -13757,15 +13881,21 @@ async function finTypeSafeRound(sid, agent) {
13757
13881
  if (!agent || !engine || agent.tsBusy) return;
13758
13882
  agent.tsBusy = true;
13759
13883
  const sidS = String(sid);
13760
- const isTrader = !!agent.main;
13884
+ /* SEMBOL İŞÇİSİ (rolü olmayan ajan) da otonom işlem açabilir — trader
13885
+ karar hattını kullanır; rol ajanları yalnız analiz üretir. */
13886
+ const isTrader = !!agent.main || !String(agent.role || '');
13761
13887
  const role = String(agent.role || '');
13762
- const roleLabel = isTrader ? 'TRADER (ana karar verici)' : ((finRoleDef(role) || {}).label || role || 'finans');
13888
+ const roleLabel = agent.main
13889
+ ? 'TRADER (ana karar verici)'
13890
+ : isTrader
13891
+ ? 'SEMBOL İŞÇİSİ (otonom)'
13892
+ : ((finRoleDef(role) || {}).label || role || 'finans');
13763
13893
  try {
13764
13894
  if (!typesafeMod.cfg().apiKey) {
13765
13895
  const now = Date.now();
13766
13896
  if (!agent.tsNoKeyAt || now - agent.tsNoKeyAt > 10 * 60 * 1000) {
13767
13897
  agent.tsNoKeyAt = now;
13768
- finTsPost(sidS, agent, '⚠ TypeSafe API anahtarı yok — bu rol typesafe-ai modunda ve LLM KULLANILMIYOR; tur atlanıyor. Sahibe söyle: Ayarlar → TypeSafe sekmesinden anahtar girilmeli.', 'anahtar');
13898
+ finTsPost(sidS, agent, '⚠ TypeSafe API anahtarı yok — finance ajanları JEV-ONLY çalışır ve LLM KULLANILMIYOR; tur atlanıyor. Sahibe söyle: Ayarlar → TypeSafe sekmesinden anahtar girilmeli.', 'anahtar');
13769
13899
  }
13770
13900
  return;
13771
13901
  }
@@ -13789,7 +13919,7 @@ async function finTypeSafeRound(sid, agent) {
13789
13919
  return;
13790
13920
  }
13791
13921
  agent.round = (Number(agent.round) || 0) + 1;
13792
- if (isTrader) {
13922
+ if (agent.main) {
13793
13923
  financeState.traderRounds = agent.round;
13794
13924
  finPush('trader', { state: 'running', round: agent.round, mode: 'typesafe' });
13795
13925
  }
@@ -13824,10 +13954,9 @@ async function finTypeSafeRound(sid, agent) {
13824
13954
  acik_pozisyon: posList.length,
13825
13955
  },
13826
13956
  limitler: { max_pozisyon: Number(f.maxPositions) || 3, min_lot: Number(f.minLot) || 0.01, max_lot: Number(f.maxLot) || 0.1 },
13827
- pozisyonlar: posList.map((p) => ({
13828
- ticket: p.ticket, sembol: p.symbol, yon: Number(p.type) === 0 ? 'buy' : 'sell',
13829
- hacim: p.volume, giris: p.price_open, sl: p.sl, tp: p.tp, kar: p.profit,
13830
- })),
13957
+ /* AÇIK POZİSYONLAR: R/kâr R'si/en iyi R + koruma bayrakları — Jev'in
13958
+ kapatma/kısmi/SL kararları bu bağlamla verilir (finTsPosState) */
13959
+ pozisyonlar: posList.map((p) => finTsPosState(p)),
13831
13960
  piyasa: {},
13832
13961
  ogrenme: finBuildLearnDigest(symbols),
13833
13962
  /* KALİBRASYON: öğrenilmiş eşik + risk çarpanı + kazandıran kurallar */
@@ -13846,7 +13975,7 @@ async function finTypeSafeRound(sid, agent) {
13846
13975
  };
13847
13976
  }
13848
13977
 
13849
- /* ---------------- TRADER: yön + teyit + kapat kararı ---------------- */
13978
+ /* -------- TRADER: yön + teyit + açık pozisyon yönetimi (kapat/kısmi/SL) -------- */
13850
13979
  if (isTrader) {
13851
13980
  const posBySym = {};
13852
13981
  for (const p of posList) {
@@ -13871,11 +14000,36 @@ async function finTypeSafeRound(sid, agent) {
13871
14000
  };
13872
14001
  if (posBySym[sym]) {
13873
14002
  const pp = posBySym[sym];
14003
+ const ps = finTsPosState(pp);
14004
+ const kzTxt = ps.kz_r == null ? 'R bilinmiyor' : `kâr ${ps.kz_r}R`;
14005
+ const bestTxt = ps.en_iyi_r == null ? '' : ` · en iyi ${ps.en_iyi_r}R`;
14006
+ const slTxt = Number(pp.sl) > 0 ? `SL ${pp.sl}` : 'SL YOK';
13874
14007
  questions['kapat_' + i] = {
13875
14008
  type: 'noul',
13876
- instructions: `${sym} açık pozisyon (${Number(pp.type) === 0 ? 'buy' : 'sell'}, kâr ${Number(pp.profit) || 0}) ŞİMDİ kapatılmalı mı? Kârı koruma, momentum dönüşü veya SL/TP yakınlığını değerlendir.`,
14009
+ instructions: `${sym} açık pozisyon (${ps.yon}, kâr ${Number(pp.profit) || 0}, ${kzTxt}${bestTxt}, ${slTxt}) ŞİMDİ kapatılmalı mı? Kârı koruma, kâr geri verme, momentum dönüşü veya SL/TP yakınlığını değerlendir.`,
13877
14010
  criteria: { true: 'Kapat — risk/kâr koruma', false: 'Açık kalsın — tez sürüyor' },
13878
14011
  };
14012
+ questions['kismi_' + i] = {
14013
+ type: 'choice',
14014
+ instructions: `${sym} açık pozisyon (${kzTxt}${bestTxt}${ps.be ? ' · SL takipte' : ''}) için ŞİMDİ kısmi kapatma uygun mu?${ps.kismi_alindi ? ' Bu pozisyonda kısmi kapatma ZATEN yapıldı — yok seç.' : ' Kârı realize etmek/riski azaltmak için değerlendir.'}`,
14015
+ criteria: {
14016
+ yok: 'Kısmi kapatma yok — pozisyon tam kalsın',
14017
+ yuzde25: 'Pozisyonun %25’i kapatılsın',
14018
+ yuzde50: 'Pozisyonun %50’si kapatılsın',
14019
+ yuzde75: 'Pozisyonun %75’i kapatılsın',
14020
+ },
14021
+ };
14022
+ questions['sl_' + i] = {
14023
+ type: 'choice',
14024
+ instructions: `${sym} açık pozisyonu için SL/koruma aksiyonu: ${ps.yon}, giriş ${Number(pp.price_open) || '?'}, şimdi ${ps.fiyat || '?'}, ${slTxt}, ${kzTxt}. Kâr yoksa ve SL varsa 'birak'; SL yoksa 'koru' ile koruma koy.`,
14025
+ criteria: {
14026
+ birak: 'Dokunma — SL yerinde kalsın',
14027
+ be: 'Breakeven — SL girişe çekilsin (kârı kilitle)',
14028
+ trail: 'Trailing — SL fiyatın gerisine taşınsın (kârı takip et)',
14029
+ sikilastir: 'Sıkılaştır — SL fiyata yaklaştırılsın (kârı daha çok koru)',
14030
+ koru: 'Koruma koy — SL’siz pozisyona ATR tabanlı stop eklensin',
14031
+ },
14032
+ };
13879
14033
  }
13880
14034
  });
13881
14035
  let ans = null;
@@ -13911,6 +14065,8 @@ async function finTypeSafeRound(sid, agent) {
13911
14065
  lines.push(`- ${sym}: KAPAT (p=${ex.toFixed(2)}) ${r && r.ok ? '✓ pozisyon kapatıldı' : '✗ ' + ((r && r.error) || 'hata')}`);
13912
14066
  } else {
13913
14067
  lines.push(`- ${sym}: pozisyon açık (kapat=${ex == null ? 'yanıt yok' : ex.toFixed(2)} < ${FIN_TS_EXIT_P}) — tez sürüyor`);
14068
+ /* JEV POZİSYON YÖNETİMİ: kısmi kapatma + SL/koruma kararları */
14069
+ try { await finTsManageOpen(sidS, agent, sym, pos, market[sym], ans, i, lines); } catch {}
13914
14070
  }
13915
14071
  continue;
13916
14072
  }
@@ -14056,7 +14212,7 @@ async function finTypeSafeRound(sid, agent) {
14056
14212
  } finally {
14057
14213
  agent.tsBusy = false;
14058
14214
  finTsSchedule(sidS, agent, finPaceSec());
14059
- if (isTrader && financeState.agents.has(sidS)) finPush('trader', { state: 'idle', round: agent.round, mode: 'typesafe' });
14215
+ if (agent.main && financeState.agents.has(sidS)) finPush('trader', { state: 'idle', round: agent.round, mode: 'typesafe' });
14060
14216
  }
14061
14217
  }
14062
14218
 
@@ -14077,9 +14233,9 @@ function finAgentRound(sid, opts) {
14077
14233
  /* hâlâ çalışıyor — done eventinde tekrar planlanır */
14078
14234
  return;
14079
14235
  }
14080
- /* TYPESAFE-ONLY MODU: roleSkills'te typesafe-ai varsa LLM HİÇ kullanılmaz —
14081
- tur deterministik TypeSafe hattıyla koşar (girdi yalnız TypeSafe'e gider,
14082
- cevaplar AJAN DM'e düşer, emirler yalnız market buy/sell) */
14236
+ /* JEV-ONLY (SABİT): finance ajanları LLM HİÇ kullanmaz — tur deterministik
14237
+ TypeSafe hattıyla koşar (girdi yalnız TypeSafe'e gider, cevaplar AJAN
14238
+ DM'e düşer, emirler yalnız market buy/sell) */
14083
14239
  if (finTsAgentMode(agent)) {
14084
14240
  finTypeSafeRound(String(sid), agent).catch(() => {});
14085
14241
  return;
@@ -14578,7 +14734,9 @@ async function financeTraderStart() {
14578
14734
  const th = f.tradeHours || {};
14579
14735
  return { ok: false, error: `trade saatleri dışı (${th.start || '09:00'}-${th.end || '22:00'} yerel) — pencere açılınca ajanlar otomatik başlar` };
14580
14736
  }
14581
- if (!engine.publicState().hasModel && !f.traderSel) return { ok: false, error: 'model yok — Ayarlar → Provider' };
14737
+ /* JEV-ONLY: LLM modeli GEREKMEZ — anahtar kapısı TypeSafe'tir */
14738
+ const tsGate = typesafeMod.unavailable();
14739
+ if (tsGate) return { ok: false, error: tsGate };
14582
14740
  try { finSyncScheduleJobs(); } catch {} /* plan/review saatleri trader açılışında garantiye alınır */
14583
14741
  /* ANA trader: varsa aynen sürdür, yoksa yeni sürekli ajan aç */
14584
14742
  let mainSid = '';
@@ -14600,27 +14758,15 @@ async function financeTraderStart() {
14600
14758
  mainSid = String(created.s.id);
14601
14759
  mainAgent = created.agent;
14602
14760
  }
14603
- try { engine.setSessionModel(mainSid, f.traderSel || null); } catch {}
14604
14761
  financeState.traderOn = true;
14605
14762
  try { engine.clearStop(); } catch {}
14606
- /* TYPESAFE-ONLY: roleSkills.trader'da typesafe-ai varsa LLM'e HİÇ gidilmez */
14607
- if (finTsAgentMode(mainAgent)) {
14608
- financeState.lastRoundAt = Date.now();
14609
- financeLog('[trader] başlatıldı (TYPESAFE-ONLY — LLM kullanılmıyor, girdi yalnız TypeSafe)');
14610
- finPush('trader', { state: 'running', round: mainAgent.round, mode: 'typesafe' });
14611
- finTypeSafeKick(mainSid, mainAgent);
14612
- finTeamStart(f);
14613
- return { ok: true, sid: mainSid };
14614
- }
14615
- const ok = engine.send(mainSid, finTraderBrief(mainAgent), { userAction: true });
14616
- if (!ok) {
14617
- financeState.traderOn = false;
14618
- return { ok: false, error: 'trader oturumu meşgul — birkaç saniye sonra tekrar dene' };
14619
- }
14763
+ /* JEV-ONLY (SABİT): Trader HER ZAMAN TypeSafe turuyla koşar — LLM'e HİÇ
14764
+ gidilmez (girdi koda toplanır, karar Jev'den gelir, emir koda uygulanır). */
14620
14765
  financeState.lastRoundAt = Date.now();
14621
- financeLog('[trader] başlatıldı (model: ' + (f.traderSel || 'genel aktif model') + ')');
14622
- finPush('trader', { state: 'running', round: mainAgent.round });
14623
- /* ANALİZ EKİBİ: seçili roller için ayrı sürekli ajanlar (koşmıyorsa) */
14766
+ financeLog('[trader] başlatıldı (JEV-ONLY — LLM kullanılmıyor, girdi yalnız TypeSafe)');
14767
+ finPush('trader', { state: 'running', round: mainAgent.round, mode: 'typesafe' });
14768
+ finTypeSafeKick(mainSid, mainAgent);
14769
+ /* ANALİZ EKİBİ: seçili roller için ayrı sürekli Jev ajanları (koşmıyorsa) */
14624
14770
  finTeamStart(f);
14625
14771
  return { ok: true, sid: mainSid };
14626
14772
  }
@@ -14643,20 +14789,10 @@ function finTeamStart(f) {
14643
14789
  const roleDef = finRoleDef(roleId);
14644
14790
  try {
14645
14791
  const created = finAgentCreate([], false, roleId);
14646
- try { engine.setSessionModel(created.s.id, f.traderSel || null); } catch {}
14647
- /* TYPESAFE-ONLY: bu rolün skill eşleştirmesinde typesafe-ai varsa LLM yok */
14648
- if (finTsAgentMode(created.agent)) {
14649
- financeLog('[ekip] ' + roleDef.label + ' başladı (TYPESAFE-ONLY — LLM kullanılmıyor)');
14650
- finTypeSafeKick(String(created.s.id), created.agent);
14651
- continue;
14652
- }
14653
- const ok = engine.send(created.s.id, finTraderBrief(created.agent), { userAction: true });
14654
- if (!ok) {
14655
- finAgentStop(String(created.s.id), 'oturum meşgul — ekip ajanı başlatılamadı');
14656
- financeLog('[ekip] ' + roleDef.label + ' başlatılamadı: oturum meşgul');
14657
- } else {
14658
- financeLog('[ekip] ' + roleDef.label + ' başladı — analiz turu koşuyor (İşlem AÇMAZ)');
14659
- }
14792
+ /* JEV-ONLY: ekibin HER rolü LLM'SİZ TypeSafe turuyla koşar (analiz
14793
+ üretir, işlem AÇMAZ) */
14794
+ financeLog('[ekip] ' + roleDef.label + ' başladı (JEV — LLM yok)');
14795
+ finTypeSafeKick(String(created.s.id), created.agent);
14660
14796
  } catch (e) {
14661
14797
  financeLog('[ekip] ' + roleDef.label + ' hatası: ' + String((e && e.message) || e));
14662
14798
  }
@@ -14697,7 +14833,9 @@ ipcMain.handle('finance:agent:spawn', async (_e, payload) => {
14697
14833
  const th = f.tradeHours || {};
14698
14834
  return { ok: false, error: `trade saatleri dışı (${th.start || '09:00'}-${th.end || '22:00'} yerel) — pencere açılınca ajanlar otomatik başlar` };
14699
14835
  }
14700
- if (!engine.publicState().hasModel && !f.traderSel) return { ok: false, error: 'model yok — Ayarlar → Provider' };
14836
+ /* JEV-ONLY: LLM modeli GEREKMEZ — anahtar kapısı TypeSafe'tir */
14837
+ const tsGate = typesafeMod.unavailable();
14838
+ if (tsGate) return { ok: false, error: tsGate };
14701
14839
  const symbol = String((payload && payload.symbol) || '').trim().toUpperCase();
14702
14840
  if (!symbol) return { ok: false, error: 'sembol gerekli' };
14703
14841
  for (const [, a] of financeState.agents) {
@@ -14706,13 +14844,9 @@ ipcMain.handle('finance:agent:spawn', async (_e, payload) => {
14706
14844
  }
14707
14845
  }
14708
14846
  const created = finAgentCreate([symbol], false);
14709
- try { engine.setSessionModel(created.s.id, f.traderSel || null); } catch {}
14710
- const ok = engine.send(created.s.id, finTraderBrief(created.agent), { userAction: true });
14711
- if (!ok) {
14712
- finAgentStop(String(created.s.id), 'oturum meşgul — ajan başlatılamadı');
14713
- return { ok: false, error: 'ajan oturumu meşgul — birkaç saniye sonra tekrar dene' };
14714
- }
14715
- financeLog('[ajan] ' + symbol + ' işçisi başlatıldı');
14847
+ /* JEV-ONLY: sembol işçisi LLM'SİZ TypeSafe turuyla otonom çalışır */
14848
+ finTypeSafeKick(String(created.s.id), created.agent);
14849
+ financeLog('[ajan] ' + symbol + ' işçisi başlatıldı (JEV — LLM yok)');
14716
14850
  return { ok: true, sid: created.s.id, title: created.s.bgTitle };
14717
14851
  });
14718
14852
 
@@ -755,7 +755,7 @@
755
755
  mail_need_to: 'Alıcı adresi gerekli',
756
756
  /* TypeSafe (System One / Jev) */
757
757
  ts_h2: 'TypeSafe (System One · Jev)',
758
- ts_sub: 'Tipli karar motoru: metin üretmeden olasılıklı yanıt (noul/choice/score). Anahtar girilince ajanlar typesafe_decision aracını kullanır; Beast Finance rol→skill eşleştirmesinde "typesafe-ai" seçilirse roller bu kararları kullanır.',
758
+ ts_sub: 'Tipli karar motoru: metin üretmeden olasılıklı yanıt (noul/choice/score). Beast Finance ajanları (Trader + analiz ekibi + sembol işçileri) JEV-ONLY çalışır — kararları YALNIZ buradan alır, LLM kullanılmaz; anahtar yoksa finans ajanları tur atmaz. Diğer ajanlar ve sohbet etkilenmez.',
759
759
  ts_key_label: 'TypeSafe API anahtarı (typesafe.ai)',
760
760
  ts_model_label: 'Model (varsayılan: jev-latest)',
761
761
  ts_enabled_label: 'TypeSafe açık (browser_agent/T3SFast + typesafe_decision kullanılabilir)',
@@ -772,7 +772,7 @@
772
772
  ts_saved_toast: 'TypeSafe anahtarı kaydedildi',
773
773
  ts_cleared_toast: 'TypeSafe anahtarı silindi',
774
774
  ts_fail_toast: 'TypeSafe kaydedilemedi',
775
- ts_hint: 'İpucu: Rol→Skill eşleştirmesinde "typesafe-ai" seçilen roller (ve ana trader playbook) kararlarını typesafe_decision ile alır; anahtar yoksa diğer ajanlar chat modeliyle devam eder.',
775
+ ts_hint: 'İpucu: Beast Finance ajanları JEV-ONLY koşar (LLM yok) — Ayarlar → TypeSafe anahtarı zorunludur. Finance SOHBET yardımcısı ve diğer ajanlar chat modelini kullanmaya devam eder.',
776
776
  },
777
777
  en: {
778
778
  newChat: '+ New Chat',
@@ -1512,7 +1512,7 @@
1512
1512
  store_login_note: 'Your Beast ID is anonymous; your real Beast Code is never shared.',
1513
1513
  /* TypeSafe (System One / Jev) */
1514
1514
  ts_h2: 'TypeSafe (System One · Jev)',
1515
- ts_sub: 'Typed decision engine: probabilistic answers without text generation (noul/choice/score). Once a key is set, agents can use the typesafe_decision tool; when "typesafe-ai" is picked in Beast Finance role→skill matching, those roles use it.',
1515
+ ts_sub: 'Typed decision engine: probabilistic answers without text generation (noul/choice/score). Beast Finance agents (Trader + analysis team + symbol workers) are JEV-ONLY — they take decisions solely from here, no LLM; without a key finance agents do not run. Other agents and the chat are unaffected.',
1516
1516
  ts_key_label: 'TypeSafe API key (typesafe.ai)',
1517
1517
  ts_model_label: 'Model (default: jev-latest)',
1518
1518
  ts_enabled_label: 'TypeSafe ON (enables browser_agent/T3SFast + typesafe_decision)',
@@ -1529,7 +1529,7 @@
1529
1529
  ts_saved_toast: 'TypeSafe key saved',
1530
1530
  ts_cleared_toast: 'TypeSafe key deleted',
1531
1531
  ts_fail_toast: 'Could not save TypeSafe key',
1532
- ts_hint: 'Tip: roles (and the main trader playbook) matched to "typesafe-ai" use typesafe_decision for their judgments; without a key other agents keep using the chat model.',
1532
+ ts_hint: 'Tip: Beast Finance agents run JEV-ONLY (no LLM) — a TypeSafe key in Settings is required. The finance chat copilot and other agents keep using the chat model.',
1533
1533
  },
1534
1534
  };
1535
1535
 
@@ -856,7 +856,7 @@
856
856
  </div>
857
857
  <div class="mini-body">
858
858
  <div id="finSkillsList" class="mini-list"></div>
859
- <div class="fin-sym-hint">Her rol için EN FAZLA 2 skill seçilir (ör. price-action + typesafe-ai). Seçili skill'i satırın sağ üstündeki çöp ikonuyla kaldırabilirsin; boş bırakırsan ajan skill'i göreve göre SKILLS kataloğundan kendi seçer. Seçim, koşan ajanlar dahil sonraki turdan itibaren geçerli olur.<br><b>typesafe-ai seçilirse:</b> o ajan LLM KULLANMAZ — tur verisi yalnız TypeSafe System One'a gider (tipli kararlar), cevaplar AJAN DM'de tüm ekibe görünür ve ajanlar birbirinin yanıtını görür; emirler YALNIZ market buy/sell olarak açılır (bekleyen emir yok). Ayarlar → TypeSafe'ten API anahtarı gerekir.</div>
859
+ <div class="fin-sym-hint"><b>BEAST FINANCE AJANLARI ARTIK HER ZAMAN JEV (TypeSafe System One) İLE ÇALIŞIR — LLM KULLANILMAZ.</b> Trader + analiz ekibi + sembol işçileri tur verisini koda toplar, kararı Jev'den (tipli olasılıklar) alır, emri kod uygular; cevaplar AJAN DM'de tüm ekibe görünür. Ayarlar → TypeSafe'ten API anahtarı zorunludur; anahtar yoksa ajanlar tur atmaz.<br>Buradaki skill seçimi (en fazla 2) yalnız finance SOHBET yardımcısının (LLM) playbook'u içindir; ajanların karar hattını değiştirmez. Seçili skill'i çöp ikonuyla kaldırabilirsin.</div>
860
860
  </div>
861
861
  </div>
862
862
  </div>
@@ -1683,8 +1683,8 @@ async function renderWebSearchPane() {
1683
1683
  }
1684
1684
 
1685
1685
  /* TypeSafe sekmesi (System One / Jev): API anahtarı + model + bağlantı testi.
1686
- Anahtar kayıtlıysa ajanlar typesafe_decision aracıyla tipli kararlar alır;
1687
- Beast Finance rol→skill eşleştirmesinde "typesafe-ai" seçilirse kullanılır. */
1686
+ Beast Finance ajanları JEV-ONLY çalışır (anahtar zorunlu); diğer ajanlar
1687
+ anahtar kayıtlıysa typesafe_decision aracıyla tipli kararlar alır. */
1688
1688
  async function renderTypesafePane() {
1689
1689
  const pane = $('#tab-typesafe');
1690
1690
  if (!pane) return;
@@ -7033,7 +7033,7 @@ async function renderCronModal(force) {
7033
7033
  row.innerHTML =
7034
7034
  `<span class="mr-dot"></span>` +
7035
7035
  `<div class="mr-main">` +
7036
- `<div class="mr-name">${escapeHtml(j.name || j.id)}</div>` +
7036
+ `<div class="mr-name">${escapeHtml(j.name || 'görev')} <span style="opacity:.55">#${escapeHtml(j.id)}</span></div>` +
7037
7037
  `<div class="mr-meta"><b>${escapeHtml(j.schedule)}</b> · ${escapeHtml(String(j.prompt || '').slice(0, 70))}${live}</div>` +
7038
7038
  `</div>`;
7039
7039
  const btns = document.createElement('div');
@@ -7407,7 +7407,8 @@ function renderCronList(jobs) {
7407
7407
  infoDiv.className = 'cj-info';
7408
7408
  const name = document.createElement('div');
7409
7409
  name.className = 'cj-name';
7410
- name.textContent = j.name;
7410
+ /* mesajlarda isim yerine JOB ID görünür — eşleştirme için listede de id */
7411
+ name.textContent = j.name + ' · #' + j.id;
7411
7412
  const meta = document.createElement('div');
7412
7413
  meta.className = 'cj-meta';
7413
7414
  const code = document.createElement('code');
@@ -7495,7 +7496,7 @@ async function renderAgendaPane() {
7495
7496
  if (!j.enabled) continue;
7496
7497
  const t = j.nextRunAt ? new Date(j.nextRunAt).getTime() : 0;
7497
7498
  if (!t) continue;
7498
- items.push({ type: isReminderLike(j) ? 'rem' : 'cron', name: j.name || j.id, at: t, meta: j.schedule, id: j.id });
7499
+ items.push({ type: isReminderLike(j) ? 'rem' : 'cron', name: (j.name || 'görev') + ' #' + j.id, at: t, meta: j.schedule, id: j.id });
7499
7500
  }
7500
7501
  for (const w of ws) {
7501
7502
  if (!w.enabled) continue;
@@ -11026,10 +11027,10 @@ function finSymPickerClose() {
11026
11027
  }
11027
11028
 
11028
11029
  /* ---------- ROL → SKILL eşleştirme modalı ----------
11029
- Roller sunucudan (snapshot.roles), skill listesi KURULU katalogdan gelir —
11030
- yeni skill eklendiğinde modalda otomatik görünür. Rol başına EN FAZLA 2
11031
- skill seçilir; seçim finance ayarına (roleSkills) yazılır; rol ajanı her
11032
- turda o skill'leri okumakla yükümlüdür (ör. price-action + typesafe-ai). */
11030
+ Roller sunucudan (snapshot.roles), skill listesi KURULU katalogdan gelir.
11031
+ Rol başına EN FAZLA 2 skill seçilir ve finance ayarına (roleSkills) yazılır.
11032
+ NOT: Finance AJANLARI artık JEV-ONLY (LLM yok) — bu seçim yalnız finance
11033
+ SOHBET yardımcısının (LLM) playbook'unu etkiler. */
11033
11034
  let finSkillNames = [];
11034
11035
 
11035
11036
  async function finSkillsOpen() {
@@ -11285,8 +11286,10 @@ function finLearnSymEl(row) {
11285
11286
  const noteCount = document.createElement('span');
11286
11287
  noteCount.className = 'fin-learn-sym-notes';
11287
11288
  noteCount.textContent = (Number(row.notes) || 0) + ' ders' + (row.hasSummary ? ' · özet' : '');
11288
- /* ÖZETLE (opencode tarzı compaction): eski dersler modele özetlettirilir */
11289
+ /* ÖZETLE: Beast Finance JEV-ONLY olduğu için LLM özetleme kapalı —
11290
+ düğme gizli (dersler tavan + TTL ile kendiliğinden sadeleşir) */
11289
11291
  const sum = document.createElement('button');
11292
+ sum.hidden = true;
11290
11293
  sum.type = 'button';
11291
11294
  sum.className = 'fin-learn-sum-btn';
11292
11295
  sum.title = 'Eski dersleri modele özetlet — hafıza sadeleşir (24+ ders birikince otomatik de çalışır)';