beast-agent 2.30.6 → 2.32.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/fsguard.js +46 -0
- package/src/agent/mcp.js +98 -18
- package/src/agent/tools.js +114 -4
- package/src/main.js +163 -22
- package/src/preload.js +5 -0
- package/src/renderer/i18n.js +121 -30
- package/src/renderer/index.html +40 -0
- package/src/renderer/renderer.js +293 -11
- package/src/renderer/style.css +13 -0
package/src/renderer/renderer.js
CHANGED
|
@@ -229,6 +229,7 @@ const els = {
|
|
|
229
229
|
cronSchedule: $('#cronSchedule'),
|
|
230
230
|
cronPrompt: $('#cronPrompt'),
|
|
231
231
|
cronAddBtn: $('#cronAddBtn'),
|
|
232
|
+
cronCancel: $('#cronCancel'),
|
|
232
233
|
cronList: $('#cronList'),
|
|
233
234
|
gearBtn: $('#gearBtn'),
|
|
234
235
|
settingsOverlay: $('#settingsOverlay'),
|
|
@@ -1242,6 +1243,7 @@ async function renderActiveSettingsTab() {
|
|
|
1242
1243
|
case 'events': await renderEventsPane(); break;
|
|
1243
1244
|
case 'empati': await renderEmpatiPane(); break;
|
|
1244
1245
|
case 'cron': await openCron(); break;
|
|
1246
|
+
case 'agenda': await renderAgendaPane(); break;
|
|
1245
1247
|
case 'usage': await renderUsagePane(); break;
|
|
1246
1248
|
case 'headroom': await renderHeadroomPane(); break;
|
|
1247
1249
|
case 'agents': await refreshAgentsPane(); break;
|
|
@@ -1327,12 +1329,14 @@ function switchTab(name) {
|
|
|
1327
1329
|
document.querySelectorAll('#setTabs .tab').forEach((b) =>
|
|
1328
1330
|
b.classList.toggle('active', b.dataset.tab === name)
|
|
1329
1331
|
);
|
|
1330
|
-
for (const p of ['lang', 'provider', 'fallout', 'skills', 'agents', 'tts', 'install', 'email', 'integrations', 'websearch', 'mcp', 'events', 'empati', 'cron', 'usage', 'headroom', 'logs', 'dash', 'sec', 'update']) {
|
|
1332
|
+
for (const p of ['lang', 'provider', 'fallout', 'skills', 'agents', 'tts', 'install', 'email', 'integrations', 'websearch', 'mcp', 'events', 'empati', 'cron', 'agenda', 'usage', 'headroom', 'logs', 'dash', 'sec', 'update']) {
|
|
1331
1333
|
const el = $('#tab-' + p);
|
|
1332
1334
|
if (el) el.hidden = p !== name; // guard: eksik pane tüm sekmeleri kilitlemesin
|
|
1333
1335
|
}
|
|
1334
1336
|
if (name === 'lang') renderLangPane();
|
|
1335
1337
|
if (name === 'cron') openCron();
|
|
1338
|
+
if (name === 'agenda') renderAgendaPane();
|
|
1339
|
+
if (name === 'email') renderEmailPane();
|
|
1336
1340
|
if (name === 'usage') renderUsagePane();
|
|
1337
1341
|
if (name === 'install') renderInstallPane();
|
|
1338
1342
|
if (name === 'headroom') renderHeadroomPane();
|
|
@@ -2640,7 +2644,25 @@ async function renderEmailPane() {
|
|
|
2640
2644
|
<input id="mailSmtpPort" class="inp" placeholder="465" autocomplete="off" />
|
|
2641
2645
|
<button id="mailSave" class="btn ghost">${_t('mail_save')}</button>
|
|
2642
2646
|
</div>` +
|
|
2643
|
-
'<div class="sub" style="margin-top:8px">' + _t('mail_note') + '</div>'
|
|
2647
|
+
'<div class="sub" style="margin-top:8px">' + _t('mail_note') + '</div>' +
|
|
2648
|
+
'<div class="divider"></div>' +
|
|
2649
|
+
'<h2>' + _t('mail_inbox') + '</h2>' +
|
|
2650
|
+
'<div style="display:flex;gap:8px;margin:6px 0;align-items:center">' +
|
|
2651
|
+
'<button id="mailRefresh" class="btn ghost">' + _t('mail_refresh') + '</button>' +
|
|
2652
|
+
'<button id="mailCompose" class="btn ghost">' + _t('mail_compose') + '</button>' +
|
|
2653
|
+
'<span id="mailMsg" class="sub" style="margin:0"></span></div>' +
|
|
2654
|
+
'<div id="mailList"></div>' +
|
|
2655
|
+
'<div id="mailRead" hidden style="margin-top:10px"></div>' +
|
|
2656
|
+
'<div id="mailWrite" hidden style="margin-top:10px">' +
|
|
2657
|
+
'<div class="form-grid" style="grid-template-columns:1fr 1fr">' +
|
|
2658
|
+
'<input id="mwTo" class="inp" placeholder="' + _t('mail_to') + '" autocomplete="off" />' +
|
|
2659
|
+
'<input id="mwSubject" class="inp" placeholder="' + _t('mail_subject') + '" autocomplete="off" />' +
|
|
2660
|
+
'</div>' +
|
|
2661
|
+
'<textarea id="mwBody" class="inp" rows="6" placeholder="' + _t('mail_body') + '" style="margin-top:6px;width:100%"></textarea>' +
|
|
2662
|
+
'<div style="display:flex;gap:8px;margin-top:6px">' +
|
|
2663
|
+
'<button id="mwSend" class="btn">' + _t('mail_send') + '</button>' +
|
|
2664
|
+
'<button id="mwCancel" class="btn ghost">' + _t('btn_close') + '</button>' +
|
|
2665
|
+
'</div></div>';
|
|
2644
2666
|
|
|
2645
2667
|
try {
|
|
2646
2668
|
const em = await beast.getEmail();
|
|
@@ -2672,6 +2694,86 @@ async function renderEmailPane() {
|
|
|
2672
2694
|
if (pass && pass !== PASS_MASK) { savedPass = pass; mailPass.value = PASS_MASK; passChanged = false; }
|
|
2673
2695
|
toast(_t('mail_saved'));
|
|
2674
2696
|
});
|
|
2697
|
+
|
|
2698
|
+
/* ---- gelen kutusu + okuma + gönderme ---- */
|
|
2699
|
+
const mailMsg = $('#mailMsg');
|
|
2700
|
+
const mailList = $('#mailList');
|
|
2701
|
+
const mailRead = $('#mailRead');
|
|
2702
|
+
const mailWrite = $('#mailWrite');
|
|
2703
|
+
const openWrite = (to, subject) => {
|
|
2704
|
+
if (!mailWrite) return;
|
|
2705
|
+
mailWrite.hidden = false;
|
|
2706
|
+
$('#mwTo').value = to || '';
|
|
2707
|
+
$('#mwSubject').value = subject || '';
|
|
2708
|
+
$('#mwBody').value = '';
|
|
2709
|
+
$('#mwBody').focus();
|
|
2710
|
+
};
|
|
2711
|
+
const loadInbox = async () => {
|
|
2712
|
+
if (!mailList) return;
|
|
2713
|
+
if (mailMsg) mailMsg.textContent = '…';
|
|
2714
|
+
if (mailRead) mailRead.hidden = true;
|
|
2715
|
+
const r = await beast.emailList({ limit: 15 }).catch((e) => ({ ok: false, error: String((e && e.message) || e) }));
|
|
2716
|
+
if (mailMsg) mailMsg.textContent = '';
|
|
2717
|
+
if (!r || r.ok === false) {
|
|
2718
|
+
mailList.innerHTML = '<div class="sub">' + escapeHtml((r && r.error) || '?') + '</div>';
|
|
2719
|
+
return;
|
|
2720
|
+
}
|
|
2721
|
+
const msgs = r.messages || [];
|
|
2722
|
+
mailList.innerHTML = msgs.length
|
|
2723
|
+
? msgs
|
|
2724
|
+
.map(
|
|
2725
|
+
(m) =>
|
|
2726
|
+
'<div class="cj-job" data-uid="' + escapeHtml(String(m.uid)) + '" style="cursor:pointer">' +
|
|
2727
|
+
'<div class="cj-info"><div class="cj-name">' + escapeHtml(m.subject || '(konu yok)') + '</div>' +
|
|
2728
|
+
'<div class="cj-meta">' + escapeHtml(m.from || '') + ' · ' + escapeHtml(fmtWhen(m.date)) + '</div></div></div>'
|
|
2729
|
+
)
|
|
2730
|
+
.join('')
|
|
2731
|
+
: '<div class="sub">' + _t('mail_empty') + '</div>';
|
|
2732
|
+
mailList.querySelectorAll('[data-uid]').forEach((row) =>
|
|
2733
|
+
row.addEventListener('click', async () => {
|
|
2734
|
+
const uid = Number(row.dataset.uid);
|
|
2735
|
+
const subjectEl = row.querySelector('.cj-name');
|
|
2736
|
+
if (mailRead) {
|
|
2737
|
+
mailRead.hidden = false;
|
|
2738
|
+
mailRead.innerHTML = '<div class="sub">…</div>';
|
|
2739
|
+
}
|
|
2740
|
+
const rr = await beast.emailRead(uid).catch(() => null);
|
|
2741
|
+
if (!mailRead) return;
|
|
2742
|
+
if (rr && rr.ok) {
|
|
2743
|
+
mailRead.innerHTML =
|
|
2744
|
+
'<div class="sub" style="white-space:pre-wrap;max-height:220px;overflow:auto">' +
|
|
2745
|
+
escapeHtml(rr.content || '') +
|
|
2746
|
+
'</div><button id="mailReply" class="btn ghost" style="margin-top:6px">' + _t('mail_reply') + '</button>';
|
|
2747
|
+
const rp = $('#mailReply');
|
|
2748
|
+
if (rp)
|
|
2749
|
+
rp.addEventListener('click', () =>
|
|
2750
|
+
openWrite('', 'Re: ' + (subjectEl ? subjectEl.textContent : ''))
|
|
2751
|
+
);
|
|
2752
|
+
} else {
|
|
2753
|
+
mailRead.innerHTML = '<div class="sub">' + escapeHtml((rr && rr.error) || _t('mail_read_fail')) + '</div>';
|
|
2754
|
+
}
|
|
2755
|
+
})
|
|
2756
|
+
);
|
|
2757
|
+
};
|
|
2758
|
+
if ($('#mailRefresh')) $('#mailRefresh').addEventListener('click', loadInbox);
|
|
2759
|
+
if ($('#mailCompose')) $('#mailCompose').addEventListener('click', () => openWrite('', ''));
|
|
2760
|
+
if ($('#mwCancel')) $('#mwCancel').addEventListener('click', () => { if (mailWrite) mailWrite.hidden = true; });
|
|
2761
|
+
if ($('#mwSend')) $('#mwSend').addEventListener('click', async () => {
|
|
2762
|
+
const to = $('#mwTo').value.trim();
|
|
2763
|
+
const subject = $('#mwSubject').value.trim();
|
|
2764
|
+
const body = $('#mwBody').value;
|
|
2765
|
+
if (!to) { toast(_t('mail_need_to')); return; }
|
|
2766
|
+
const r = await beast.emailSend({ to, subject, body }).catch((e) => ({ ok: false, error: String((e && e.message) || e) }));
|
|
2767
|
+
if (r && r.ok) {
|
|
2768
|
+
toast(_t('mail_sent'));
|
|
2769
|
+
if (mailWrite) mailWrite.hidden = true;
|
|
2770
|
+
loadInbox();
|
|
2771
|
+
} else {
|
|
2772
|
+
toast((r && r.error) || _t('mail_send_fail'));
|
|
2773
|
+
}
|
|
2774
|
+
});
|
|
2775
|
+
/* ayar kayıtlıysa ve sekme GÖRÜNÜRse gelen kutusunu yükle (boşuna IMAP bağlantısı yok) */
|
|
2776
|
+
if (savedPass && $('#mailUser').value.trim() && !pane.hidden) loadInbox();
|
|
2675
2777
|
}
|
|
2676
2778
|
|
|
2677
2779
|
/* ---------------- integrations (WhatsApp) ---------------- */
|
|
@@ -5572,7 +5674,15 @@ function renderAgentsPane() {
|
|
|
5572
5674
|
/* ---------------- events from engine ---------------- */
|
|
5573
5675
|
|
|
5574
5676
|
function onEvent(ev) {
|
|
5575
|
-
|
|
5677
|
+
if (ev.type === 'notify-click') {
|
|
5678
|
+
/* toast tıklandı: ilgili panele atla */
|
|
5679
|
+
if (ev.target === 'watchers') openWatchModal();
|
|
5680
|
+
else if (ev.target === 'cron') openSettings().then(() => switchTab('cron')).catch(() => {});
|
|
5681
|
+
else if (ev.target === 'agents') { toggleRail(true); refreshAgentsPane(); }
|
|
5682
|
+
else openSettings().catch(() => {});
|
|
5683
|
+
return;
|
|
5684
|
+
}
|
|
5685
|
+
if (ev.type === 'sessions') { refreshSessions(); return; }
|
|
5576
5686
|
if (ev.type === 'approval') {
|
|
5577
5687
|
/* Beast Studio oturumunun onayı: panelde ipucu + kart sohbete düşer */
|
|
5578
5688
|
if (stSessionId && ev.sessionId === stSessionId) {
|
|
@@ -6333,6 +6443,13 @@ async function openWatchLogModal(id) {
|
|
|
6333
6443
|
}
|
|
6334
6444
|
|
|
6335
6445
|
let lastCronKey = '';
|
|
6446
|
+
/* Cron DÜZENLEME: satıra tıkla → form dolar, buton "Güncelle"ye döner */
|
|
6447
|
+
let editingCronId = '';
|
|
6448
|
+
function resetCronEdit() {
|
|
6449
|
+
editingCronId = '';
|
|
6450
|
+
if (els.cronAddBtn) els.cronAddBtn.textContent = _t('cron_add');
|
|
6451
|
+
if (els.cronCancel) els.cronCancel.hidden = true;
|
|
6452
|
+
}
|
|
6336
6453
|
async function renderCronModal(force) {
|
|
6337
6454
|
let jobs = [];
|
|
6338
6455
|
try { jobs = (await beast.cronList()) || []; } catch {}
|
|
@@ -6755,18 +6872,116 @@ function renderCronList(jobs) {
|
|
|
6755
6872
|
btns.appendChild(mkBtn(j.enabled ? '❚❚' : '▶', j.enabled ? _t('cr_pause') : _t('cr_start'), async () => { await beast.cronToggle(j.id); refreshCron(); }));
|
|
6756
6873
|
btns.appendChild(mkBtn('×', _t('cr_del'), async () => { await beast.cronDelete(j.id); refreshCron(); }));
|
|
6757
6874
|
row.appendChild(btns);
|
|
6758
|
-
|
|
6759
|
-
|
|
6875
|
+
const loadEdit = () => {
|
|
6876
|
+
editingCronId = j.id;
|
|
6877
|
+
els.cronName.value = j.name || '';
|
|
6760
6878
|
els.cronPreset.value = '__custom';
|
|
6761
|
-
els.cronSchedule.value = j.schedule;
|
|
6762
|
-
els.cronPrompt.value = j.prompt;
|
|
6763
|
-
|
|
6879
|
+
els.cronSchedule.value = j.schedule || '';
|
|
6880
|
+
els.cronPrompt.value = j.prompt || '';
|
|
6881
|
+
if (els.cronAddBtn) els.cronAddBtn.textContent = _t('cr_update');
|
|
6882
|
+
if (els.cronCancel) els.cronCancel.hidden = false;
|
|
6883
|
+
els.cronName.focus();
|
|
6884
|
+
toast(_t('cr_edit_loaded'));
|
|
6885
|
+
};
|
|
6886
|
+
dot.addEventListener('click', loadEdit);
|
|
6887
|
+
info.addEventListener('click', loadEdit);
|
|
6888
|
+
dot.title = (j.enabled ? _t('cr_dot_on') : _t('cr_dot_off')) + ' — ' + _t('cr_edit_hint');
|
|
6764
6889
|
els.cronList.appendChild(row);
|
|
6765
6890
|
}
|
|
6766
6891
|
}
|
|
6767
6892
|
|
|
6768
6893
|
function openCron() { refreshCron(); }
|
|
6769
6894
|
|
|
6895
|
+
/* ---------------- AJANDA: yaklaşan cron + hatırlatıcı + izleyiciler ---------------- */
|
|
6896
|
+
|
|
6897
|
+
function isReminderLike(j) {
|
|
6898
|
+
if (!j) return false;
|
|
6899
|
+
if (j.kind === 'reminder') return true;
|
|
6900
|
+
const n = String(j.name || '');
|
|
6901
|
+
const p = String(j.prompt || '');
|
|
6902
|
+
return (
|
|
6903
|
+
/^Hatırlatma:/.test(n) ||
|
|
6904
|
+
/^Tekrarlı hatırlatma:/.test(n) ||
|
|
6905
|
+
p.startsWith('[HATIRLATMA ZAMANI]') ||
|
|
6906
|
+
p.startsWith('[TEKRARLI HATIRLATMA]')
|
|
6907
|
+
);
|
|
6908
|
+
}
|
|
6909
|
+
|
|
6910
|
+
function relTime(ms) {
|
|
6911
|
+
const diff = ms - Date.now();
|
|
6912
|
+
const abs = Math.abs(diff);
|
|
6913
|
+
const dk = Math.round(abs / 60000);
|
|
6914
|
+
const saat = Math.floor(dk / 60);
|
|
6915
|
+
const gun = Math.floor(saat / 24);
|
|
6916
|
+
let label;
|
|
6917
|
+
if (dk < 1) return _t('aj_now');
|
|
6918
|
+
else if (dk < 60) label = dk + ' dk';
|
|
6919
|
+
else if (saat < 24) label = saat + ' sa';
|
|
6920
|
+
else label = gun + ' gün';
|
|
6921
|
+
return diff >= 0 ? label + ' ' + _t('aj_later') : label + ' ' + _t('aj_ago');
|
|
6922
|
+
}
|
|
6923
|
+
|
|
6924
|
+
async function renderAgendaPane() {
|
|
6925
|
+
const pane = $('#tab-agenda');
|
|
6926
|
+
if (!pane) return;
|
|
6927
|
+
let jobs = [];
|
|
6928
|
+
let ws = [];
|
|
6929
|
+
try { jobs = (await beast.cronList()) || []; } catch {}
|
|
6930
|
+
try { ws = (await beast.watchersList()) || []; } catch {}
|
|
6931
|
+
const items = [];
|
|
6932
|
+
for (const j of jobs) {
|
|
6933
|
+
if (!j.enabled) continue;
|
|
6934
|
+
const t = j.nextRunAt ? new Date(j.nextRunAt).getTime() : 0;
|
|
6935
|
+
if (!t) continue;
|
|
6936
|
+
items.push({ type: isReminderLike(j) ? 'rem' : 'cron', name: j.name || j.id, at: t, meta: j.schedule, id: j.id });
|
|
6937
|
+
}
|
|
6938
|
+
for (const w of ws) {
|
|
6939
|
+
if (!w.enabled) continue;
|
|
6940
|
+
const every = w.everySec ? w.everySec * 1000 : (w.everyMin || 15) * 60000;
|
|
6941
|
+
const last = w.lastCheckAt ? new Date(w.lastCheckAt).getTime() : 0;
|
|
6942
|
+
items.push({
|
|
6943
|
+
type: 'watch',
|
|
6944
|
+
name: w.name,
|
|
6945
|
+
at: last ? last + every : Date.now(),
|
|
6946
|
+
meta: opText(w) + ' · her ' + fmtEvery(w),
|
|
6947
|
+
id: w.id,
|
|
6948
|
+
});
|
|
6949
|
+
}
|
|
6950
|
+
items.sort((a, b) => a.at - b.at);
|
|
6951
|
+
const badge = { cron: '🕐', rem: '⏰', watch: '👁' };
|
|
6952
|
+
const rows = items.length
|
|
6953
|
+
? items
|
|
6954
|
+
.map(
|
|
6955
|
+
(it) =>
|
|
6956
|
+
'<div class="cron-job ag-item" data-type="' + it.type + '" data-id="' + escapeHtml(it.id) + '" style="cursor:pointer">' +
|
|
6957
|
+
'<div class="cj-info"><div class="cj-name">' + badge[it.type] + ' ' + escapeHtml(it.name) + '</div>' +
|
|
6958
|
+
'<div class="cj-meta">' + escapeHtml(String(it.meta || '')) + ' · <b>' + escapeHtml(relTime(it.at)) + '</b> · ' + escapeHtml(fmtTime(it.at)) + '</div></div></div>'
|
|
6959
|
+
)
|
|
6960
|
+
.join('')
|
|
6961
|
+
: '<div class="cron-empty">' + _t('aj_empty') + '</div>';
|
|
6962
|
+
let notifOn = true;
|
|
6963
|
+
try { notifOn = !!(await beast.notifyGet()).toast; } catch {}
|
|
6964
|
+
pane.innerHTML =
|
|
6965
|
+
'<h2>' + _t('aj_h2') + '</h2><div class="sub">' + _t('aj_sub') + '</div>' +
|
|
6966
|
+
'<label class="lock-row" style="margin-top:8px"><input type="checkbox" id="ajNotify" ' + (notifOn ? 'checked' : '') + '/><span>' + _t('aj_notify') + '</span></label>' +
|
|
6967
|
+
'<div style="margin-top:10px">' + rows + '</div>';
|
|
6968
|
+
const nj = $('#ajNotify');
|
|
6969
|
+
if (nj) nj.addEventListener('change', async (e) => {
|
|
6970
|
+
await beast.notifySet(e.target.checked).catch(() => {});
|
|
6971
|
+
toast(e.target.checked ? _t('aj_notify_on') : _t('aj_notify_off'));
|
|
6972
|
+
});
|
|
6973
|
+
pane.querySelectorAll('.ag-item').forEach((row) => {
|
|
6974
|
+
row.addEventListener('click', () => {
|
|
6975
|
+
if (row.dataset.type === 'watch') {
|
|
6976
|
+
closeSettings();
|
|
6977
|
+
openWatchModal();
|
|
6978
|
+
} else {
|
|
6979
|
+
switchTab('cron');
|
|
6980
|
+
}
|
|
6981
|
+
});
|
|
6982
|
+
});
|
|
6983
|
+
}
|
|
6984
|
+
|
|
6770
6985
|
/* ---------------- boot ---------------- */
|
|
6771
6986
|
|
|
6772
6987
|
async function init() {
|
|
@@ -7161,6 +7376,59 @@ async function init() {
|
|
|
7161
7376
|
if (els.watchLogOverlay) els.watchLogOverlay.addEventListener('click', (e) => {
|
|
7162
7377
|
if (e.target === els.watchLogOverlay) closeWatchLogModal();
|
|
7163
7378
|
});
|
|
7379
|
+
|
|
7380
|
+
/* watcher EKLEME formu: tür seçimine göre alanlar açılır/kapanır */
|
|
7381
|
+
const wKindSel = $('#wAddKind');
|
|
7382
|
+
const wSyncKind = () => {
|
|
7383
|
+
const k = wKindSel ? wKindSel.value : 'web';
|
|
7384
|
+
const web = $('#wAddWeb');
|
|
7385
|
+
const cond = $('#wAddCond');
|
|
7386
|
+
const logs = $('#wAddLogs');
|
|
7387
|
+
if (web) web.hidden = k !== 'web';
|
|
7388
|
+
if (cond) cond.hidden = k === 'logs';
|
|
7389
|
+
if (logs) logs.hidden = k !== 'logs';
|
|
7390
|
+
};
|
|
7391
|
+
if (wKindSel) {
|
|
7392
|
+
wKindSel.addEventListener('change', wSyncKind);
|
|
7393
|
+
wSyncKind();
|
|
7394
|
+
}
|
|
7395
|
+
const wAddBtn = $('#wAddBtn');
|
|
7396
|
+
if (wAddBtn) {
|
|
7397
|
+
wAddBtn.addEventListener('click', async () => {
|
|
7398
|
+
const kind = wKindSel ? wKindSel.value : 'web';
|
|
7399
|
+
const input = {
|
|
7400
|
+
name: $('#wAddName').value.trim(),
|
|
7401
|
+
kind,
|
|
7402
|
+
everyMin: Number($('#wAddEvery').value) || 15,
|
|
7403
|
+
};
|
|
7404
|
+
if (kind === 'web') {
|
|
7405
|
+
input.url = $('#wAddUrl').value.trim();
|
|
7406
|
+
input.path = $('#wAddPath').value.trim();
|
|
7407
|
+
}
|
|
7408
|
+
if (kind !== 'logs') {
|
|
7409
|
+
input.op = $('#wAddOp').value;
|
|
7410
|
+
const v = $('#wAddValue').value.trim();
|
|
7411
|
+
input.value = input.op === 'changed' || v === '' ? null : (Number.isNaN(Number(v)) ? v : Number(v));
|
|
7412
|
+
} else {
|
|
7413
|
+
input.level = $('#wAddLevel').value;
|
|
7414
|
+
input.windowMin = Number($('#wAddWindow').value) || 10;
|
|
7415
|
+
input.re = $('#wAddRe').value.trim();
|
|
7416
|
+
input.op = 'gt';
|
|
7417
|
+
input.value = 0;
|
|
7418
|
+
}
|
|
7419
|
+
const r = await beast.watchersAdd(input).catch((e) => ({ ok: false, error: String((e && e.message) || e) }));
|
|
7420
|
+
if (!r || r.ok === false) { toast((r && r.error) || 'İzleyici eklenemedi'); return; }
|
|
7421
|
+
for (const id of ['#wAddName', '#wAddUrl', '#wAddPath', '#wAddValue', '#wAddRe']) {
|
|
7422
|
+
const el = $(id);
|
|
7423
|
+
if (el) el.value = '';
|
|
7424
|
+
}
|
|
7425
|
+
lastWatchKey = '';
|
|
7426
|
+
lastWatchPaneKey = '';
|
|
7427
|
+
await renderWatchersModal(true);
|
|
7428
|
+
await renderWatchersPane(true);
|
|
7429
|
+
toast(_t('w_added'));
|
|
7430
|
+
});
|
|
7431
|
+
}
|
|
7164
7432
|
if (els.cronOverlay) els.cronOverlay.addEventListener('click', (e) => {
|
|
7165
7433
|
if (e.target === els.cronOverlay) closeCronModal();
|
|
7166
7434
|
});
|
|
@@ -7173,12 +7441,26 @@ async function init() {
|
|
|
7173
7441
|
const schedule = els.cronSchedule.value.trim();
|
|
7174
7442
|
const prompt = els.cronPrompt.value.trim();
|
|
7175
7443
|
if (!schedule || !prompt) { toast('Cron ifadesi ve görev metni gerekli'); return; }
|
|
7176
|
-
|
|
7177
|
-
|
|
7444
|
+
if (editingCronId) {
|
|
7445
|
+
const r = await beast.cronUpdate(editingCronId, { name, schedule, prompt });
|
|
7446
|
+
if (!r || r.ok === false) { toast((r && r.error) || 'Güncellenemedi'); return; }
|
|
7447
|
+
toast(_t('cr_updated'));
|
|
7448
|
+
} else {
|
|
7449
|
+
const r = await beast.cronAdd({ name, schedule, prompt });
|
|
7450
|
+
if (!r.ok) { toast(r.error || 'Eklenemedi'); return; }
|
|
7451
|
+
toast(_t('cr_added'));
|
|
7452
|
+
}
|
|
7178
7453
|
els.cronName.value = ''; els.cronSchedule.value = ''; els.cronPrompt.value = '';
|
|
7179
|
-
|
|
7454
|
+
resetCronEdit();
|
|
7180
7455
|
refreshCron();
|
|
7181
7456
|
});
|
|
7457
|
+
if (els.cronCancel) {
|
|
7458
|
+
els.cronCancel.addEventListener('click', () => {
|
|
7459
|
+
els.cronName.value = ''; els.cronSchedule.value = ''; els.cronPrompt.value = '';
|
|
7460
|
+
resetCronEdit();
|
|
7461
|
+
toast(_t('cr_edit_cancelled'));
|
|
7462
|
+
});
|
|
7463
|
+
}
|
|
7182
7464
|
document.addEventListener('mousemove', (e) => {
|
|
7183
7465
|
if (!rz) return;
|
|
7184
7466
|
const w = Math.max(300, Math.min(rz.sw - (e.clientX - rz.sx), window.innerWidth - 340));
|
package/src/renderer/style.css
CHANGED
|
@@ -1484,6 +1484,19 @@ body.browser-open .mini-overlay { right: var(--bw, 480px); }
|
|
|
1484
1484
|
font-size: 12px;
|
|
1485
1485
|
padding: 4px 6px;
|
|
1486
1486
|
}
|
|
1487
|
+
/* ---------- İzleyici EKLEME formu ---------- */
|
|
1488
|
+
#wAddBox {
|
|
1489
|
+
display: flex; flex-direction: column; gap: 6px;
|
|
1490
|
+
background: var(--panel); border: 1px solid var(--border);
|
|
1491
|
+
border-radius: 9px; padding: 8px; margin-bottom: 10px;
|
|
1492
|
+
}
|
|
1493
|
+
.mini-add-row { display: flex; gap: 6px; align-items: center; }
|
|
1494
|
+
.mini-add-row .inp { flex: 1; min-width: 0; margin: 0; padding: 5px 8px; font-size: 12px; }
|
|
1495
|
+
#wAddBtn {
|
|
1496
|
+
flex: none; background: var(--accent); color: #fff; border: none;
|
|
1497
|
+
border-radius: 7px; padding: 5px 11px; font-size: 14px; cursor: pointer;
|
|
1498
|
+
}
|
|
1499
|
+
#wAddBtn:hover { filter: brightness(1.1); }
|
|
1487
1500
|
.wl-row {
|
|
1488
1501
|
display: flex; align-items: baseline; gap: 7px;
|
|
1489
1502
|
background: var(--panel); border: 1px solid var(--border);
|