beast-agent 2.56.0 → 2.57.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/engine.js +65 -0
- package/src/agent/telegram.js +2 -0
- package/src/main.js +163 -14
- package/src/preload.js +1 -0
- package/src/renderer/index.html +11 -0
- package/src/renderer/renderer.js +89 -0
- package/src/renderer/style.css +20 -0
package/package.json
CHANGED
package/src/agent/engine.js
CHANGED
|
@@ -7109,6 +7109,11 @@ Engine.prototype._pushAgentDm = function (dm) {
|
|
|
7109
7109
|
this._agentDms = this._agentDms || [];
|
|
7110
7110
|
this._agentDms.push(dm);
|
|
7111
7111
|
if (this._agentDms.length > 600) this._agentDms.splice(0, this._agentDms.length - 600);
|
|
7112
|
+
/* DIŞ KÖPRÜ KANCASI (main.js: Telegram): panel kaydı düşen her DM tek
|
|
7113
|
+
noktadan dışarı bildirilir — köprü hangi mesajı göndereceğine kendi karar verir. */
|
|
7114
|
+
if (typeof this.onAgentDm === 'function') {
|
|
7115
|
+
try { this.onAgentDm(dm); } catch {}
|
|
7116
|
+
}
|
|
7112
7117
|
};
|
|
7113
7118
|
|
|
7114
7119
|
/* ---------- EKİP GRUBU: aynı görevde koşan paralel ajanlar otomatik
|
|
@@ -7214,6 +7219,66 @@ Engine.prototype._agentTeamPost = function (gid, fromSid, fromTitle, text) {
|
|
|
7214
7219
|
} catch {}
|
|
7215
7220
|
};
|
|
7216
7221
|
|
|
7222
|
+
/* Grubu hazırla (yoksa kur): Telegram köprüsü ve finans alarmları grubu önceden
|
|
7223
|
+
hiç kurulmamış olsa da panele düşebilsin. */
|
|
7224
|
+
Engine.prototype._agentGroupEnsure = function (gid, title, opts) {
|
|
7225
|
+
gid = String(gid || '');
|
|
7226
|
+
if (!gid) return null;
|
|
7227
|
+
let g = this._agentGroups.get(gid);
|
|
7228
|
+
if (!g) {
|
|
7229
|
+
g = {
|
|
7230
|
+
id: gid,
|
|
7231
|
+
title: String(title || gid),
|
|
7232
|
+
members: [],
|
|
7233
|
+
titles: {},
|
|
7234
|
+
createdAt: nowIso(),
|
|
7235
|
+
closed: false,
|
|
7236
|
+
team: !(opts && opts.system),
|
|
7237
|
+
};
|
|
7238
|
+
this._agentGroups.set(gid, g);
|
|
7239
|
+
}
|
|
7240
|
+
if (title && !g.title) g.title = String(title);
|
|
7241
|
+
g.closed = false;
|
|
7242
|
+
delete g.closedAt;
|
|
7243
|
+
return g;
|
|
7244
|
+
};
|
|
7245
|
+
|
|
7246
|
+
/* DIŞ KAYNAKLI (kullanıcı/Telegram) GRUP POSTU: panelde gerçek mesaj olarak
|
|
7247
|
+
görünür + istenirse koşan üyelere DM gibi teslim edilir. Sistem postlarından
|
|
7248
|
+
farkı: model tarafına da düşebilir (wake kararı çağıranın). */
|
|
7249
|
+
Engine.prototype.agentDmGroupPost = function (input) {
|
|
7250
|
+
try {
|
|
7251
|
+
const i = input || {};
|
|
7252
|
+
const gid = String(i.gid || '');
|
|
7253
|
+
const g = this._agentGroupEnsure(gid, i.title || '', { system: !!i.system });
|
|
7254
|
+
if (!g) return { ok: false, error: 'gid gerekli' };
|
|
7255
|
+
const dm = {
|
|
7256
|
+
at: nowIso(),
|
|
7257
|
+
from: String(i.fromSid || 'user'),
|
|
7258
|
+
fromTitle: String(i.fromTitle || 'Kullanıcı'),
|
|
7259
|
+
to: '',
|
|
7260
|
+
toTitle: 'ekip',
|
|
7261
|
+
group: gid,
|
|
7262
|
+
groupTitle: g.title,
|
|
7263
|
+
topic: String(i.topic || 'grup').slice(0, 60),
|
|
7264
|
+
text: String(i.text || '').slice(0, 4000),
|
|
7265
|
+
...(i.system ? { system: true } : {}),
|
|
7266
|
+
...(i.viaTelegram ? { viaTelegram: true } : {}),
|
|
7267
|
+
};
|
|
7268
|
+
this._pushAgentDm(dm);
|
|
7269
|
+
/* canlı event TEK SEFER: ilk koşan üye (yoksa gönderen) — panelde çoğalmaz */
|
|
7270
|
+
const firstRunning = (g.members || []).find((m) => {
|
|
7271
|
+
const j = this._bgJobs && this._bgJobs.get(m);
|
|
7272
|
+
return j && j.status === 'running';
|
|
7273
|
+
});
|
|
7274
|
+
emitSafe(this, firstRunning || String(i.fromSid || ''), { type: 'agent-dm', ...dm });
|
|
7275
|
+
this._persistAgentDms();
|
|
7276
|
+
return { ok: true, group: g.title };
|
|
7277
|
+
} catch (e) {
|
|
7278
|
+
return { ok: false, error: String((e && e.message) || e) };
|
|
7279
|
+
}
|
|
7280
|
+
};
|
|
7281
|
+
|
|
7217
7282
|
/* Sistem promptuna ekip zorunluluğu */
|
|
7218
7283
|
Engine.prototype._agentTeamPromptLine = function (gid) {
|
|
7219
7284
|
const g = this._agentGroups && this._agentGroups.get(String(gid));
|
package/src/agent/telegram.js
CHANGED
|
@@ -106,6 +106,8 @@ class TelegramBridge {
|
|
|
106
106
|
username: String(msg.from.username || ''),
|
|
107
107
|
senderName: String(msg.from.first_name || msg.from.username || ''),
|
|
108
108
|
isGroup: !!(msg.chat && (msg.chat.type === 'group' || msg.chat.type === 'supergroup')),
|
|
109
|
+
chatTitle: String((msg.chat && (msg.chat.title || msg.chat.username)) || ''),
|
|
110
|
+
chatType: String((msg.chat && msg.chat.type) || 'private'),
|
|
109
111
|
};
|
|
110
112
|
try {
|
|
111
113
|
if (this.onIncoming) this.onIncoming(String(chatId), payload);
|
package/src/main.js
CHANGED
|
@@ -332,6 +332,18 @@ let tgCronSid = null; // Telegram CRON TABAN OTURUMU: otomatik işler; hiçbir k
|
|
|
332
332
|
let tgHistory = new Map(); // chatId -> [sid,...]
|
|
333
333
|
const TG_HISTORY_CAP = 20;
|
|
334
334
|
let tgLastActiveChatId = ''; // en son mesaj gelen TG sohbeti — cron yansıtma hedefi
|
|
335
|
+
/* Botun gördüğü Telegram GRUPLARI: chatId -> {title, at}. Ajan DM ↔ Telegram
|
|
336
|
+
köprüsü kurulumunda grup seçimi bu listeden yapılır (BotFather'da gizlilik
|
|
337
|
+
kapatılmalı ya da bot gruba admin olmalı ki mesajlar düşsün). */
|
|
338
|
+
let tgGroups = {};
|
|
339
|
+
try {
|
|
340
|
+
const raw = settings.tgGroups;
|
|
341
|
+
if (raw && typeof raw === 'object') {
|
|
342
|
+
for (const [id, v] of Object.entries(raw)) {
|
|
343
|
+
if (v && typeof v === 'object') tgGroups[String(id)] = { title: String(v.title || ''), at: Number(v.at) || 0 };
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
} catch {}
|
|
335
347
|
let dc = null;
|
|
336
348
|
let dcChats = new Map(); // discord channelId -> KENDİ oturumu: her kanal AYRI (gizlilik)
|
|
337
349
|
let dcCronSid = null; // Discord CRON TABAN OTURUMU: otomatik işler; hiçbir kişiye bağlı DEĞİL
|
|
@@ -672,6 +684,29 @@ function tgLog(line) {
|
|
|
672
684
|
try { log.info('telegram', line); } catch {}
|
|
673
685
|
}
|
|
674
686
|
|
|
687
|
+
/* Gelen grup mesajından grubu hatırla — ajan DM köprüsü grup seçicisi bu
|
|
688
|
+
listeden beslenir. Başlık değişmedikçe diske yazılmaz (yalnız tazeleme). */
|
|
689
|
+
function tgRememberGroup(chatId, title) {
|
|
690
|
+
const id = String(chatId || '');
|
|
691
|
+
if (!id) return;
|
|
692
|
+
const cur = tgGroups[id];
|
|
693
|
+
const t = String(title || '');
|
|
694
|
+
const at = Date.now();
|
|
695
|
+
if (cur && (cur.title === t || !t)) {
|
|
696
|
+
cur.at = at;
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
tgGroups[id] = { title: t || (cur && cur.title) || id, at };
|
|
700
|
+
settings.tgGroups = tgGroups;
|
|
701
|
+
try { saveSettings(); } catch {}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
function tgGroupsList() {
|
|
705
|
+
return Object.entries(tgGroups)
|
|
706
|
+
.map(([id, v]) => ({ id, title: String((v && v.title) || id), at: Number((v && v.at) || 0) }))
|
|
707
|
+
.sort((a, b) => b.at - a.at);
|
|
708
|
+
}
|
|
709
|
+
|
|
675
710
|
function tgFind(senderId, username) {
|
|
676
711
|
const list = settings.tgAllow || [];
|
|
677
712
|
if (!list.length) return null; // boş liste = kimseye cevap yok
|
|
@@ -2895,8 +2930,20 @@ async function tgFlush(chatId) {
|
|
|
2895
2930
|
async function handleTgIncoming(chatId, payload) {
|
|
2896
2931
|
try {
|
|
2897
2932
|
if (!engine) return;
|
|
2898
|
-
/*
|
|
2933
|
+
/* GRUP: normal grup desteği kapalı; ancak AJAN DM ↔ TELEGRAM köprüsünde
|
|
2934
|
+
seçili grupsa mesaj AJAN DM grubuna düşer ve finance ajanları uyanır. */
|
|
2899
2935
|
if (payload.isGroup) {
|
|
2936
|
+
tgRememberGroup(chatId, payload.chatTitle);
|
|
2937
|
+
const dmTg = finDmTgCfg();
|
|
2938
|
+
if (dmTg.on && String(dmTg.chat) === String(chatId)) {
|
|
2939
|
+
const allowed = tgFind(payload.senderId, payload.username);
|
|
2940
|
+
tgLog(
|
|
2941
|
+
`grup(ajan dm) chat=${chatId} sender=${payload.senderId || '?'} user=${payload.username || '-'} allowed=${!!allowed}`
|
|
2942
|
+
);
|
|
2943
|
+
if (!allowed) return; /* izin listesi dışı yoksay */
|
|
2944
|
+
finTelegramToAgentDm(payload);
|
|
2945
|
+
return;
|
|
2946
|
+
}
|
|
2900
2947
|
tgLog(`skip: grup mesajı chat=${chatId} (grup desteği kapalı)`);
|
|
2901
2948
|
return;
|
|
2902
2949
|
}
|
|
@@ -3566,6 +3613,10 @@ function reloadBackend() {
|
|
|
3566
3613
|
düşünce sıradaki planlı turu BEKLEMEZ — ajan boştaysa tur hemen başlar
|
|
3567
3614
|
(ajan-ajan DM'lerinde engine kancayı çağırmaz; ping-pong korunur). */
|
|
3568
3615
|
engine.onDmQueued = (job) => { try { finWakeAgent(job && job.id); } catch {} };
|
|
3616
|
+
/* AJAN DM → TELEGRAM: AJAN DM grubuna düşen her kayıt (alarm/sistem postu
|
|
3617
|
+
dahil) tek kancadan geçer; köprü ayarı açıksa seçili Telegram grubuna
|
|
3618
|
+
yansıtılır (Telegram'dan gelen mesajlar viaTelegram ile geri gönderilmez). */
|
|
3619
|
+
engine.onAgentDm = (dm) => { try { finAgentDmToTelegram(dm); } catch {} };
|
|
3569
3620
|
/* PANEL RUN köprüsü: ajanın panel_run aracı → ÇALIŞTIR panelindeki yönetilen
|
|
3570
3621
|
süreç koşucusu (sandbox:run IPC ile aynı makine). */
|
|
3571
3622
|
engine.sbRunHook = sbRunStartManaged;
|
|
@@ -7683,14 +7734,15 @@ function watcherFire(w, value) {
|
|
|
7683
7734
|
? 'izlenen değer değişti'
|
|
7684
7735
|
: `kural sağlandı (son değer ${value}, koşul ${w.op} ${w.value ?? ''})`;
|
|
7685
7736
|
toastNotify(`İzleyici: ${w.name}`, target, 'watchers');
|
|
7686
|
-
/* FINANCE AJANI: izleyici alarmı AJAN DM
|
|
7687
|
-
tur beklemeden uyandırır (
|
|
7688
|
-
eski davranış: mesaj doğrudan
|
|
7689
|
-
|
|
7690
|
-
|
|
7691
|
-
|
|
7737
|
+
/* FINANCE AJANI: izleyici alarmı AJAN DM GRUBUNA bildirim olarak düşer ve
|
|
7738
|
+
koşan TÜM finance ajanlarını tur beklemeden uyandırır (finWakeAgents:
|
|
7739
|
+
grup postu + dm+wake). Diğer oturumlarda eski davranış: mesaj doğrudan
|
|
7740
|
+
sohbete iner. */
|
|
7741
|
+
if (financeState.agents.has(String(sid)) || (financeState.mode && financeState.agents.size)) {
|
|
7742
|
+
finWakeAgents(
|
|
7692
7743
|
`[FİNANS OLAYI — İZLEYİCİ ALARMI: ${w.name}]\n- ${target}\n` +
|
|
7693
|
-
`Şimdi yap: izleyiciyi kurma nedenini hatırla; durumu değerlendir, gerekiyorsa işlem/uyarı üret. Kısa rapor ver
|
|
7744
|
+
`Şimdi yap: izleyiciyi kurma nedenini hatırla; durumu değerlendir, gerekiyorsa işlem/uyarı üret. Kısa rapor ver.`,
|
|
7745
|
+
{ kind: 'watcher', watcher: w.id }
|
|
7694
7746
|
);
|
|
7695
7747
|
return;
|
|
7696
7748
|
}
|
|
@@ -9349,6 +9401,12 @@ function finCfg() {
|
|
|
9349
9401
|
iptal) düşer; fiyat alarmı, koruma (BE/trailing/kısmi TP), günlük limit ve
|
|
9350
9402
|
rapor bildirimleri panelde kalır. false = tüm olaylar kanallara gider. */
|
|
9351
9403
|
if (typeof f.notifyTradeOnly !== 'boolean') f.notifyTradeOnly = true;
|
|
9404
|
+
/* AJAN DM ↔ TELEGRAM KÖPRÜSÜ: açıkken `team:finance` AJAN DM grubundaki
|
|
9405
|
+
mesajlar seçilen Telegram grubuna düşer; o gruba yazılan mesaj AJAN DM
|
|
9406
|
+
grubunda görünür ve koşan finance ajanları tur beklemeden uyanır. */
|
|
9407
|
+
if (typeof f.dmTelegram !== 'boolean') f.dmTelegram = false;
|
|
9408
|
+
if (typeof f.dmTelegramChat !== 'string') f.dmTelegramChat = '';
|
|
9409
|
+
if (typeof f.dmTelegramTitle !== 'string') f.dmTelegramTitle = '';
|
|
9352
9410
|
if (!Number.isFinite(Number(f.maxDailyLossPct))) f.maxDailyLossPct = 3;
|
|
9353
9411
|
/* GÜNLÜK LİMİT AKSİYONU: warn = yalnız uyarı; stop = tüm finance ajanlarını
|
|
9354
9412
|
durdur; flatten = durdur + tüm pozisyonları kapat */
|
|
@@ -10001,6 +10059,76 @@ async function finStatsRefresh(force) {
|
|
|
10001
10059
|
}
|
|
10002
10060
|
}
|
|
10003
10061
|
|
|
10062
|
+
/* ---- AJAN DM ↔ TELEGRAM KÖPRÜSÜ ----
|
|
10063
|
+
Beast Finance görünüm ayarlarından açılır: `team:finance` AJAN DM grubundaki
|
|
10064
|
+
her mesaj (alarm/sistem postları dahil) seçilen Telegram grubuna yansır;
|
|
10065
|
+
o gruba yazılan mesaj AJAN DM grubunda görünür ve koşan finance ajanları
|
|
10066
|
+
tur beklemeden uyandırılır. Ayarlar: finCfg().dmTelegram / dmTelegramChat. */
|
|
10067
|
+
const FIN_TEAM_GID = 'team:finance';
|
|
10068
|
+
const FIN_TEAM_TITLE = 'Beast Finance EKİP';
|
|
10069
|
+
|
|
10070
|
+
/* Köprü ayarı (tek nokta): açık + grup seçili mi? */
|
|
10071
|
+
function finDmTgCfg() {
|
|
10072
|
+
let f = {};
|
|
10073
|
+
try { f = finCfg(); } catch {}
|
|
10074
|
+
return {
|
|
10075
|
+
on: !!(f && f.dmTelegram && f.dmTelegramChat),
|
|
10076
|
+
chat: String((f && f.dmTelegramChat) || ''),
|
|
10077
|
+
title: String((f && f.dmTelegramTitle) || ''),
|
|
10078
|
+
};
|
|
10079
|
+
}
|
|
10080
|
+
|
|
10081
|
+
/* Giden: AJAN DM grubu → Telegram (Telegram'dan gelenler geri gönderilmez). */
|
|
10082
|
+
function finAgentDmToTelegram(dm) {
|
|
10083
|
+
try {
|
|
10084
|
+
if (!dm || dm.viaTelegram) return;
|
|
10085
|
+
if (String(dm.group || '') !== FIN_TEAM_GID) return;
|
|
10086
|
+
const c = finDmTgCfg();
|
|
10087
|
+
if (!c.on || !tg || !tg.connected) return;
|
|
10088
|
+
const who = String(dm.fromTitle || (dm.system ? 'SİSTEM' : 'Ajan'));
|
|
10089
|
+
const body =
|
|
10090
|
+
`👥 *${String(dm.groupTitle || FIN_TEAM_TITLE)}* · ${who}\n` +
|
|
10091
|
+
String(dm.text || '').slice(0, 3800);
|
|
10092
|
+
Promise.resolve(tg.send(c.chat, body)).catch((e) =>
|
|
10093
|
+
tgLog('ajan dm → telegram hata: ' + String((e && e.message) || e))
|
|
10094
|
+
);
|
|
10095
|
+
} catch {}
|
|
10096
|
+
}
|
|
10097
|
+
|
|
10098
|
+
/* Gelen: Telegram grubu → AJAN DM grubu (+ tüm koşan finance ajanlarını uyandır). */
|
|
10099
|
+
function finTelegramToAgentDm(payload) {
|
|
10100
|
+
try {
|
|
10101
|
+
const body = String((payload && payload.text) || '').trim();
|
|
10102
|
+
if (!body || !engine) return { ok: false };
|
|
10103
|
+
const who = String((payload && (payload.senderName || payload.username)) || 'Telegram');
|
|
10104
|
+
const label = `Sahip · Telegram (${who})`;
|
|
10105
|
+
try {
|
|
10106
|
+
if (typeof engine.agentDmGroupPost === 'function') {
|
|
10107
|
+
engine.agentDmGroupPost({
|
|
10108
|
+
gid: FIN_TEAM_GID,
|
|
10109
|
+
title: FIN_TEAM_TITLE,
|
|
10110
|
+
fromSid: 'tg:' + String((payload && payload.senderId) || ''),
|
|
10111
|
+
fromTitle: label,
|
|
10112
|
+
topic: 'telegram',
|
|
10113
|
+
text: body,
|
|
10114
|
+
viaTelegram: true,
|
|
10115
|
+
});
|
|
10116
|
+
}
|
|
10117
|
+
} catch {}
|
|
10118
|
+
const wake =
|
|
10119
|
+
`[AJAN DM — TELEGRAM GRUBU · ${label}]\n${body}\n` +
|
|
10120
|
+
'Şimdi yap: sahibin Telegram grubundan gelen bu mesajı değerlendir; gerekiyorsa ekipçe aksiyon al. Kısa rapor ver.';
|
|
10121
|
+
let sent = 0;
|
|
10122
|
+
for (const [sid] of financeState.agents) {
|
|
10123
|
+
if (finWakeAgentDm(sid, wake)) sent += 1;
|
|
10124
|
+
}
|
|
10125
|
+
financeLog(`[telegram] ajan dm grubuna mesaj düştü (${sent} ajan uyandı)`);
|
|
10126
|
+
return { ok: true, sent };
|
|
10127
|
+
} catch {
|
|
10128
|
+
return { ok: false };
|
|
10129
|
+
}
|
|
10130
|
+
}
|
|
10131
|
+
|
|
10004
10132
|
/* ---- FİNANS OLAY → AJAN DM UYANDIRMA ----
|
|
10005
10133
|
Stop/TP/bekleyen emir aktivasyonu/fiyat alarmı gibi olaylar koşan finance
|
|
10006
10134
|
ajanlarına AJAN DM'i olarak düşer ve BOŞTAKİ ajanı TUR SANİYESİNİ
|
|
@@ -10031,20 +10159,32 @@ function finWakeAgentDm(sid, text) {
|
|
|
10031
10159
|
}
|
|
10032
10160
|
}
|
|
10033
10161
|
|
|
10034
|
-
/* Tüm koşan finance ajanlarını olayla uyandır. Dönüş: uyandırılan ajan sayısı.
|
|
10162
|
+
/* Tüm koşan finance ajanlarını olayla uyandır. Dönüş: uyandırılan ajan sayısı.
|
|
10163
|
+
Olay HER durumda ekip DM grubuna sistem postu olarak düşer (koşan ajan yoksa
|
|
10164
|
+
bile panelde görünür — grup yoksa kurulur). */
|
|
10035
10165
|
function finWakeAgents(text, meta) {
|
|
10036
10166
|
const body = String(text || '').trim();
|
|
10037
10167
|
if (!body || !engine) return 0;
|
|
10038
|
-
if (!financeState.agents.size) {
|
|
10039
|
-
financeLog('[olay] koşan finance ajanı yok — uyarı yalnız günlük/bildirimde' + (meta && meta.kind ? ' (' + meta.kind + ')' : ''));
|
|
10040
|
-
return 0;
|
|
10041
|
-
}
|
|
10042
10168
|
/* Panel görünürlüğü: olay ekip DM grubuna sistem postu olarak düşer */
|
|
10043
10169
|
try {
|
|
10044
|
-
if (typeof engine.
|
|
10170
|
+
if (typeof engine.agentDmGroupPost === 'function') {
|
|
10171
|
+
engine.agentDmGroupPost({
|
|
10172
|
+
gid: FIN_TEAM_GID,
|
|
10173
|
+
title: FIN_TEAM_TITLE,
|
|
10174
|
+
fromSid: 'finance',
|
|
10175
|
+
fromTitle: 'Beast Finance',
|
|
10176
|
+
topic: 'ortak görev',
|
|
10177
|
+
text: body,
|
|
10178
|
+
system: true,
|
|
10179
|
+
});
|
|
10180
|
+
} else if (typeof engine._agentTeamPost === 'function') {
|
|
10045
10181
|
engine._agentTeamPost('team:finance', 'finance', 'Beast Finance', body);
|
|
10046
10182
|
}
|
|
10047
10183
|
} catch {}
|
|
10184
|
+
if (!financeState.agents.size) {
|
|
10185
|
+
financeLog('[olay] koşan finance ajanı yok — uyarı yalnız günlük/bildirimde' + (meta && meta.kind ? ' (' + meta.kind + ')' : ''));
|
|
10186
|
+
return 0;
|
|
10187
|
+
}
|
|
10048
10188
|
let sent = 0;
|
|
10049
10189
|
for (const [sid] of financeState.agents) {
|
|
10050
10190
|
if (finWakeAgentDm(sid, body)) sent += 1;
|
|
@@ -11473,6 +11613,13 @@ ipcMain.handle('finance:settings', async (_e, patch) => {
|
|
|
11473
11613
|
if (p.notifyTrades !== undefined) f.notifyTrades = !!p.notifyTrades;
|
|
11474
11614
|
if (p.notifyWatchdog !== undefined) f.notifyWatchdog = !!p.notifyWatchdog;
|
|
11475
11615
|
if (p.notifyTradeOnly !== undefined) f.notifyTradeOnly = !!p.notifyTradeOnly;
|
|
11616
|
+
/* AJAN DM ↔ TELEGRAM köprüsü ayarları */
|
|
11617
|
+
if (p.dmTelegram !== undefined) f.dmTelegram = !!p.dmTelegram;
|
|
11618
|
+
if (p.dmTelegramChat !== undefined) {
|
|
11619
|
+
f.dmTelegramChat = String(p.dmTelegramChat || '').trim().slice(0, 64);
|
|
11620
|
+
if (!f.dmTelegramChat) f.dmTelegram = false;
|
|
11621
|
+
}
|
|
11622
|
+
if (p.dmTelegramTitle !== undefined) f.dmTelegramTitle = String(p.dmTelegramTitle || '').trim().slice(0, 80);
|
|
11476
11623
|
if (p.maxDailyLossPct !== undefined) f.maxDailyLossPct = Math.max(0, Math.min(50, Number(p.maxDailyLossPct) || 0));
|
|
11477
11624
|
if (p.dailyLossAction !== undefined) {
|
|
11478
11625
|
const v = String(p.dailyLossAction || 'warn').toLowerCase();
|
|
@@ -13877,6 +14024,8 @@ ipcMain.handle('tg:allow:set', (_e, list) => {
|
|
|
13877
14024
|
saveSettings();
|
|
13878
14025
|
return settings.tgAllow;
|
|
13879
14026
|
});
|
|
14027
|
+
/* Botun gördüğü gruplar (AJAN DM ↔ TELEGRAM grup seçicisi) */
|
|
14028
|
+
ipcMain.handle('tg:groups:list', () => tgGroupsList());
|
|
13880
14029
|
ipcMain.handle('tg:sessions', () => [...tgChats.values()]);
|
|
13881
14030
|
|
|
13882
14031
|
/* Sohbet geçmişi etiketi (Telegram): "Telegram <ad|chatId>" */
|
package/src/preload.js
CHANGED
|
@@ -221,6 +221,7 @@ contextBridge.exposeInMainWorld('beast', {
|
|
|
221
221
|
tgStop: () => ipcRenderer.invoke('tg:stop'),
|
|
222
222
|
tgGetAllow: () => ipcRenderer.invoke('tg:allow:get'),
|
|
223
223
|
tgSetAllow: (list) => ipcRenderer.invoke('tg:allow:set', list),
|
|
224
|
+
tgGroupsList: () => ipcRenderer.invoke('tg:groups:list'),
|
|
224
225
|
tgListSessions: () => ipcRenderer.invoke('tg:sessions'),
|
|
225
226
|
onTgEvent: (cb) => ipcRenderer.on('tg:event', (_e, ev) => cb(ev)),
|
|
226
227
|
dcGetStatus: () => ipcRenderer.invoke('dc:status:get'),
|
package/src/renderer/index.html
CHANGED
|
@@ -891,6 +891,17 @@
|
|
|
891
891
|
<span class="fsr-main"><b>AKIŞ</b><i>Ajan ve MT5 olay günlüğü</i></span>
|
|
892
892
|
</label>
|
|
893
893
|
<div class="fin-set-note">RİSK OTOMASYONU gizliyken koruma döngüsü (watchdog) kapatılır; tekrar gösterdiğinde ilgili kutucuktan açabilirsin.</div>
|
|
894
|
+
<div class="fin-set-sep"></div>
|
|
895
|
+
<label class="fin-set-row" title="Açıkken Beast Finance AJAN DM grubundaki mesajlar (alarm/sistem postları dahil) seçtiğin Telegram grubuna düşer; o gruba yazdığın mesaj AJAN DM grubunda görünür ve koşan finance ajanları tur beklemeden uyanır.">
|
|
896
|
+
<input id="finDmTgOn" type="checkbox" />
|
|
897
|
+
<span class="fsr-main"><b>AJAN DM ↔ TELEGRAM</b><i>Ajan DM grubu Telegram'da canlı — iki yönlü köprü</i></span>
|
|
898
|
+
</label>
|
|
899
|
+
<div id="finDmTgWrap" class="fin-set-sub" hidden>
|
|
900
|
+
<span class="fin-set-lbl">TELEGRAM GRUBU</span>
|
|
901
|
+
<select id="finDmTgChat" title="Botu eklediğin Telegram grubunu seç — liste, bottan mesaj alınan grupları gösterir"></select>
|
|
902
|
+
<button id="finDmTgRefresh" class="fin-set-btn" title="Grup listesini yenile — bottan mesaj alan gruplar listelenir">⟳ Listeyi yenile</button>
|
|
903
|
+
<div id="finDmTgHint" class="fin-set-note" style="margin:2px 0 0"></div>
|
|
904
|
+
</div>
|
|
894
905
|
</div>
|
|
895
906
|
</div>
|
|
896
907
|
</div>
|
package/src/renderer/renderer.js
CHANGED
|
@@ -203,6 +203,11 @@ const els = {
|
|
|
203
203
|
finShowNotify: $('#finShowNotify'),
|
|
204
204
|
finShowPerf: $('#finShowPerf'),
|
|
205
205
|
finShowFlow: $('#finShowFlow'),
|
|
206
|
+
finDmTgOn: $('#finDmTgOn'),
|
|
207
|
+
finDmTgWrap: $('#finDmTgWrap'),
|
|
208
|
+
finDmTgChat: $('#finDmTgChat'),
|
|
209
|
+
finDmTgRefresh: $('#finDmTgRefresh'),
|
|
210
|
+
finDmTgHint: $('#finDmTgHint'),
|
|
206
211
|
finRiskCard: $('#finRiskCard'),
|
|
207
212
|
finNotifyCard: $('#finNotifyCard'),
|
|
208
213
|
finPerfCard: $('#finPerfCard'),
|
|
@@ -10119,6 +10124,11 @@ async function finSnapshot() {
|
|
|
10119
10124
|
if (!finView.risk && r.cfg && r.cfg.watchdog !== false) finSaveCfg({ watchdog: false });
|
|
10120
10125
|
finRenderStats(r.stats, r.equity, r.account && r.account.currency ? r.account.currency : '');
|
|
10121
10126
|
finRenderAlerts(r.alerts);
|
|
10127
|
+
/* görünüm ayarları açıkken AJAN DM ↔ TELEGRAM seçimi cfg ile senkron kalsın
|
|
10128
|
+
(kullanıcı dropdown'dayken DOM'a dokunulmaz) */
|
|
10129
|
+
if (els.finSettingsOverlay && !els.finSettingsOverlay.hidden && document.activeElement !== els.finDmTgChat) {
|
|
10130
|
+
finDmTgPaint();
|
|
10131
|
+
}
|
|
10122
10132
|
}
|
|
10123
10133
|
|
|
10124
10134
|
function finLogLine(line) {
|
|
@@ -10280,8 +10290,63 @@ function finViewApply() {
|
|
|
10280
10290
|
if (!finView.risk) finSaveCfg({ watchdog: false });
|
|
10281
10291
|
}
|
|
10282
10292
|
|
|
10293
|
+
/* ---------- AJAN DM ↔ TELEGRAM (görünüm ayarları) ----------
|
|
10294
|
+
Ayarlar settings.finance'ta: dmTelegram + dmTelegramChat/Title. Grup listesi
|
|
10295
|
+
bottan mesaj alan gruplardan gelir (kanal: tg:groups:list). */
|
|
10296
|
+
let finDmTgGroups = [];
|
|
10297
|
+
|
|
10298
|
+
function finDmTgPaint() {
|
|
10299
|
+
if (!els.finDmTgOn) return;
|
|
10300
|
+
const cfg = finCfgCache || {};
|
|
10301
|
+
const on = cfg.dmTelegram === true;
|
|
10302
|
+
els.finDmTgOn.checked = on;
|
|
10303
|
+
const row = els.finDmTgOn.closest('.fin-set-row');
|
|
10304
|
+
if (row) row.classList.toggle('on', on);
|
|
10305
|
+
if (els.finDmTgWrap) els.finDmTgWrap.hidden = !on;
|
|
10306
|
+
if (els.finDmTgChat) {
|
|
10307
|
+
const cur = String(cfg.dmTelegramChat || '');
|
|
10308
|
+
const sel = els.finDmTgChat;
|
|
10309
|
+
sel.textContent = '';
|
|
10310
|
+
const opt0 = document.createElement('option');
|
|
10311
|
+
opt0.value = '';
|
|
10312
|
+
opt0.textContent = finDmTgGroups.length ? '— Grup seç —' : '— Görünen grup yok —';
|
|
10313
|
+
sel.appendChild(opt0);
|
|
10314
|
+
let has = false;
|
|
10315
|
+
for (const g of finDmTgGroups) {
|
|
10316
|
+
const o = document.createElement('option');
|
|
10317
|
+
o.value = String(g.id);
|
|
10318
|
+
o.textContent = String(g.title || g.id) + ' (' + g.id + ')';
|
|
10319
|
+
if (String(g.id) === cur) { o.selected = true; has = true; }
|
|
10320
|
+
sel.appendChild(o);
|
|
10321
|
+
}
|
|
10322
|
+
/* listelenmemiş kayıtlı grup kaybolmasın — mevcut seçim korunur */
|
|
10323
|
+
if (cur && !has) {
|
|
10324
|
+
const o = document.createElement('option');
|
|
10325
|
+
o.value = cur;
|
|
10326
|
+
o.textContent = String(cfg.dmTelegramTitle || cur) + ' (' + cur + ')';
|
|
10327
|
+
o.selected = true;
|
|
10328
|
+
sel.appendChild(o);
|
|
10329
|
+
}
|
|
10330
|
+
}
|
|
10331
|
+
if (els.finDmTgHint) {
|
|
10332
|
+
els.finDmTgHint.textContent = finDmTgGroups.length
|
|
10333
|
+
? 'Seçili gruptaki mesajlar AJAN DM grubunda görünür; AJAN DM mesajları da bu gruba düşer.'
|
|
10334
|
+
: 'Botu bir Telegram grubuna ekle, gruba bir mesaj yaz ve "Listeyi yenile"ye bas (BotFather → /setprivacy → Disable ya da bot gruba admin olmalı).';
|
|
10335
|
+
}
|
|
10336
|
+
}
|
|
10337
|
+
|
|
10338
|
+
async function finDmTgRefresh() {
|
|
10339
|
+
try {
|
|
10340
|
+
const list = await beast.tgGroupsList();
|
|
10341
|
+
finDmTgGroups = Array.isArray(list) ? list : [];
|
|
10342
|
+
} catch { finDmTgGroups = []; }
|
|
10343
|
+
finDmTgPaint();
|
|
10344
|
+
}
|
|
10345
|
+
|
|
10283
10346
|
function finSettingsOpen() {
|
|
10284
10347
|
if (els.finSettingsOverlay) els.finSettingsOverlay.hidden = false;
|
|
10348
|
+
finDmTgPaint();
|
|
10349
|
+
finDmTgRefresh();
|
|
10285
10350
|
}
|
|
10286
10351
|
function finSettingsCloseModal() {
|
|
10287
10352
|
if (els.finSettingsOverlay) els.finSettingsOverlay.hidden = true;
|
|
@@ -10315,6 +10380,30 @@ if (els.finShowRisk) els.finShowRisk.addEventListener('change', () => finViewTog
|
|
|
10315
10380
|
if (els.finShowNotify) els.finShowNotify.addEventListener('change', () => finViewToggle('notify', els.finShowNotify.checked));
|
|
10316
10381
|
if (els.finShowPerf) els.finShowPerf.addEventListener('change', () => finViewToggle('perf', els.finShowPerf.checked));
|
|
10317
10382
|
if (els.finShowFlow) els.finShowFlow.addEventListener('change', () => finViewToggle('flow', els.finShowFlow.checked));
|
|
10383
|
+
/* AJAN DM ↔ TELEGRAM köprüsü kontrolleri */
|
|
10384
|
+
if (els.finDmTgOn) {
|
|
10385
|
+
els.finDmTgOn.addEventListener('change', () => {
|
|
10386
|
+
const on = els.finDmTgOn.checked;
|
|
10387
|
+
if (finCfgCache) finCfgCache.dmTelegram = on;
|
|
10388
|
+
finSaveCfg({ dmTelegram: on });
|
|
10389
|
+
finDmTgPaint();
|
|
10390
|
+
toast(on ? 'AJAN DM ↔ Telegram köprüsü açıldı' : 'AJAN DM ↔ Telegram köprüsü kapatıldı');
|
|
10391
|
+
if (on) finDmTgRefresh();
|
|
10392
|
+
});
|
|
10393
|
+
}
|
|
10394
|
+
if (els.finDmTgChat) {
|
|
10395
|
+
els.finDmTgChat.addEventListener('change', () => {
|
|
10396
|
+
const id = els.finDmTgChat.value || '';
|
|
10397
|
+
const g = finDmTgGroups.find((x) => String(x.id) === String(id));
|
|
10398
|
+
if (finCfgCache) {
|
|
10399
|
+
finCfgCache.dmTelegramChat = id;
|
|
10400
|
+
finCfgCache.dmTelegramTitle = g ? String(g.title || '') : '';
|
|
10401
|
+
}
|
|
10402
|
+
finSaveCfg({ dmTelegramChat: id, dmTelegramTitle: g ? String(g.title || '') : '' });
|
|
10403
|
+
toast(id ? 'Telegram grubu bağlandı: ' + (g ? g.title || id : id) : 'Telegram grubu seçilmedi');
|
|
10404
|
+
});
|
|
10405
|
+
}
|
|
10406
|
+
if (els.finDmTgRefresh) els.finDmTgRefresh.addEventListener('click', () => finDmTgRefresh());
|
|
10318
10407
|
finViewApply();
|
|
10319
10408
|
|
|
10320
10409
|
/* ---------- BÖLÜM SIRALAMA (sürükle-bırak) ----------
|
package/src/renderer/style.css
CHANGED
|
@@ -5869,3 +5869,23 @@ body.finance-mode #composerWrap { margin-right: var(--finW, 400px); }
|
|
|
5869
5869
|
.fin-set-row .fsr-main b { font-size: 12px; color: var(--text); letter-spacing: 0.4px; }
|
|
5870
5870
|
.fin-set-row .fsr-main i { font-style: normal; font-size: 10.5px; color: var(--muted); }
|
|
5871
5871
|
.fin-set-note { margin-top: 8px; font-size: 10.5px; color: var(--muted); line-height: 1.4; }
|
|
5872
|
+
.fin-set-sep { height: 1px; margin: 10px 0; background: var(--border); }
|
|
5873
|
+
.fin-set-sub {
|
|
5874
|
+
display: flex;
|
|
5875
|
+
flex-direction: column;
|
|
5876
|
+
gap: 6px;
|
|
5877
|
+
margin: 2px 0 6px;
|
|
5878
|
+
padding: 9px 10px;
|
|
5879
|
+
background: var(--panel);
|
|
5880
|
+
border: 1px solid var(--border);
|
|
5881
|
+
border-radius: 9px;
|
|
5882
|
+
}
|
|
5883
|
+
.fin-set-sub[hidden] { display: none; }
|
|
5884
|
+
.fin-set-lbl { font-size: 10.5px; color: var(--muted); letter-spacing: 0.5px; }
|
|
5885
|
+
.fin-set-sub select { width: 100%; }
|
|
5886
|
+
.fin-set-btn {
|
|
5887
|
+
align-self: flex-start;
|
|
5888
|
+
font-size: 10.5px;
|
|
5889
|
+
padding: 3px 8px;
|
|
5890
|
+
cursor: pointer;
|
|
5891
|
+
}
|