beast-agent 2.19.1 → 2.21.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/customtools.js +242 -0
- package/src/agent/engine.js +47 -12
- package/src/agent/skills.js +83 -1
- package/src/main.js +47 -6
- package/src/preload.js +5 -0
- package/src/renderer/index.html +56 -2
- package/src/renderer/renderer.js +340 -42
- package/src/renderer/style.css +285 -4
package/src/renderer/index.html
CHANGED
|
@@ -22,6 +22,16 @@
|
|
|
22
22
|
</div>
|
|
23
23
|
<div id="watchPaneList"></div>
|
|
24
24
|
</div>
|
|
25
|
+
<div id="toolBox">
|
|
26
|
+
<div id="toolBoxHead">
|
|
27
|
+
<span id="toolBoxTitle">TOOLLAR</span>
|
|
28
|
+
<span class="bot-bar-btns">
|
|
29
|
+
<button id="toolFolderBtn" title="Toollar klasörünü aç (%APPDATA%\beast\tools)"><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="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7z"/></svg></button>
|
|
30
|
+
<button id="toolAdd" title="Yeni tool yaz">+</button>
|
|
31
|
+
</span>
|
|
32
|
+
</div>
|
|
33
|
+
<div id="toolList"></div>
|
|
34
|
+
</div>
|
|
25
35
|
<div id="botBar">
|
|
26
36
|
<div id="botBarHead">
|
|
27
37
|
<span id="botBarTitle" data-i18n="bot_head">BOTLAR</span>
|
|
@@ -363,10 +373,54 @@
|
|
|
363
373
|
</aside>
|
|
364
374
|
</div>
|
|
365
375
|
|
|
376
|
+
<div id="dmOverlay" hidden>
|
|
377
|
+
<div id="dmDialog">
|
|
378
|
+
<div id="dmDialogHead">
|
|
379
|
+
<span id="dmDialogTitle">AJAN DM — OTURUMLAR</span>
|
|
380
|
+
<span class="bot-bar-btns">
|
|
381
|
+
<button id="dmColumnBtn" title="Yan sütunda canlı akış olarak da göster">▤︎</button>
|
|
382
|
+
<button id="dmModalClear" title="Tüm DM geçmişini sil"><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="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>
|
|
383
|
+
<button id="dmModalClose" title="Kapat">✕︎</button>
|
|
384
|
+
</span>
|
|
385
|
+
</div>
|
|
386
|
+
<div id="dmDialogList"></div>
|
|
387
|
+
<div class="dm-hint">Thread = ajan çifti + konu · gelen/giden hepsi kronolojik</div>
|
|
388
|
+
</div>
|
|
389
|
+
</div>
|
|
390
|
+
|
|
391
|
+
<div id="toolOverlay" hidden>
|
|
392
|
+
<div id="toolDialog">
|
|
393
|
+
<div id="toolDialogHead">
|
|
394
|
+
<span id="toolDialogTitle">YENİ TOOL</span>
|
|
395
|
+
<button id="toolClose" title="Kapat">✕︎</button>
|
|
396
|
+
</div>
|
|
397
|
+
<div class="tool-form">
|
|
398
|
+
<label>Tool adı (ajan tool__<ad> olarak çağırır)</label>
|
|
399
|
+
<input id="toolName" placeholder="örn: gold_emir" spellcheck="false" autocomplete="off" />
|
|
400
|
+
<label>Açıklama — ajan bu metni görüp ne zaman çağıracağını anlar</label>
|
|
401
|
+
<input id="toolDesc" placeholder="örn: GOLD için özel emir açar (side, lot, sl, tp)" spellcheck="false" autocomplete="off" />
|
|
402
|
+
<label>Parametre şeması (JSON)</label>
|
|
403
|
+
<textarea id="toolParams" rows="6" spellcheck="false" placeholder='{"type":"object","properties":{"side":{"type":"string"},"lot":{"type":"number"}},"required":["side"]}'></textarea>
|
|
404
|
+
<label>run.js kodu — stdin: JSON args · stdout: JSON sonuç (console.log)</label>
|
|
405
|
+
<textarea id="toolCode" rows="12" spellcheck="false" placeholder="const args = JSON.parse(...); console.log(JSON.stringify({ ok: true }));"></textarea>
|
|
406
|
+
<div id="toolFormErr" class="sub" style="color:var(--err)" hidden></div>
|
|
407
|
+
</div>
|
|
408
|
+
<div id="toolTestRow">
|
|
409
|
+
<input id="toolTestArgs" placeholder='deneme argümanları (JSON): {"mesaj":"merhaba"}' spellcheck="false" autocomplete="off" />
|
|
410
|
+
<button id="toolTestBtn">▶︎ Çalıştır</button>
|
|
411
|
+
</div>
|
|
412
|
+
<pre id="toolTestOut" hidden></pre>
|
|
413
|
+
<div id="toolDialogBtns">
|
|
414
|
+
<button id="toolDeleteBtn" class="tool-danger" hidden>Sil</button>
|
|
415
|
+
<span class="file-spacer"></span>
|
|
416
|
+
<button id="toolSaveBtn" class="tool-primary">Kaydet</button>
|
|
417
|
+
</div>
|
|
418
|
+
</div>
|
|
419
|
+
</div>
|
|
420
|
+
|
|
366
421
|
<div id="settingsOverlay" hidden>
|
|
367
422
|
<div id="settingsDialog">
|
|
368
|
-
<aside id="setTabs">
|
|
369
|
-
<div class="set-tabs-title" data-i18n="set_title">AYARLAR</div>
|
|
423
|
+
<aside id="setTabs"> <div class="set-tabs-title" data-i18n="set_title">AYARLAR</div>
|
|
370
424
|
<nav class="set-tabs-list">
|
|
371
425
|
<button class="tab active" data-tab="lang" data-i18n="tab_lang">Dil</button>
|
|
372
426
|
<button class="tab" data-tab="provider" data-i18n="tab_provider">Provider</button>
|
package/src/renderer/renderer.js
CHANGED
|
@@ -45,9 +45,30 @@ const els = {
|
|
|
45
45
|
dmBtn: $('#dmBtn'),
|
|
46
46
|
dmRailList: $('#dmRailList'),
|
|
47
47
|
dmClear: $('#dmClear'),
|
|
48
|
+
dmOverlay: $('#dmOverlay'),
|
|
49
|
+
dmDialogList: $('#dmDialogList'),
|
|
50
|
+
dmModalClose: $('#dmModalClose'),
|
|
51
|
+
dmModalClear: $('#dmModalClear'),
|
|
52
|
+
dmColumnBtn: $('#dmColumnBtn'),
|
|
48
53
|
watchBtn: $('#watchBtn'),
|
|
49
54
|
watchPaneList: $('#watchPaneList'),
|
|
50
55
|
watchPaneOpen: $('#watchPaneOpen'),
|
|
56
|
+
toolBoxAdd: $('#toolAdd'),
|
|
57
|
+
toolList: $('#toolList'),
|
|
58
|
+
toolFolderBtn: $('#toolFolderBtn'),
|
|
59
|
+
toolOverlay: $('#toolOverlay'),
|
|
60
|
+
toolClose: $('#toolClose'),
|
|
61
|
+
toolDialogTitle: $('#toolDialogTitle'),
|
|
62
|
+
toolName: $('#toolName'),
|
|
63
|
+
toolDesc: $('#toolDesc'),
|
|
64
|
+
toolParams: $('#toolParams'),
|
|
65
|
+
toolCode: $('#toolCode'),
|
|
66
|
+
toolFormErr: $('#toolFormErr'),
|
|
67
|
+
toolTestArgs: $('#toolTestArgs'),
|
|
68
|
+
toolTestBtn: $('#toolTestBtn'),
|
|
69
|
+
toolTestOut: $('#toolTestOut'),
|
|
70
|
+
toolSaveBtn: $('#toolSaveBtn'),
|
|
71
|
+
toolDeleteBtn: $('#toolDeleteBtn'),
|
|
51
72
|
watchPaneLog: $('#watchPaneLog'),
|
|
52
73
|
cronBtn: $('#cronBtn'),
|
|
53
74
|
watchOverlay: $('#watchOverlay'),
|
|
@@ -5003,25 +5024,41 @@ async function loadRailChat(id) {
|
|
|
5003
5024
|
}
|
|
5004
5025
|
}
|
|
5005
5026
|
|
|
5006
|
-
/* ---------------- AJAN DM
|
|
5007
|
-
|
|
5008
|
-
|
|
5027
|
+
/* ---------------- AJAN DM (ajanlar arası konuşma) ----------------
|
|
5028
|
+
İki görünüm: ✉ modal (oturum listesi) + yan sütun (canlı akış).
|
|
5029
|
+
Thread anahtarı = ajan çifti + KONU — aynı konudaki mesajlar tek
|
|
5030
|
+
oturumda toplanır, gelen/giden hepsi kronolojik görünür. */
|
|
5009
5031
|
|
|
5010
5032
|
const dmState = {
|
|
5011
|
-
dms: [], // { at, from, fromTitle, to, toTitle, text }
|
|
5012
|
-
open: new Set(), // açık thread key'leri
|
|
5033
|
+
dms: [], // { at, from, fromTitle, to, toTitle, topic, text }
|
|
5034
|
+
open: new Set(), // açık thread key'leri (modal + sütun ortak)
|
|
5013
5035
|
};
|
|
5014
5036
|
|
|
5015
|
-
function
|
|
5037
|
+
function dmThreadOf(dm) {
|
|
5016
5038
|
const a = String(dm.from || '');
|
|
5017
5039
|
const b = String(dm.to || '');
|
|
5018
|
-
|
|
5040
|
+
const pair = a < b ? a + '|' + b : b + '|' + a;
|
|
5041
|
+
return pair + '|' + String(dm.topic || '(genel)').toLowerCase();
|
|
5019
5042
|
}
|
|
5020
5043
|
|
|
5021
|
-
function
|
|
5044
|
+
function dmThreadTitle(dm) {
|
|
5022
5045
|
const a = String(dm.fromTitle || 'Ajan');
|
|
5023
5046
|
const b = String(dm.toTitle || 'Ajan');
|
|
5024
|
-
|
|
5047
|
+
const pair = a < b ? a + ' ↔ ' + b : b + ' ↔ ' + a;
|
|
5048
|
+
const topic = String(dm.topic || '(genel)');
|
|
5049
|
+
return topic === '(genel)' ? pair : pair + ' · ' + topic;
|
|
5050
|
+
}
|
|
5051
|
+
|
|
5052
|
+
function dmThreads() {
|
|
5053
|
+
const threads = new Map();
|
|
5054
|
+
for (const dm of dmState.dms) {
|
|
5055
|
+
const key = dmThreadOf(dm);
|
|
5056
|
+
if (!threads.has(key)) threads.set(key, []);
|
|
5057
|
+
threads.get(key).push(dm);
|
|
5058
|
+
}
|
|
5059
|
+
return [...threads.entries()].sort(
|
|
5060
|
+
(x, y) => new Date(y[1][y[1].length - 1].at) - new Date(x[1][x[1].length - 1].at)
|
|
5061
|
+
);
|
|
5025
5062
|
}
|
|
5026
5063
|
|
|
5027
5064
|
function dmTime(iso) {
|
|
@@ -5030,6 +5067,15 @@ function dmTime(iso) {
|
|
|
5030
5067
|
return d.toLocaleTimeString('tr-TR', { hour: '2-digit', minute: '2-digit' });
|
|
5031
5068
|
}
|
|
5032
5069
|
|
|
5070
|
+
function dmMsgHtml(m) {
|
|
5071
|
+
return (
|
|
5072
|
+
`<div class="dmt-msg"><span class="dm-who">${escapeHtml(String(m.fromTitle || 'Ajan'))} → ${escapeHtml(String(m.toTitle || 'Ajan'))}</span>` +
|
|
5073
|
+
`${escapeHtml(String(m.text || ''))}<span class="dm-at">${dmTime(m.at)}</span></div>`
|
|
5074
|
+
);
|
|
5075
|
+
}
|
|
5076
|
+
|
|
5077
|
+
/* --- yan sütun --- */
|
|
5078
|
+
|
|
5033
5079
|
function renderDmRail() {
|
|
5034
5080
|
const list = els.dmRailList;
|
|
5035
5081
|
if (!list) return;
|
|
@@ -5037,37 +5083,19 @@ function renderDmRail() {
|
|
|
5037
5083
|
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>';
|
|
5038
5084
|
return;
|
|
5039
5085
|
}
|
|
5040
|
-
/* çiftlere grupla (kronolojik) — en yeni thread üstte */
|
|
5041
|
-
const threads = new Map();
|
|
5042
|
-
for (const dm of dmState.dms) {
|
|
5043
|
-
const key = dmPairOf(dm);
|
|
5044
|
-
if (!threads.has(key)) threads.set(key, []);
|
|
5045
|
-
threads.get(key).push(dm);
|
|
5046
|
-
}
|
|
5047
|
-
const rows = [...threads.entries()].sort(
|
|
5048
|
-
(x, y) => new Date(y[1][y[1].length - 1].at) - new Date(x[1][x[1].length - 1].at)
|
|
5049
|
-
);
|
|
5050
5086
|
list.innerHTML = '';
|
|
5051
|
-
for (const [key, msgs] of
|
|
5087
|
+
for (const [key, msgs] of dmThreads()) {
|
|
5052
5088
|
const open = dmState.open.has(key);
|
|
5053
5089
|
const last = msgs[msgs.length - 1];
|
|
5054
5090
|
const el = document.createElement('div');
|
|
5055
5091
|
el.className = 'dmt' + (open ? ' open' : '');
|
|
5056
5092
|
el.innerHTML =
|
|
5057
5093
|
'<div class="dmt-head">' +
|
|
5058
|
-
`<span class="dmt-title">${escapeHtml(
|
|
5094
|
+
`<span class="dmt-title">${escapeHtml(dmThreadTitle(last))}</span>` +
|
|
5059
5095
|
`<span class="dmt-count">${msgs.length}</span>` +
|
|
5060
5096
|
'</div>' +
|
|
5061
5097
|
`<div class="dmt-last">${escapeHtml(String(last.text || '').replace(/\s+/g, ' ').slice(0, 90))} · ${dmTime(last.at)}</div>` +
|
|
5062
|
-
'<div class="dmt-msgs">' +
|
|
5063
|
-
msgs
|
|
5064
|
-
.map(
|
|
5065
|
-
(m) =>
|
|
5066
|
-
`<div class="dmt-msg"><span class="dm-who">${escapeHtml(String(m.fromTitle || 'Ajan'))} → ${escapeHtml(String(m.toTitle || 'Ajan'))}</span>` +
|
|
5067
|
-
`${escapeHtml(String(m.text || ''))}<span class="dm-at">${dmTime(m.at)}</span></div>`
|
|
5068
|
-
)
|
|
5069
|
-
.join('') +
|
|
5070
|
-
'</div>';
|
|
5098
|
+
'<div class="dmt-msgs">' + msgs.map(dmMsgHtml).join('') + '</div>';
|
|
5071
5099
|
el.addEventListener('click', () => {
|
|
5072
5100
|
if (dmState.open.has(key)) dmState.open.delete(key);
|
|
5073
5101
|
else dmState.open.add(key);
|
|
@@ -5095,18 +5123,263 @@ function toggleDmRail(hide) {
|
|
|
5095
5123
|
if (!hide) refreshDmRail();
|
|
5096
5124
|
}
|
|
5097
5125
|
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5126
|
+
/* --- modal (✉ butonu) --- */
|
|
5127
|
+
|
|
5128
|
+
function renderDmModal() {
|
|
5129
|
+
const list = els.dmDialogList;
|
|
5130
|
+
if (!list) return;
|
|
5131
|
+
if (!dmState.dms.length) {
|
|
5132
|
+
list.innerHTML = '<div class="dm-empty">Henüz ajan DM\u2019i yok.<br>Ajanlar agent_dm aracıyla birbirine mesaj attıkça oturumlar burada birikir.</div>';
|
|
5133
|
+
return;
|
|
5134
|
+
}
|
|
5135
|
+
list.innerHTML = '';
|
|
5136
|
+
for (const [key, msgs] of dmThreads()) {
|
|
5137
|
+
const open = dmState.open.has(key);
|
|
5138
|
+
const last = msgs[msgs.length - 1];
|
|
5139
|
+
const el = document.createElement('div');
|
|
5140
|
+
el.className = 'dmt' + (open ? ' open' : '');
|
|
5141
|
+
el.innerHTML =
|
|
5142
|
+
'<div class="dmt-head">' +
|
|
5143
|
+
`<span class="dmt-title">${escapeHtml(dmThreadTitle(last))}</span>` +
|
|
5144
|
+
`<span class="dmt-count">${msgs.length}</span>` +
|
|
5145
|
+
'</div>' +
|
|
5146
|
+
`<div class="dmt-last">${escapeHtml(String(last.text || '').replace(/\s+/g, ' ').slice(0, 120))} · ${dmTime(last.at)}</div>` +
|
|
5147
|
+
'<div class="dmt-msgs">' + msgs.map(dmMsgHtml).join('') + '</div>';
|
|
5148
|
+
el.addEventListener('click', () => {
|
|
5149
|
+
if (dmState.open.has(key)) dmState.open.delete(key);
|
|
5150
|
+
else dmState.open.add(key);
|
|
5151
|
+
renderDmModal();
|
|
5152
|
+
const again = els.dmDialogList.querySelector('.dmt.open .dmt-msgs');
|
|
5153
|
+
if (again) again.scrollTop = again.scrollHeight;
|
|
5154
|
+
});
|
|
5155
|
+
list.appendChild(el);
|
|
5156
|
+
}
|
|
5157
|
+
}
|
|
5158
|
+
|
|
5159
|
+
async function openDmModal() {
|
|
5160
|
+
if (!els.dmOverlay) return;
|
|
5161
|
+
els.dmOverlay.hidden = false;
|
|
5162
|
+
await refreshDmRail(); // kayıtları tazele
|
|
5163
|
+
renderDmModal();
|
|
5164
|
+
if (els.dmBtn) els.dmBtn.classList.add('on');
|
|
5165
|
+
}
|
|
5166
|
+
|
|
5167
|
+
function closeDmModal() {
|
|
5168
|
+
if (els.dmOverlay) els.dmOverlay.hidden = true;
|
|
5169
|
+
if (els.dmBtn) els.dmBtn.classList.remove('on');
|
|
5170
|
+
}
|
|
5171
|
+
|
|
5172
|
+
async function dmClearAll() {
|
|
5173
|
+
if (!(await uiConfirm('TÜM ajan DM geçmişi silinsin mi?', 'Sil'))) return;
|
|
5174
|
+
try { await beast.agentDmsClear(); } catch {}
|
|
5175
|
+
dmState.dms = [];
|
|
5176
|
+
renderDmRail();
|
|
5177
|
+
renderDmModal();
|
|
5178
|
+
toast('Ajan DM geçmişi silindi');
|
|
5179
|
+
}
|
|
5180
|
+
|
|
5181
|
+
if (els.dmBtn) els.dmBtn.addEventListener('click', openDmModal);
|
|
5182
|
+
if (els.dmModalClose) els.dmModalClose.addEventListener('click', closeDmModal);
|
|
5183
|
+
if (els.dmModalClear) els.dmModalClear.addEventListener('click', dmClearAll);
|
|
5184
|
+
if (els.dmOverlay) {
|
|
5185
|
+
els.dmOverlay.addEventListener('click', (e) => {
|
|
5186
|
+
if (e.target === els.dmOverlay) closeDmModal();
|
|
5187
|
+
});
|
|
5188
|
+
els.dmOverlay.addEventListener('keydown', (e) => {
|
|
5189
|
+
if (e.key === 'Escape') { e.stopPropagation(); closeDmModal(); }
|
|
5101
5190
|
});
|
|
5102
5191
|
}
|
|
5103
|
-
if (els.dmClear)
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5192
|
+
if (els.dmClear) els.dmClear.addEventListener('click', dmClearAll);
|
|
5193
|
+
if (els.dmColumnBtn) {
|
|
5194
|
+
els.dmColumnBtn.addEventListener('click', () => {
|
|
5195
|
+
closeDmModal();
|
|
5196
|
+
toggleDmRail(false); // yan sütunda canlı akış
|
|
5197
|
+
});
|
|
5198
|
+
}
|
|
5199
|
+
|
|
5200
|
+
/* ---------------- TOOLS konsolu (kişisel araçlar) ----------------
|
|
5201
|
+
%APPDATA%\beast\tools\<ad>\tool.json + run.js — kullanıcı kendi araçlarını
|
|
5202
|
+
yazar; finance dahil TÜM oturumlar tool__<ad> olarak çağırır. Sol panelde
|
|
5203
|
+
buradan görüntülenir, yazılır, test edilir, silinir. */
|
|
5204
|
+
|
|
5205
|
+
const toolUi = {
|
|
5206
|
+
tools: [],
|
|
5207
|
+
editId: null,
|
|
5208
|
+
logRows: [],
|
|
5209
|
+
};
|
|
5210
|
+
|
|
5211
|
+
const TOOL_EXAMPLE_CODE =
|
|
5212
|
+
"'use strict';\n" +
|
|
5213
|
+
"// KİŞİSEL TOOL — stdin: JSON args · stdout: JSON sonuç\n" +
|
|
5214
|
+
"const fs = require('fs');\n" +
|
|
5215
|
+
"let raw = '';\n" +
|
|
5216
|
+
"try { raw = fs.readFileSync(0, 'utf8'); } catch {}\n" +
|
|
5217
|
+
"let args = {};\n" +
|
|
5218
|
+
"try { args = JSON.parse(raw || '{}'); } catch {}\n" +
|
|
5219
|
+
"// Buraya kendi işini yaz (MT5 köprüsü, özel API, hesap, sinyal…)\n" +
|
|
5220
|
+
"console.log(JSON.stringify({ ok: true, echo: args }));\n";
|
|
5221
|
+
|
|
5222
|
+
let toolRenderTimer = null;
|
|
5223
|
+
function scheduleToolRender() {
|
|
5224
|
+
if (toolRenderTimer) return;
|
|
5225
|
+
toolRenderTimer = setTimeout(() => {
|
|
5226
|
+
toolRenderTimer = null;
|
|
5227
|
+
renderToolBox();
|
|
5228
|
+
}, 500);
|
|
5229
|
+
}
|
|
5230
|
+
|
|
5231
|
+
async function renderToolBox() {
|
|
5232
|
+
const list = els.toolList;
|
|
5233
|
+
if (!list) return;
|
|
5234
|
+
try { toolUi.tools = (await beast.toolsList()) || []; } catch { toolUi.tools = []; }
|
|
5235
|
+
list.textContent = '';
|
|
5236
|
+
if (!toolUi.tools.length) {
|
|
5237
|
+
const d = document.createElement('div');
|
|
5238
|
+
d.className = 'tool-empty';
|
|
5239
|
+
d.textContent = 'Tool yok — + ile kendi aracını yaz (Finance dahil tüm oturumlarda çalışır)';
|
|
5240
|
+
list.appendChild(d);
|
|
5241
|
+
return;
|
|
5242
|
+
}
|
|
5243
|
+
for (const t of toolUi.tools) {
|
|
5244
|
+
const row = document.createElement('div');
|
|
5245
|
+
row.className = 'tool-row';
|
|
5246
|
+
const last = toolUi.logRows.filter((l) => l.toolId === t.id).slice(-1)[0];
|
|
5247
|
+
const st = last ? (last.ok ? 'ok' : 'err') : 'idle';
|
|
5248
|
+
const tip = last
|
|
5249
|
+
? 'son çalışma ' + dmTime(last.at) + (last.error ? ' · hata: ' + last.error : ' · ' + last.ms + ' ms')
|
|
5250
|
+
: 'hiç çalışmadı';
|
|
5251
|
+
row.innerHTML =
|
|
5252
|
+
'<span class="tool-dot ' + st + '" title="' + escapeHtml(tip) + '"></span>' +
|
|
5253
|
+
'<span class="tool-name" title="' + escapeHtml(t.description || '') + '">' + escapeHtml(t.name) + '</span>' +
|
|
5254
|
+
'<span class="tool-btns">' +
|
|
5255
|
+
'<button class="tb-run" title="Aç & test çalıştır">▶︎</button>' +
|
|
5256
|
+
'<button class="tb-edit" title="Düzenle">✎︎</button>' +
|
|
5257
|
+
'<button class="tb-del" title="Sil">✕︎</button>' +
|
|
5258
|
+
'</span>';
|
|
5259
|
+
row.querySelector('.tb-run').addEventListener('click', () => openToolDialog(t));
|
|
5260
|
+
row.querySelector('.tb-edit').addEventListener('click', () => openToolDialog(t));
|
|
5261
|
+
row.querySelector('.tb-del').addEventListener('click', async () => {
|
|
5262
|
+
if (!(await uiConfirm('"' + t.name + '" toolu silinsin mi? (ajanlar artık çağıramaz)', 'Sil'))) return;
|
|
5263
|
+
const r = await beast.toolDelete(t.id).catch(() => ({ ok: false }));
|
|
5264
|
+
if (r && r.ok) {
|
|
5265
|
+
toast('Tool silindi');
|
|
5266
|
+
renderToolBox();
|
|
5267
|
+
} else toast((r && r.error) || 'Silinemedi');
|
|
5268
|
+
});
|
|
5269
|
+
list.appendChild(row);
|
|
5270
|
+
}
|
|
5271
|
+
}
|
|
5272
|
+
|
|
5273
|
+
function openToolDialog(t) {
|
|
5274
|
+
if (!els.toolOverlay) return;
|
|
5275
|
+
toolUi.editId = t ? t.id : null;
|
|
5276
|
+
els.toolDialogTitle.textContent = t ? 'TOOL · ' + t.name : 'YENİ TOOL';
|
|
5277
|
+
els.toolName.value = t ? t.name : '';
|
|
5278
|
+
els.toolDesc.value = t ? t.description || '' : '';
|
|
5279
|
+
els.toolParams.value = t
|
|
5280
|
+
? JSON.stringify(t.parameters || { type: 'object', properties: {} }, null, 2)
|
|
5281
|
+
: '{\n "type": "object",\n "properties": {},\n "required": []\n}';
|
|
5282
|
+
els.toolCode.value = t ? t.code || TOOL_EXAMPLE_CODE : TOOL_EXAMPLE_CODE;
|
|
5283
|
+
els.toolTestArgs.value = t && t.parameters && Array.isArray(t.parameters.required) && t.parameters.required.length
|
|
5284
|
+
? JSON.stringify(Object.fromEntries(t.parameters.required.map((k) => [k, ''])), null, 1)
|
|
5285
|
+
: '';
|
|
5286
|
+
els.toolTestOut.hidden = true;
|
|
5287
|
+
els.toolTestOut.textContent = '';
|
|
5288
|
+
els.toolFormErr.hidden = true;
|
|
5289
|
+
els.toolDeleteBtn.hidden = !t;
|
|
5290
|
+
els.toolOverlay.hidden = false;
|
|
5291
|
+
els.toolName.focus();
|
|
5292
|
+
}
|
|
5293
|
+
|
|
5294
|
+
function closeToolDialog() {
|
|
5295
|
+
if (els.toolOverlay) els.toolOverlay.hidden = true;
|
|
5296
|
+
}
|
|
5297
|
+
|
|
5298
|
+
function toolErr(msg) {
|
|
5299
|
+
if (els.toolFormErr) {
|
|
5300
|
+
els.toolFormErr.textContent = msg;
|
|
5301
|
+
els.toolFormErr.hidden = !msg;
|
|
5302
|
+
}
|
|
5303
|
+
}
|
|
5304
|
+
|
|
5305
|
+
if (els.toolBoxAdd) els.toolBoxAdd.addEventListener('click', () => openToolDialog(null));
|
|
5306
|
+
if (els.toolFolderBtn) els.toolFolderBtn.addEventListener('click', () => beast.toolsOpenFolder());
|
|
5307
|
+
if (els.toolClose) els.toolClose.addEventListener('click', closeToolDialog);
|
|
5308
|
+
if (els.toolOverlay) {
|
|
5309
|
+
els.toolOverlay.addEventListener('click', (e) => {
|
|
5310
|
+
if (e.target === els.toolOverlay) closeToolDialog();
|
|
5311
|
+
});
|
|
5312
|
+
els.toolOverlay.addEventListener('keydown', (e) => {
|
|
5313
|
+
if (e.key === 'Escape') { e.stopPropagation(); closeToolDialog(); }
|
|
5314
|
+
});
|
|
5315
|
+
}
|
|
5316
|
+
if (els.toolSaveBtn) {
|
|
5317
|
+
els.toolSaveBtn.addEventListener('click', async () => {
|
|
5318
|
+
toolErr('');
|
|
5319
|
+
const name = String(els.toolName.value || '').trim();
|
|
5320
|
+
if (!name) return toolErr('Tool adı gerekli');
|
|
5321
|
+
let parameters = null;
|
|
5322
|
+
try {
|
|
5323
|
+
parameters = JSON.parse(els.toolParams.value || '{}');
|
|
5324
|
+
} catch {
|
|
5325
|
+
return toolErr('Parametre şeması geçerli JSON değil');
|
|
5326
|
+
}
|
|
5327
|
+
const code = String(els.toolCode.value || '').trim();
|
|
5328
|
+
if (!code) return toolErr('run.js kodu boş olamaz');
|
|
5329
|
+
const r = await beast
|
|
5330
|
+
.toolSave({ id: toolUi.editId, name, description: String(els.toolDesc.value || ''), parameters, code })
|
|
5331
|
+
.catch((e) => ({ ok: false, error: String((e && e.message) || e) }));
|
|
5332
|
+
if (r && r.ok) {
|
|
5333
|
+
closeToolDialog();
|
|
5334
|
+
toast('Tool kaydedildi — ajanlar tool__' + r.id + ' olarak çağırabilir (Finance dahil)');
|
|
5335
|
+
renderToolBox();
|
|
5336
|
+
} else {
|
|
5337
|
+
toolErr((r && r.error) || 'Kaydedilemedi');
|
|
5338
|
+
}
|
|
5339
|
+
});
|
|
5340
|
+
}
|
|
5341
|
+
if (els.toolDeleteBtn) {
|
|
5342
|
+
els.toolDeleteBtn.addEventListener('click', async () => {
|
|
5343
|
+
if (!toolUi.editId) return;
|
|
5344
|
+
const t = toolUi.tools.find((x) => x.id === toolUi.editId);
|
|
5345
|
+
if (!(await uiConfirm('"' + ((t && t.name) || toolUi.editId) + '" toolu silinsin mi?', 'Sil'))) return;
|
|
5346
|
+
const r = await beast.toolDelete(toolUi.editId).catch(() => ({ ok: false }));
|
|
5347
|
+
if (r && r.ok) {
|
|
5348
|
+
closeToolDialog();
|
|
5349
|
+
toast('Tool silindi');
|
|
5350
|
+
renderToolBox();
|
|
5351
|
+
} else toast((r && r.error) || 'Silinemedi');
|
|
5352
|
+
});
|
|
5353
|
+
}
|
|
5354
|
+
if (els.toolTestBtn) {
|
|
5355
|
+
els.toolTestBtn.addEventListener('click', async () => {
|
|
5356
|
+
toolErr('');
|
|
5357
|
+
let args = {};
|
|
5358
|
+
try {
|
|
5359
|
+
args = JSON.parse(els.toolTestArgs.value || '{}');
|
|
5360
|
+
} catch {
|
|
5361
|
+
return toolErr('Test argümanları geçerli JSON değil');
|
|
5362
|
+
}
|
|
5363
|
+
const id = toolUi.editId || String(els.toolName.value || '').trim().toLowerCase().replace(/[^a-z0-9_-]+/g, '_').replace(/^_+|_+$/g, '');
|
|
5364
|
+
if (!id) return toolErr('Önce tool adı gir');
|
|
5365
|
+
/* önce kaydet (yeni tool ilk testte de diskte olsun) */
|
|
5366
|
+
const sr = await beast
|
|
5367
|
+
.toolSave({
|
|
5368
|
+
id: toolUi.editId,
|
|
5369
|
+
name: String(els.toolName.value || id),
|
|
5370
|
+
description: String(els.toolDesc.value || ''),
|
|
5371
|
+
parameters: (() => {
|
|
5372
|
+
try { return JSON.parse(els.toolParams.value || '{}'); } catch { return null; }
|
|
5373
|
+
})() || { type: 'object', properties: {} },
|
|
5374
|
+
code: String(els.toolCode.value || ''),
|
|
5375
|
+
})
|
|
5376
|
+
.catch((e) => ({ ok: false, error: String((e && e.message) || e) }));
|
|
5377
|
+
if (!sr || !sr.ok) return toolErr((sr && sr.error) || 'Tool kaydedilemedi');
|
|
5378
|
+
els.toolTestOut.hidden = false;
|
|
5379
|
+
els.toolTestOut.textContent = 'çalışıyor…';
|
|
5380
|
+
const r = await beast.toolRun(sr.id, args).catch((e) => ({ ok: false, error: String((e && e.message) || e) }));
|
|
5381
|
+
els.toolTestOut.textContent = JSON.stringify(r, null, 2).slice(0, 8000);
|
|
5382
|
+
renderToolBox();
|
|
5110
5383
|
});
|
|
5111
5384
|
}
|
|
5112
5385
|
|
|
@@ -5254,7 +5527,7 @@ function onEvent(ev) {
|
|
|
5254
5527
|
scheduleAgentsRender();
|
|
5255
5528
|
return;
|
|
5256
5529
|
}
|
|
5257
|
-
/* AJAN DM: ajanlar arası mesaj —
|
|
5530
|
+
/* AJAN DM: ajanlar arası mesaj — açık görünümde canlı düşer (modal/sütun) */
|
|
5258
5531
|
if (ev.type === 'agent-dm') {
|
|
5259
5532
|
dmState.dms.push({
|
|
5260
5533
|
at: ev.at,
|
|
@@ -5262,12 +5535,28 @@ function onEvent(ev) {
|
|
|
5262
5535
|
fromTitle: ev.fromTitle,
|
|
5263
5536
|
to: ev.to,
|
|
5264
5537
|
toTitle: ev.toTitle,
|
|
5538
|
+
topic: ev.topic,
|
|
5265
5539
|
text: ev.text,
|
|
5266
5540
|
});
|
|
5267
5541
|
if (dmState.dms.length > 400) dmState.dms.splice(0, dmState.dms.length - 400);
|
|
5542
|
+
if (els.dmOverlay && !els.dmOverlay.hidden) renderDmModal();
|
|
5268
5543
|
if ($('#dmRail') && !$('#dmRail').classList.contains('dm-hidden')) renderDmRail();
|
|
5269
5544
|
return;
|
|
5270
5545
|
}
|
|
5546
|
+
/* KİŞİSEL TOOL çalışma kaydı — TOOLS konsolunun nokta göstergeleri */
|
|
5547
|
+
if (ev.type === 'tool-log') {
|
|
5548
|
+
toolUi.logRows.push({
|
|
5549
|
+
at: ev.at,
|
|
5550
|
+
tool: ev.tool,
|
|
5551
|
+
toolId: ev.toolId,
|
|
5552
|
+
ok: ev.ok,
|
|
5553
|
+
ms: ev.ms,
|
|
5554
|
+
error: ev.error,
|
|
5555
|
+
});
|
|
5556
|
+
if (toolUi.logRows.length > 60) toolUi.logRows.splice(0, toolUi.logRows.length - 60);
|
|
5557
|
+
scheduleToolRender();
|
|
5558
|
+
return;
|
|
5559
|
+
}
|
|
5271
5560
|
/* OFFLINE MESAJ KUYRUĞU: bağlantı + kuyruk olayları (sessionId filtresinden önce) */
|
|
5272
5561
|
if (ev.type === 'net' || ev.type === 'netQueue') { onNetEvent(ev); return; }
|
|
5273
5562
|
/* Sandbox klonlama progress'i (sessionId'siz global olay) */
|
|
@@ -6415,6 +6704,7 @@ async function init() {
|
|
|
6415
6704
|
};
|
|
6416
6705
|
|
|
6417
6706
|
refreshAgentsPane();
|
|
6707
|
+
renderToolBox(); // TOOLS konsolu: kişisel araçlar sol panelde
|
|
6418
6708
|
|
|
6419
6709
|
els.sendBtn.addEventListener('click', sendCurrent);
|
|
6420
6710
|
els.stopBtn.addEventListener('click', () => {
|
|
@@ -8616,7 +8906,15 @@ async function setFinanceMode(on) {
|
|
|
8616
8906
|
const brandSub = document.querySelector('#brand .brand-sub');
|
|
8617
8907
|
if (brandSub) brandSub.textContent = on ? 'Finance' : 'Agent';
|
|
8618
8908
|
try { localStorage.setItem('beast.financeMode', on ? '1' : '0'); } catch {}
|
|
8619
|
-
beast.financeMode(!!on, activeId).catch(() => {});
|
|
8909
|
+
const fm = await beast.financeMode(!!on, activeId).catch(() => ({}));
|
|
8910
|
+
/* finance modu açıldı ama aktif oturum NORMAL (örn. WhatsApp sohbeti) ise
|
|
8911
|
+
ASLA o oturumu finance'e çevirme — kendine ÖZEL finance oturumu aç */
|
|
8912
|
+
if (on && fm && fm.needNew) {
|
|
8913
|
+
try {
|
|
8914
|
+
const created = await beast.createSession();
|
|
8915
|
+
if (created && created.id) await openSession(created.id);
|
|
8916
|
+
} catch {}
|
|
8917
|
+
}
|
|
8620
8918
|
/* sohbet geçmişi listesi değişir: finance modunda yalnız finance sohbetleri */
|
|
8621
8919
|
try {
|
|
8622
8920
|
await refreshSessions();
|