beast-agent 2.17.0 → 2.19.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 +219 -28
- package/src/agent/skills.js +1 -1
- package/src/agent/watchers.js +93 -1
- package/src/cron.js +46 -7
- package/src/main.js +457 -69
- package/src/preload.js +7 -0
- package/src/renderer/i18n.js +20 -0
- package/src/renderer/index.html +32 -1
- package/src/renderer/renderer.js +247 -3
- package/src/renderer/style.css +182 -3
package/src/preload.js
CHANGED
|
@@ -20,6 +20,8 @@ contextBridge.exposeInMainWorld('beast', {
|
|
|
20
20
|
agentsList: () => ipcRenderer.invoke('agents:list'),
|
|
21
21
|
agentsDetail: (id) => ipcRenderer.invoke('agents:detail', id),
|
|
22
22
|
agentsCancel: (id) => ipcRenderer.invoke('agents:cancel', id),
|
|
23
|
+
agentDmsList: () => ipcRenderer.invoke('agent-dms:list'),
|
|
24
|
+
agentDmsClear: () => ipcRenderer.invoke('agent-dms:clear'),
|
|
23
25
|
getCeoMode: () => ipcRenderer.invoke('ceo:get'),
|
|
24
26
|
setCeoMode: (v) => ipcRenderer.invoke('ceo:set', v),
|
|
25
27
|
listNotes: () => ipcRenderer.invoke('notes:list'),
|
|
@@ -106,6 +108,7 @@ contextBridge.exposeInMainWorld('beast', {
|
|
|
106
108
|
financeSettings: (patch) => ipcRenderer.invoke('finance:settings', patch),
|
|
107
109
|
financeTraderStart: () => ipcRenderer.invoke('finance:trader:start'),
|
|
108
110
|
financeTraderStop: () => ipcRenderer.invoke('finance:trader:stop'),
|
|
111
|
+
financeAgentSpawn: (symbol) => ipcRenderer.invoke('finance:agent:spawn', { symbol }),
|
|
109
112
|
financeConnect: () => ipcRenderer.invoke('finance:connect'),
|
|
110
113
|
financeClose: (ticket, volume) => ipcRenderer.invoke('finance:close', { ticket, volume }),
|
|
111
114
|
financeInstall: () => ipcRenderer.invoke('finance:install'),
|
|
@@ -146,6 +149,10 @@ contextBridge.exposeInMainWorld('beast', {
|
|
|
146
149
|
|
|
147
150
|
watchersToggle: (id) => ipcRenderer.invoke('watchers:toggle', id),
|
|
148
151
|
|
|
152
|
+
watchersLogs: () => ipcRenderer.invoke('watchers:logs'),
|
|
153
|
+
|
|
154
|
+
watchersLogsClear: (id) => ipcRenderer.invoke('watchers:logsClear', id),
|
|
155
|
+
|
|
149
156
|
providerKeys: () => ipcRenderer.invoke('providers:keys'),
|
|
150
157
|
|
|
151
158
|
openPath: (p) => ipcRenderer.invoke('shell:openPath', p),
|
package/src/renderer/i18n.js
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
tipThink: 'Düşünme (reasoning) seviyesi',
|
|
19
19
|
tipPickCfg: 'Picker\u2019da görünecek modeller',
|
|
20
20
|
tipRail: 'Paralel Ajan Konsolu',
|
|
21
|
+
tipAgentDm: 'Ajan DM — ajanlar arası konuşma',
|
|
21
22
|
tipNet: 'İnternet durumu',
|
|
22
23
|
tip_net_online: 'İnternet: bağlı',
|
|
23
24
|
tip_net_offline: 'İnternet: yok — bağlantı dönünce işler otomatik sürer',
|
|
@@ -61,6 +62,7 @@
|
|
|
61
62
|
tipLang: 'Dil değiştir / Switch language',
|
|
62
63
|
// kenar çubuğu & paneller
|
|
63
64
|
labelParallel: 'Paralel Ajanlar',
|
|
65
|
+
labelAgentDm: 'Ajan DM',
|
|
64
66
|
set_title: 'AYARLAR',
|
|
65
67
|
tab_lang: 'Dil',
|
|
66
68
|
lang_sub: 'Arayüz dili — uygulama dili ve sesli komut dili buradan değişir',
|
|
@@ -542,6 +544,14 @@
|
|
|
542
544
|
bot_no_watchers: 'Bu bota ait izleyici yok.',
|
|
543
545
|
w_pane: 'İZLEYİCİLER',
|
|
544
546
|
w_empty: 'Kayıtlı izleyici yok.',
|
|
547
|
+
tipWatchLog: 'İzleyici loglarını gör',
|
|
548
|
+
w_log_title: 'İzleyici Logları',
|
|
549
|
+
w_log_clear: 'Seçili izleyicinin loglarını temizle',
|
|
550
|
+
w_log_cleared: 'Loglar temizlendi',
|
|
551
|
+
w_log_empty: 'Bu izleyici için henüz log kaydı yok.',
|
|
552
|
+
w_log_ev_ok: 'kontrol',
|
|
553
|
+
w_log_ev_trigger: 'tetik',
|
|
554
|
+
w_log_ev_error: 'hata',
|
|
545
555
|
bot_stats_sub: 'Bu botun kullanım özeti.',
|
|
546
556
|
bot_stat_numbers: 'Numara',
|
|
547
557
|
bot_stat_sessions: 'Sohbet',
|
|
@@ -655,6 +665,7 @@
|
|
|
655
665
|
tipThink: 'Reasoning level',
|
|
656
666
|
tipPickCfg: 'Models shown in picker',
|
|
657
667
|
tipRail: 'Parallel Agents Console',
|
|
668
|
+
tipAgentDm: 'Agent DM — agent-to-agent chat',
|
|
658
669
|
tipNet: 'Internet status',
|
|
659
670
|
tip_net_online: 'Internet: connected',
|
|
660
671
|
tip_net_offline: 'Internet: offline — work resumes automatically once the connection returns',
|
|
@@ -696,6 +707,7 @@
|
|
|
696
707
|
tipThemeLight: 'Light theme',
|
|
697
708
|
tipLang: 'Dil değiştir / Switch language',
|
|
698
709
|
labelParallel: 'Parallel Agents',
|
|
710
|
+
labelAgentDm: 'Agent DM',
|
|
699
711
|
set_title: 'SETTINGS',
|
|
700
712
|
tab_lang: 'Language',
|
|
701
713
|
lang_sub: 'Interface language — app UI and voice command language',
|
|
@@ -1038,6 +1050,14 @@
|
|
|
1038
1050
|
cr_toggle_pause: 'Pause',
|
|
1039
1051
|
w_empty: 'No saved watchers — add from the form above.',
|
|
1040
1052
|
w_pane: 'WATCHERS',
|
|
1053
|
+
tipWatchLog: 'View watcher logs',
|
|
1054
|
+
w_log_title: 'Watcher Logs',
|
|
1055
|
+
w_log_clear: 'Clear selected watcher logs',
|
|
1056
|
+
w_log_cleared: 'Logs cleared',
|
|
1057
|
+
w_log_empty: 'No log entries for this watcher yet.',
|
|
1058
|
+
w_log_ev_ok: 'check',
|
|
1059
|
+
w_log_ev_trigger: 'trigger',
|
|
1060
|
+
w_log_ev_error: 'error',
|
|
1041
1061
|
wa_vazgec: 'Cancel',
|
|
1042
1062
|
wa_kaydet: 'save',
|
|
1043
1063
|
wa_updated: 'Updated',
|
package/src/renderer/index.html
CHANGED
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
<div id="watchPaneHead">
|
|
18
18
|
<span id="watchPaneTitle" data-i18n="w_pane">İZLEYİCİLER</span>
|
|
19
19
|
<span class="file-spacer"></span>
|
|
20
|
-
<button id="
|
|
20
|
+
<button id="watchPaneLog" title="İzleyici loglarını gör" data-i18n-title="tipWatchLog"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M10 9H8"/><path d="M16 13H8"/><path d="M16 17H8"/></svg></button>
|
|
21
|
+
<button id="watchPaneOpen" title="İzleyicileri yönet" data-i18n-title="tipWatch">+</button>
|
|
21
22
|
</div>
|
|
22
23
|
<div id="watchPaneList"></div>
|
|
23
24
|
</div>
|
|
@@ -93,6 +94,7 @@
|
|
|
93
94
|
<button id="finBtn" class="dd-btn dd-icon-btn" title="Beast Finance — MT5 trade paneli (bilgisayardaki MetaTrader 5 ile çalışır)"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3v18h18"/><path d="M7 15l4-5 3 3 5-7"/></svg></button>
|
|
94
95
|
<button id="sbBtn" class="dd-btn dd-icon-btn" title="Beast Sandbox — GitHub reposu indir & içinde çalış" data-i18n-title="tipSandbox"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/></svg></button>
|
|
95
96
|
<button id="railBtn" class="dd-btn dd-icon-btn" title="Paralel Ajan Konsolu" data-i18n-title="tipRail">▤</button>
|
|
97
|
+
<button id="dmBtn" class="dd-btn dd-icon-btn" title="Ajan DM — ajanlar arası konuşma" data-i18n-title="tipAgentDm">✉︎</button>
|
|
96
98
|
<button id="watchBtn" class="dd-btn dd-icon-btn" title="İzleyiciler (Watchers)" data-i18n-title="tipWatch">◎</button>
|
|
97
99
|
<button id="cronBtn" class="dd-btn dd-icon-btn" title="Cron Görevler" data-i18n-title="tipCron">⏱︎</button>
|
|
98
100
|
<button id="termCBtn" class="dd-btn dd-icon-btn" title="CMD terminali" data-i18n-title="tipTermC">❯︎</button>
|
|
@@ -345,6 +347,19 @@
|
|
|
345
347
|
<span class="foot-label2" data-i18n="labelParallel">Paralel Ajanlar</span>
|
|
346
348
|
</div>
|
|
347
349
|
</aside>
|
|
350
|
+
|
|
351
|
+
<aside id="dmRail" class="dm-hidden">
|
|
352
|
+
<div id="dmRailHead">
|
|
353
|
+
<span id="dmRailTitle" data-i18n="labelAgentDm">AJAN DM</span>
|
|
354
|
+
<button id="dmClear" title="DM geçmişini temizle" aria-label="DM geçmişini temizle">
|
|
355
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#111" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18"/><path d="M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6"/><path d="M14 11v6"/></svg>
|
|
356
|
+
</button>
|
|
357
|
+
</div>
|
|
358
|
+
<div id="dmRailList"></div>
|
|
359
|
+
<div id="sideFoot2">
|
|
360
|
+
<span class="foot-label2" data-i18n="labelAgentDm">Ajan DM</span>
|
|
361
|
+
</div>
|
|
362
|
+
</aside>
|
|
348
363
|
</div>
|
|
349
364
|
|
|
350
365
|
<div id="settingsOverlay" hidden>
|
|
@@ -528,6 +543,22 @@
|
|
|
528
543
|
</div>
|
|
529
544
|
</div>
|
|
530
545
|
|
|
546
|
+
<div id="watchLogOverlay" class="mini-overlay" hidden>
|
|
547
|
+
<div class="mini-dialog">
|
|
548
|
+
<div class="mini-head">
|
|
549
|
+
<span class="mini-title" data-i18n="w_log_title">İzleyici Logları</span>
|
|
550
|
+
<button class="mini-close" id="watchLogClose" title="Kapat" data-i18n-title="btn_close">×</button>
|
|
551
|
+
</div>
|
|
552
|
+
<div class="mini-body">
|
|
553
|
+
<div id="watchLogBar">
|
|
554
|
+
<select id="watchLogSel" class="mini-select"></select>
|
|
555
|
+
<button id="watchLogClear" class="mr-btn" title="Seçili izleyicinin loglarını temizle" data-i18n-title="w_log_clear"><svg viewBox="0 0 24 24" width="12" height="12" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18"/><path d="M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6"/><path d="M14 11v6"/></svg></button>
|
|
556
|
+
</div>
|
|
557
|
+
<div id="watchLogList" class="mini-list"></div>
|
|
558
|
+
</div>
|
|
559
|
+
</div>
|
|
560
|
+
</div>
|
|
561
|
+
|
|
531
562
|
<div id="finSymOverlay" class="mini-overlay" hidden>
|
|
532
563
|
<div class="mini-dialog fin-sym-dialog">
|
|
533
564
|
<div class="mini-head">
|
package/src/renderer/renderer.js
CHANGED
|
@@ -42,9 +42,13 @@ const els = {
|
|
|
42
42
|
netDot: $('#netDot'),
|
|
43
43
|
railBtn: $('#railBtn'),
|
|
44
44
|
railClear: $('#railClear'),
|
|
45
|
+
dmBtn: $('#dmBtn'),
|
|
46
|
+
dmRailList: $('#dmRailList'),
|
|
47
|
+
dmClear: $('#dmClear'),
|
|
45
48
|
watchBtn: $('#watchBtn'),
|
|
46
49
|
watchPaneList: $('#watchPaneList'),
|
|
47
50
|
watchPaneOpen: $('#watchPaneOpen'),
|
|
51
|
+
watchPaneLog: $('#watchPaneLog'),
|
|
48
52
|
cronBtn: $('#cronBtn'),
|
|
49
53
|
watchOverlay: $('#watchOverlay'),
|
|
50
54
|
cronOverlay: $('#cronOverlay'),
|
|
@@ -52,6 +56,11 @@ const els = {
|
|
|
52
56
|
cronClose: $('#cronClose'),
|
|
53
57
|
watchList: $('#watchList'),
|
|
54
58
|
cronModalList: $('#cronModalList'),
|
|
59
|
+
watchLogOverlay: $('#watchLogOverlay'),
|
|
60
|
+
watchLogClose: $('#watchLogClose'),
|
|
61
|
+
watchLogSel: $('#watchLogSel'),
|
|
62
|
+
watchLogClear: $('#watchLogClear'),
|
|
63
|
+
watchLogList: $('#watchLogList'),
|
|
55
64
|
browserBar: $('#browserBar'),
|
|
56
65
|
bbBack: $('#bbBack'),
|
|
57
66
|
bbFwd: $('#bbFwd'),
|
|
@@ -4993,6 +5002,113 @@ async function loadRailChat(id) {
|
|
|
4993
5002
|
}
|
|
4994
5003
|
}
|
|
4995
5004
|
|
|
5005
|
+
/* ---------------- AJAN DM sütunu (ajanlar arası konuşma) ----------------
|
|
5006
|
+
rail ile aynı mimari: sağda ikinci sütun, dmBtn ile açılır/kapanır.
|
|
5007
|
+
DM'ler ajanların agent_dm araç çağrılarından gelir; çiftlere gruplanır. */
|
|
5008
|
+
|
|
5009
|
+
const dmState = {
|
|
5010
|
+
dms: [], // { at, from, fromTitle, to, toTitle, text }
|
|
5011
|
+
open: new Set(), // açık thread key'leri
|
|
5012
|
+
};
|
|
5013
|
+
|
|
5014
|
+
function dmPairOf(dm) {
|
|
5015
|
+
const a = String(dm.from || '');
|
|
5016
|
+
const b = String(dm.to || '');
|
|
5017
|
+
return a < b ? a + '|' + b : b + '|' + a;
|
|
5018
|
+
}
|
|
5019
|
+
|
|
5020
|
+
function dmPairTitle(dm) {
|
|
5021
|
+
const a = String(dm.fromTitle || 'Ajan');
|
|
5022
|
+
const b = String(dm.toTitle || 'Ajan');
|
|
5023
|
+
return a < b ? a + ' ↔ ' + b : b + ' ↔ ' + a;
|
|
5024
|
+
}
|
|
5025
|
+
|
|
5026
|
+
function dmTime(iso) {
|
|
5027
|
+
const d = new Date(iso || '');
|
|
5028
|
+
if (!d.getTime()) return '';
|
|
5029
|
+
return d.toLocaleTimeString('tr-TR', { hour: '2-digit', minute: '2-digit' });
|
|
5030
|
+
}
|
|
5031
|
+
|
|
5032
|
+
function renderDmRail() {
|
|
5033
|
+
const list = els.dmRailList;
|
|
5034
|
+
if (!list) return;
|
|
5035
|
+
if (!dmState.dms.length) {
|
|
5036
|
+
list.innerHTML = '<div class="dm-empty">Ajanlar arasında DM yok.<br>Ajanlar agent_dm aracıyla birbirine mesaj attıkça burada görünür.</div>';
|
|
5037
|
+
return;
|
|
5038
|
+
}
|
|
5039
|
+
/* çiftlere grupla (kronolojik) — en yeni thread üstte */
|
|
5040
|
+
const threads = new Map();
|
|
5041
|
+
for (const dm of dmState.dms) {
|
|
5042
|
+
const key = dmPairOf(dm);
|
|
5043
|
+
if (!threads.has(key)) threads.set(key, []);
|
|
5044
|
+
threads.get(key).push(dm);
|
|
5045
|
+
}
|
|
5046
|
+
const rows = [...threads.entries()].sort(
|
|
5047
|
+
(x, y) => new Date(y[1][y[1].length - 1].at) - new Date(x[1][x[1].length - 1].at)
|
|
5048
|
+
);
|
|
5049
|
+
list.innerHTML = '';
|
|
5050
|
+
for (const [key, msgs] of rows) {
|
|
5051
|
+
const open = dmState.open.has(key);
|
|
5052
|
+
const last = msgs[msgs.length - 1];
|
|
5053
|
+
const el = document.createElement('div');
|
|
5054
|
+
el.className = 'dmt' + (open ? ' open' : '');
|
|
5055
|
+
el.innerHTML =
|
|
5056
|
+
'<div class="dmt-head">' +
|
|
5057
|
+
`<span class="dmt-title">${escapeHtml(dmPairTitle(last))}</span>` +
|
|
5058
|
+
`<span class="dmt-count">${msgs.length}</span>` +
|
|
5059
|
+
'</div>' +
|
|
5060
|
+
`<div class="dmt-last">${escapeHtml(String(last.text || '').replace(/\s+/g, ' ').slice(0, 90))} · ${dmTime(last.at)}</div>` +
|
|
5061
|
+
'<div class="dmt-msgs">' +
|
|
5062
|
+
msgs
|
|
5063
|
+
.map(
|
|
5064
|
+
(m) =>
|
|
5065
|
+
`<div class="dmt-msg"><span class="dm-who">${escapeHtml(String(m.fromTitle || 'Ajan'))} → ${escapeHtml(String(m.toTitle || 'Ajan'))}</span>` +
|
|
5066
|
+
`${escapeHtml(String(m.text || ''))}<span class="dm-at">${dmTime(m.at)}</span></div>`
|
|
5067
|
+
)
|
|
5068
|
+
.join('') +
|
|
5069
|
+
'</div>';
|
|
5070
|
+
el.addEventListener('click', () => {
|
|
5071
|
+
if (dmState.open.has(key)) dmState.open.delete(key);
|
|
5072
|
+
else dmState.open.add(key);
|
|
5073
|
+
renderDmRail();
|
|
5074
|
+
const again = els.dmRailList.querySelector('.dmt.open .dmt-msgs');
|
|
5075
|
+
if (again) again.scrollTop = again.scrollHeight;
|
|
5076
|
+
});
|
|
5077
|
+
list.appendChild(el);
|
|
5078
|
+
}
|
|
5079
|
+
}
|
|
5080
|
+
|
|
5081
|
+
async function refreshDmRail() {
|
|
5082
|
+
try {
|
|
5083
|
+
const dms = await beast.agentDmsList();
|
|
5084
|
+
if (Array.isArray(dms)) dmState.dms = dms;
|
|
5085
|
+
} catch {}
|
|
5086
|
+
renderDmRail();
|
|
5087
|
+
}
|
|
5088
|
+
|
|
5089
|
+
function toggleDmRail(hide) {
|
|
5090
|
+
const rail = $('#dmRail');
|
|
5091
|
+
if (!rail) return;
|
|
5092
|
+
rail.classList.toggle('dm-hidden', !!hide);
|
|
5093
|
+
if (els.dmBtn) els.dmBtn.classList.toggle('on', !hide);
|
|
5094
|
+
if (!hide) refreshDmRail();
|
|
5095
|
+
}
|
|
5096
|
+
|
|
5097
|
+
if (els.dmBtn) {
|
|
5098
|
+
els.dmBtn.addEventListener('click', () => {
|
|
5099
|
+
toggleDmRail(!$('#dmRail').classList.contains('dm-hidden'));
|
|
5100
|
+
});
|
|
5101
|
+
}
|
|
5102
|
+
if (els.dmClear) {
|
|
5103
|
+
els.dmClear.addEventListener('click', async () => {
|
|
5104
|
+
if (!(await uiConfirm('TÜM ajan DM geçmişi silinsin mi?', 'Sil'))) return;
|
|
5105
|
+
try { await beast.agentDmsClear(); } catch {}
|
|
5106
|
+
dmState.dms = [];
|
|
5107
|
+
renderDmRail();
|
|
5108
|
+
toast('Ajan DM geçmişi silindi');
|
|
5109
|
+
});
|
|
5110
|
+
}
|
|
5111
|
+
|
|
4996
5112
|
function renderAgentsPane() {
|
|
4997
5113
|
const pane = $('#tab-agents');
|
|
4998
5114
|
if (!pane) return;
|
|
@@ -5137,6 +5253,20 @@ function onEvent(ev) {
|
|
|
5137
5253
|
scheduleAgentsRender();
|
|
5138
5254
|
return;
|
|
5139
5255
|
}
|
|
5256
|
+
/* AJAN DM: ajanlar arası mesaj — panel açıksa canlı düşer */
|
|
5257
|
+
if (ev.type === 'agent-dm') {
|
|
5258
|
+
dmState.dms.push({
|
|
5259
|
+
at: ev.at,
|
|
5260
|
+
from: ev.from,
|
|
5261
|
+
fromTitle: ev.fromTitle,
|
|
5262
|
+
to: ev.to,
|
|
5263
|
+
toTitle: ev.toTitle,
|
|
5264
|
+
text: ev.text,
|
|
5265
|
+
});
|
|
5266
|
+
if (dmState.dms.length > 400) dmState.dms.splice(0, dmState.dms.length - 400);
|
|
5267
|
+
if ($('#dmRail') && !$('#dmRail').classList.contains('dm-hidden')) renderDmRail();
|
|
5268
|
+
return;
|
|
5269
|
+
}
|
|
5140
5270
|
/* OFFLINE MESAJ KUYRUĞU: bağlantı + kuyruk olayları (sessionId filtresinden önce) */
|
|
5141
5271
|
if (ev.type === 'net' || ev.type === 'netQueue') { onNetEvent(ev); return; }
|
|
5142
5272
|
/* Sandbox klonlama progress'i (sessionId'siz global olay) */
|
|
@@ -5611,6 +5741,11 @@ async function renderWatchersPane(force) {
|
|
|
5611
5741
|
`</div></div>`;
|
|
5612
5742
|
const btns = document.createElement('div');
|
|
5613
5743
|
btns.className = 'wp-btns';
|
|
5744
|
+
const lg = document.createElement('button');
|
|
5745
|
+
lg.className = 'wp-btn';
|
|
5746
|
+
lg.innerHTML = '<svg viewBox="0 0 24 24" width="12" height="12" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M10 9H8"/><path d="M16 13H8"/><path d="M16 17H8"/></svg>';
|
|
5747
|
+
lg.title = _t('w_log_title');
|
|
5748
|
+
lg.addEventListener('click', (e) => { e.stopPropagation(); openWatchLogModal(w.id); });
|
|
5614
5749
|
const t = document.createElement('button');
|
|
5615
5750
|
t.className = 'wp-btn';
|
|
5616
5751
|
t.textContent = w.enabled ? '❚❚' : '▶';
|
|
@@ -5632,7 +5767,7 @@ async function renderWatchersPane(force) {
|
|
|
5632
5767
|
renderWatchersPane(true);
|
|
5633
5768
|
renderWatchersModal(true);
|
|
5634
5769
|
});
|
|
5635
|
-
btns.append(t, d);
|
|
5770
|
+
btns.append(lg, t, d);
|
|
5636
5771
|
row.appendChild(btns);
|
|
5637
5772
|
row.addEventListener('click', () => openWatchModal());
|
|
5638
5773
|
list.appendChild(row);
|
|
@@ -5669,6 +5804,11 @@ async function renderWatchersModal(force) {
|
|
|
5669
5804
|
`</div></div>`;
|
|
5670
5805
|
const btns = document.createElement('div');
|
|
5671
5806
|
btns.style.cssText = 'display:flex;gap:6px;flex:none';
|
|
5807
|
+
const lg = document.createElement('button');
|
|
5808
|
+
lg.className = 'mr-btn';
|
|
5809
|
+
lg.innerHTML = '<svg viewBox="0 0 24 24" width="12" height="12" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M10 9H8"/><path d="M16 13H8"/><path d="M16 17H8"/></svg>';
|
|
5810
|
+
lg.title = _t('w_log_title');
|
|
5811
|
+
lg.addEventListener('click', () => openWatchLogModal(w.id));
|
|
5672
5812
|
const t = document.createElement('button');
|
|
5673
5813
|
t.className = 'mr-btn';
|
|
5674
5814
|
t.textContent = w.enabled ? '❚❚' : '▶';
|
|
@@ -5679,12 +5819,85 @@ async function renderWatchersModal(force) {
|
|
|
5679
5819
|
d.textContent = '×';
|
|
5680
5820
|
d.title = _t('cr_del');
|
|
5681
5821
|
d.addEventListener('click', async () => { await beast.watchersRemove(w.id); renderWatchersModal(); });
|
|
5682
|
-
btns.append(t, d);
|
|
5822
|
+
btns.append(lg, t, d);
|
|
5683
5823
|
row.appendChild(btns);
|
|
5684
5824
|
els.watchList.appendChild(row);
|
|
5685
5825
|
}
|
|
5686
5826
|
}
|
|
5687
5827
|
|
|
5828
|
+
/* ---------- İZLEYİCİ LOG MODALI ----------
|
|
5829
|
+
Her izleyicinin logu AYRI tutulur (watcher-logs.json) ve AYRI gösterilir:
|
|
5830
|
+
üstteki seçiciyle izleyici seç → yalnız onun denetim kayıtları listelenir. */
|
|
5831
|
+
let watchLogSelId = '';
|
|
5832
|
+
let lastWatchLogKey = '';
|
|
5833
|
+
let lastWatchLogSelKey = '';
|
|
5834
|
+
|
|
5835
|
+
async function renderWatchLogModal(force) {
|
|
5836
|
+
if (!els.watchLogOverlay) return;
|
|
5837
|
+
let rows = []; try { rows = (await beast.watchersList()) || []; } catch {}
|
|
5838
|
+
let logsMap = {}; try { logsMap = (await beast.watchersLogs()) || {}; } catch {}
|
|
5839
|
+
/* seçim: yok olan seçilmişse ilk izleyiciye düş */
|
|
5840
|
+
if (!rows.some((w) => w.id === watchLogSelId)) watchLogSelId = rows.length ? rows[0].id : '';
|
|
5841
|
+
/* seçici — izleyici listesi değişmediyse DOM'a dokunma (odak korunur) */
|
|
5842
|
+
const selKey = JSON.stringify(rows.map((w) => [w.id, w.name, w.enabled]));
|
|
5843
|
+
if (selKey !== lastWatchLogSelKey) {
|
|
5844
|
+
lastWatchLogSelKey = selKey;
|
|
5845
|
+
els.watchLogSel.innerHTML = '';
|
|
5846
|
+
if (!rows.length) {
|
|
5847
|
+
const o = document.createElement('option');
|
|
5848
|
+
o.textContent = _t('w_empty');
|
|
5849
|
+
o.value = '';
|
|
5850
|
+
els.watchLogSel.appendChild(o);
|
|
5851
|
+
} else {
|
|
5852
|
+
for (const w of rows) {
|
|
5853
|
+
const o = document.createElement('option');
|
|
5854
|
+
o.value = w.id;
|
|
5855
|
+
o.textContent = (w.enabled ? '' : '⏸ ') + w.name;
|
|
5856
|
+
els.watchLogSel.appendChild(o);
|
|
5857
|
+
}
|
|
5858
|
+
}
|
|
5859
|
+
els.watchLogSel.value = watchLogSelId;
|
|
5860
|
+
}
|
|
5861
|
+
/* log satırları — yalnız seçili izleyicinin kayıtları */
|
|
5862
|
+
const entries = watchLogSelId ? (logsMap[watchLogSelId] || []) : [];
|
|
5863
|
+
const key = JSON.stringify([watchLogSelId, selKey, entries]);
|
|
5864
|
+
if (!force && key === lastWatchLogKey) return;
|
|
5865
|
+
lastWatchLogKey = key;
|
|
5866
|
+
els.watchLogList.innerHTML = '';
|
|
5867
|
+
if (!watchLogSelId || !entries.length) {
|
|
5868
|
+
els.watchLogList.innerHTML = '<div class="mini-empty">' + _t('w_log_empty') + '</div>';
|
|
5869
|
+
return;
|
|
5870
|
+
}
|
|
5871
|
+
const evBadge = { ok: ['ok', _t('w_log_ev_ok')], trigger: ['trigger', _t('w_log_ev_trigger')], error: ['error', _t('w_log_ev_error')] };
|
|
5872
|
+
for (const en of entries) {
|
|
5873
|
+
const [cls, label] = evBadge[en.ev] || ['ok', en.ev];
|
|
5874
|
+
const row = document.createElement('div');
|
|
5875
|
+
row.className = 'wl-row';
|
|
5876
|
+
row.innerHTML =
|
|
5877
|
+
`<span class="wl-time">${escapeHtml(fmtWhen(en.ts))}</span>` +
|
|
5878
|
+
`<span class="wl-badge ${cls}">${escapeHtml(label)}</span>` +
|
|
5879
|
+
`<span class="wl-main">` +
|
|
5880
|
+
(en.ev === 'error'
|
|
5881
|
+
? `<span class="wl-err">${escapeHtml(String(en.error || '').slice(0, 120))}</span>`
|
|
5882
|
+
: (en.value !== null && en.value !== undefined ? escapeHtml(String(en.value).slice(0, 120)) : '—')) +
|
|
5883
|
+
`</span>`;
|
|
5884
|
+
els.watchLogList.appendChild(row);
|
|
5885
|
+
}
|
|
5886
|
+
}
|
|
5887
|
+
|
|
5888
|
+
function closeWatchLogModal() {
|
|
5889
|
+
toggleMini(els.watchLogOverlay, true);
|
|
5890
|
+
stopMiniRefresh();
|
|
5891
|
+
}
|
|
5892
|
+
|
|
5893
|
+
async function openWatchLogModal(id) {
|
|
5894
|
+
if (id) watchLogSelId = String(id);
|
|
5895
|
+
lastWatchLogSelKey = ''; /* seçici her açılışta TAZE kurulsun */
|
|
5896
|
+
toggleMini(els.watchLogOverlay, false);
|
|
5897
|
+
await renderWatchLogModal(true);
|
|
5898
|
+
startMiniRefresh();
|
|
5899
|
+
}
|
|
5900
|
+
|
|
5688
5901
|
let lastCronKey = '';
|
|
5689
5902
|
async function renderCronModal(force) {
|
|
5690
5903
|
let jobs = [];
|
|
@@ -5746,6 +5959,7 @@ function startMiniRefresh() {
|
|
|
5746
5959
|
stopMiniRefresh();
|
|
5747
5960
|
miniRefreshTimer = setInterval(async () => {
|
|
5748
5961
|
if (els.watchOverlay && !els.watchOverlay.hidden) await renderWatchersModal();
|
|
5962
|
+
else if (els.watchLogOverlay && !els.watchLogOverlay.hidden) await renderWatchLogModal();
|
|
5749
5963
|
else if (els.cronOverlay && !els.cronOverlay.hidden) await renderCronModal();
|
|
5750
5964
|
else stopMiniRefresh();
|
|
5751
5965
|
}, 4000);
|
|
@@ -5976,6 +6190,8 @@ const SLASH_COMMANDS = [
|
|
|
5976
6190
|
{ cmd: '/notify', desc: 'hata maili aç/kapa · /notify on|off' },
|
|
5977
6191
|
{ cmd: '/think ', desc: 'düşünme seviyesi · /think 0-5 (0 kapalı)' },
|
|
5978
6192
|
{ cmd: '/clear', desc: 'oturum geçmişini GERÇEKTEN sil (kod korunur)' },
|
|
6193
|
+
{ cmd: '/autodel', desc: 'tüm otomatik hatırlatmaları sil · /autodel all: cron dahil hepsi' },
|
|
6194
|
+
{ cmd: '/deltodo', desc: 'todo listesini temizle · /deltodo all: tüm oturumlar' },
|
|
5979
6195
|
{ cmd: '/start', desc: 'durdurulan servisleri devam ettir' },
|
|
5980
6196
|
{ cmd: '/rule ', desc: 'kalıcı kural ekle' },
|
|
5981
6197
|
{ cmd: '/rules', desc: 'kalıcı kuralları listele' },
|
|
@@ -6487,12 +6703,29 @@ async function init() {
|
|
|
6487
6703
|
/* cron modülü — olay bağlama */
|
|
6488
6704
|
if (els.watchBtn) els.watchBtn.addEventListener('click', openWatchModal);
|
|
6489
6705
|
if (els.watchPaneOpen) els.watchPaneOpen.addEventListener('click', openWatchModal);
|
|
6706
|
+
if (els.watchPaneLog) els.watchPaneLog.addEventListener('click', () => openWatchLogModal());
|
|
6490
6707
|
if (els.cronBtn) els.cronBtn.addEventListener('click', openCronModal);
|
|
6491
6708
|
if (els.watchClose) els.watchClose.addEventListener('click', closeWatchModal);
|
|
6492
6709
|
if (els.cronClose) els.cronClose.addEventListener('click', closeCronModal);
|
|
6710
|
+
if (els.watchLogClose) els.watchLogClose.addEventListener('click', closeWatchLogModal);
|
|
6711
|
+
if (els.watchLogSel) els.watchLogSel.addEventListener('change', () => {
|
|
6712
|
+
watchLogSelId = els.watchLogSel.value;
|
|
6713
|
+
lastWatchLogKey = '';
|
|
6714
|
+
renderWatchLogModal(true);
|
|
6715
|
+
});
|
|
6716
|
+
if (els.watchLogClear) els.watchLogClear.addEventListener('click', async () => {
|
|
6717
|
+
if (!watchLogSelId) return;
|
|
6718
|
+
await beast.watchersLogsClear(watchLogSelId);
|
|
6719
|
+
lastWatchLogKey = '';
|
|
6720
|
+
await renderWatchLogModal(true);
|
|
6721
|
+
toast(_t('w_log_cleared'));
|
|
6722
|
+
});
|
|
6493
6723
|
if (els.watchOverlay) els.watchOverlay.addEventListener('click', (e) => {
|
|
6494
6724
|
if (e.target === els.watchOverlay) closeWatchModal();
|
|
6495
6725
|
});
|
|
6726
|
+
if (els.watchLogOverlay) els.watchLogOverlay.addEventListener('click', (e) => {
|
|
6727
|
+
if (e.target === els.watchLogOverlay) closeWatchLogModal();
|
|
6728
|
+
});
|
|
6496
6729
|
if (els.cronOverlay) els.cronOverlay.addEventListener('click', (e) => {
|
|
6497
6730
|
if (e.target === els.cronOverlay) closeCronModal();
|
|
6498
6731
|
});
|
|
@@ -6579,6 +6812,7 @@ async function init() {
|
|
|
6579
6812
|
document.addEventListener('keydown', (e) => {
|
|
6580
6813
|
if (e.key === 'Escape') {
|
|
6581
6814
|
if ($('#botOverlay') && !$('#botOverlay').hidden) { botOverlaySetOpen(false); return; }
|
|
6815
|
+
if (els.watchLogOverlay && !els.watchLogOverlay.hidden) { closeWatchLogModal(); return; }
|
|
6582
6816
|
if (els.watchOverlay && !els.watchOverlay.hidden) { closeWatchModal(); return; }
|
|
6583
6817
|
if (els.cronOverlay && !els.cronOverlay.hidden) { closeCronModal(); return; }
|
|
6584
6818
|
if (!els.settingsOverlay.hidden) closeSettings();
|
|
@@ -8234,7 +8468,17 @@ function finRenderSymbols(list) {
|
|
|
8234
8468
|
row.innerHTML =
|
|
8235
8469
|
'<span class="fs-name">' + (s.symbol || '?') + '</span>' +
|
|
8236
8470
|
'<span class="fs-price ' + cls + '">' + bid.toFixed(digits) + '</span>' +
|
|
8237
|
-
'<span class="fs-spread">sp ' + (s.spread != null ? s.spread : '—') + '</span>'
|
|
8471
|
+
'<span class="fs-spread">sp ' + (s.spread != null ? s.spread : '—') + '</span>' +
|
|
8472
|
+
'<button class="fs-agent" title="' + escapeHtml(s.symbol || '') + ' için AYRI finance ajanı başlat (paralel koşar)">▶︎</button>';
|
|
8473
|
+
const spawnBtn = row.querySelector('.fs-agent');
|
|
8474
|
+
if (spawnBtn) {
|
|
8475
|
+
spawnBtn.addEventListener('click', async (e) => {
|
|
8476
|
+
e.stopPropagation();
|
|
8477
|
+
const r = await beast.financeAgentSpawn(s.symbol).catch((err) => ({ ok: false, error: String((err && err.message) || err) }));
|
|
8478
|
+
if (r && r.ok) toast(s.symbol + ' için ajan başladı — Paralel Ajanlar panelinde izle');
|
|
8479
|
+
else toast((r && r.error) || 'Ajan başlatılamadı');
|
|
8480
|
+
});
|
|
8481
|
+
}
|
|
8238
8482
|
els.finSymList.appendChild(row);
|
|
8239
8483
|
}
|
|
8240
8484
|
}
|