beast-agent 2.38.4 → 2.39.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/bots.js +66 -0
- package/src/agent/customtools.js +1 -1
- package/src/agent/engine.js +222 -45
- package/src/agent/financetools.js +52 -0
- package/src/agent/mt5/BeastFinance.mq5 +290 -0
- package/src/agent/mt5setup.js +520 -0
- package/src/agent/scripts/mt5_bridge.py +112 -0
- package/src/agent/seeds/mql5/SKILL.md +25 -2
- package/src/agent/seeds/tool-yazma/SKILL.md +6 -4
- package/src/main.js +232 -12
- package/src/preload.js +1 -0
- package/src/renderer/index.html +18 -5
- package/src/renderer/renderer.js +159 -36
- package/src/renderer/style.css +30 -17
package/package.json
CHANGED
package/src/agent/bots.js
CHANGED
|
@@ -98,6 +98,70 @@ function adminBot() {
|
|
|
98
98
|
};
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
/* ZORUNLU VARSAYILAN BOTLAR: Beast (admin) + Trader + Coder + Tool.
|
|
102
|
+
Eksik olanlar OTOMATİK açılır — Tool botunun TEK görevi tool yazmaktır;
|
|
103
|
+
diğer ajanlar/botlar tool_request ile ona devreder (cephane mantığı). */
|
|
104
|
+
const DEFAULT_BOT_SEEDS = [
|
|
105
|
+
{
|
|
106
|
+
id: 'trader',
|
|
107
|
+
name: 'Trader',
|
|
108
|
+
icon: '📊',
|
|
109
|
+
prompt:
|
|
110
|
+
'Sen BEAST Trader botsun: disiplinli bir trading analisti. Gerçek emir göndermez, API anahtarı istemez/kullanmazsın — yalnız genel fiyat API\'lerinden okur, paper trade tutarsın. Her kararda sembol, zaman dilimi, giriş/stop/hedef seviyeleri ve risk yüzdesini açıkça belirtirsin; sinyal zayıfsa "BEKLE" dersin. İzleyici (watcher) kurarak sürekli izlersin. Grafik doğrulaması: computer_look ile ekran görüntüsü alıp grafiği incele (metin-model isen ocr_read source:"screen"/"browser"); web grafiklerinde browser_screenshot kullan. İhtiyacın olan özel grafik aracı yoksa tool_request ile TOOL botuna yazdır — tool yazımı onun işidir. Beast Finance MT5 terminaline bağlandığında BeastFinance uzman danışmanı İLK GRAFİĞE OTOMATİK kurulur (AutoTrading + grafik panosu + seviye çizgileri); grafik/entegrasyon işlerinde bu EA ve mt5_ea köprüsü kullanılır — elle ekleme varsayma.',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
id: 'coder',
|
|
114
|
+
name: 'Coder',
|
|
115
|
+
icon: '🤖',
|
|
116
|
+
prompt:
|
|
117
|
+
'Sen BEAST Coder botsun: disiplinli bir yazılım mühendisi. Küçük adımlarla plan çıkarır (todo), uygular, doğrularsın. Dosya düzenler, komut çalıştırır ve kısa net açıklamalar yaparsın; gereksiz konuşmazsın. Beast Finance tarafında BeastFinance.mq5 uzman danışmanı MT5 grafiğine otomatik kurulur; MT5/entegrasyon işleri bu EA ve mt5_ea köprüsü üzerinden yürür.',
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
id: 'tool',
|
|
121
|
+
name: 'Tool',
|
|
122
|
+
icon: '🛠️',
|
|
123
|
+
prompt:
|
|
124
|
+
'Sen BEAST TOOL botusun — TEK görevin TOOL YAZMAK. Başka hiçbir iş yapmazsın: analiz, genel sohbet, araştırma, kod projesi YOK; yalnız eksik/bozuk araçları yazar ve onarırsın. Her istek bir araç ihtiyacıdır. ÖNCE skill aracıyla "tool-yazma" skill\'ini oku ve sözleşmeye BİREBİR uy: araç %APPDATA%\\beast\\tools\\<slug>\\ klasöründe tool.json (tanım) + run.js (kod) olarak yaşar; slug a-z0-9_- 2-24 karakter. Sözleşme: stdin JSON argüman → stdout SADECE JSON sonuç; {ok:true,...} ya da {ok:false,error:"sebep"}; günlük/teşhis metnini console.error\'a yaz. Var olan aracı silip baştan yazma — edit_file ile GÜNCELLE. Yazdıktan sonra run_command ile TEST DÖNGÜSÜ işlet (echo \'{"mesaj":"test"}\' | node "%APPDATA%\\beast\\tools\\<slug>\\run.js"): çıktı JSON ve ok:true DEĞİLSE stderr\'i/hatayı oku → edit_file ile düzelt → YENİDEN test et; en fazla 5 deneme. Ancak test GEÇİNCE "YAYINDA" de; geçmeyen aracı yayınlama, raporda BAŞARISIZ + kök hatayı yaz. Ağ çağrılarında timeout kullan; şifre/API anahtarını ASLA loglama/yazma. İstek eksikse tek cümlelik varsayım yazıp çalışan aracı üret. Cevabın TEK paragraf: tool adı (tool__<slug>), ne yaptığı, adımlar (yazıldı → test → düzeltme → YAYINDA/BAŞARISIZ), doğrulama sonucu ve tek satır çağrı örneği. Başka ajanlara iş devretme — tool yazımı senin işin. TÜM ajanlar (Beast, finance trader/ekip, müşteri botları) tool_request ya da bot DM ile sana istek atar; her isteği araç ihtiyacı say ve sözleşmeye uygun yaz. Beast Finance ajanlarından grafik/ekran görüntüsü istekleri de gelir (ör. MT5 grafiğini PNG dosyasına kaydetme) — bunlar da araçtır, aynı sözleşmeyle yaz ve doğrula. BEASTFINANCE EA ARTIK VAR ve MT5 terminaline İLK GRAFIĞE OTOMATİK kurulur (derleme + AutoTrading dahil; kurmaya/kopyalamaya ÇALIŞMA). Beast Finance\'in ENTEGRASYON kanalı odur: heartbeat beast_ea.json, komut köprüsü beast_cmd.json/beast_cmd_ack.json, grafik panosu + seviye çizgileri beast_note.json (screenshot\'larda görünür); finance oturumlarında mt5_ea (status/ping/chart/note) aracıyla konuşulur. MT5 entegrasyonu isteği geldiğinde ÖNCE skill("mql5") oku ve köprüyü GENİŞLET (EA\'da ProcessCommands\'a yeni komut + python tarafında ea_cmd) — sıfırdan EA/script yazma.',
|
|
125
|
+
},
|
|
126
|
+
];
|
|
127
|
+
|
|
128
|
+
/* Eksik varsayılan botları oluştur (id sabit — tool_request 'tool' id'sini arar) */
|
|
129
|
+
function ensureDefaultBots() {
|
|
130
|
+
loadRegistry();
|
|
131
|
+
let created = false;
|
|
132
|
+
for (const def of DEFAULT_BOT_SEEDS) {
|
|
133
|
+
if (REG.bots.some((b) => b && b.id === def.id)) continue;
|
|
134
|
+
if (REG.bots.length >= MAX_BOTS) break;
|
|
135
|
+
const bot = {
|
|
136
|
+
id: def.id,
|
|
137
|
+
name: def.name,
|
|
138
|
+
icon: ICONS.includes(def.icon) ? def.icon : '🤖',
|
|
139
|
+
admin: false,
|
|
140
|
+
code: '',
|
|
141
|
+
prompt: String(def.prompt || '').slice(0, 4000),
|
|
142
|
+
perm: 'all',
|
|
143
|
+
vis: true,
|
|
144
|
+
/* Tool botu araç yazıp doğrulayabilmeli: run_command/read/write açık */
|
|
145
|
+
skills: { ...DEFAULT_SKILLS, run_command: def.id === 'tool' },
|
|
146
|
+
seeBots: [],
|
|
147
|
+
extBrowser: false,
|
|
148
|
+
browserDefault: 'dahili',
|
|
149
|
+
extCommand: '',
|
|
150
|
+
plugins: [],
|
|
151
|
+
createdAt: nowIso(),
|
|
152
|
+
};
|
|
153
|
+
REG.bots.push(bot);
|
|
154
|
+
created = true;
|
|
155
|
+
logChange(def.id, `varsayılan bot otomatik oluşturuldu (name="${def.name}")`);
|
|
156
|
+
}
|
|
157
|
+
if (created) {
|
|
158
|
+
ensureBotCodes();
|
|
159
|
+
saveRegistry();
|
|
160
|
+
ensureDirs();
|
|
161
|
+
}
|
|
162
|
+
return created;
|
|
163
|
+
}
|
|
164
|
+
|
|
101
165
|
/* ---------- registry ---------- */
|
|
102
166
|
|
|
103
167
|
let REG = null;
|
|
@@ -114,6 +178,8 @@ function loadRegistry() {
|
|
|
114
178
|
const beast = REG.bots.find((b) => b && b.id === 'beast');
|
|
115
179
|
if (!beast) REG.bots.unshift(adminBot());
|
|
116
180
|
else Object.assign(beast, { ...adminBot(), ...beast, id: 'beast', admin: true, name: beast.name || 'Beast' });
|
|
181
|
+
/* ZORUNLU bot seti: Beast + Trader + Coder + Tool (eksikler otomatik açılır) */
|
|
182
|
+
ensureDefaultBots();
|
|
117
183
|
saveRegistry();
|
|
118
184
|
ensureDirs();
|
|
119
185
|
return REG;
|
package/src/agent/customtools.js
CHANGED
|
@@ -149,7 +149,7 @@ function call(name, args) {
|
|
|
149
149
|
finish({ ok: false, error: 'tool zaman aşımı (' + Math.round(TOOL_TIMEOUT_MS / 1000) + ' sn)' });
|
|
150
150
|
}, TOOL_TIMEOUT_MS);
|
|
151
151
|
try {
|
|
152
|
-
child = spawn(process.execPath, [t.script], { cwd: t.
|
|
152
|
+
child = spawn(process.execPath, [t.script], { cwd: path.dirname(t.script), stdio: ['pipe', 'pipe', 'pipe'] });
|
|
153
153
|
} catch (e) {
|
|
154
154
|
return finish({ ok: false, error: String((e && e.message) || e) });
|
|
155
155
|
}
|
package/src/agent/engine.js
CHANGED
|
@@ -132,15 +132,16 @@ const PERM_TOOL_SETS = {
|
|
|
132
132
|
'web_search', 'http_fetch', 'webfetch', 'deep_search',
|
|
133
133
|
'browser_open', 'browser_read', 'browser_snapshot', 'browser_screenshot',
|
|
134
134
|
'browser_click', 'browser_type', 'browser_press', 'browser_scroll', 'browser_select',
|
|
135
|
-
'ocr_read',
|
|
135
|
+
'ocr_read', 'tool_request',
|
|
136
136
|
]),
|
|
137
137
|
read: new Set([
|
|
138
138
|
'web_search', 'http_fetch', 'webfetch', 'deep_search',
|
|
139
139
|
'browser_open', 'browser_read', 'browser_snapshot',
|
|
140
140
|
'list_dir', 'read_file', 'grep', 'glob',
|
|
141
141
|
'git_diff_review', 'repo_map', 'repo_symbols', 'xlsx_read',
|
|
142
|
+
'tool_request',
|
|
142
143
|
]),
|
|
143
|
-
chat: new Set([]), //
|
|
144
|
+
chat: new Set(['tool_request']), // sohbet + tool devri
|
|
144
145
|
};
|
|
145
146
|
const PERM_LEVELS = ['all', 'web', 'read', 'chat'];
|
|
146
147
|
|
|
@@ -320,6 +321,8 @@ class Engine {
|
|
|
320
321
|
this.browser = opts.browser || null; // dahili tarayıcı kancaları
|
|
321
322
|
this.fileSend = opts.fileSend || null; // #26 dosya gönderim köprüsü (chat/WA)
|
|
322
323
|
this.notifyOwnerFail = opts.notifyOwnerFail !== false; // #25 hata mail bildirimi (runtime /notify)
|
|
324
|
+
/* ENTEGRASYON BİLDİRİMİ: tool yazım/doğrulama adımları WA/TG/Discord'a düşer */
|
|
325
|
+
this.integrationNotify = typeof opts.integrationNotify === 'function' ? opts.integrationNotify : null;
|
|
323
326
|
this.reminders = opts.reminders || null; // hatırlatıcı kancası (main enjekte eder)
|
|
324
327
|
this.watchers = opts.watchers || null; // arka plan izleyici köprüsü (main enjekte eder)
|
|
325
328
|
/* opencode permission Service (birebir port): ask/reply — once|always|reject.
|
|
@@ -1918,6 +1921,8 @@ class Engine {
|
|
|
1918
1921
|
'ROL: TEKNİK ANALİZ AJANI 📊 — fiyat yapısı uzmanısın, İşlem AÇMAZSIN (mt5_trade/mt5_pending/mt5_close KULLANMA). Her turda odak semboller için: trend/yapı, destek-direnç bölgeleri, momentum (mt5_market + mt5_history verisiyle); sembol başına AL/SAT/BEKLE + giriş/SL/TP fikri üret — trader bu öneriyi işleme çevirir.',
|
|
1919
1922
|
macro:
|
|
1920
1923
|
'ROL: MAKRO AJANI 🌍 — büyük resim uzmanısın, İşlem AÇMAZSIN (mt5_trade/mt5_pending/mt5_close KULLANMA). Her turda web_search ile güncel makro manşetleri + ekonomik takvim riskleri (faiz, CPI, jeopolitik); DXY/altın/petrol bağıntılarını odak sembollere çevir; sembol başına yön eğilimi + TEMKİN/BEKLE notu ver.',
|
|
1924
|
+
visual:
|
|
1925
|
+
'ROL: GÖRSEL ANALİZ AJANI 👁 — grafik/ekran görüntüsü uzmanısın, İşlem AÇMAZSIN (mt5_trade/mt5_pending/mt5_close KULLANMA). Her turda computer_look ile MT5 grafiğini yakala (gerekirse computer_act ile timeframe/zoom ayarla); web grafikleri için browser_open + browser_screenshot, görsel göremeyen metin-model isen ocr_read (source:"screen"/"browser") kullan. Gördüğün yapıyı yorumla: trend, formasyon, mum yapısı, destek-direnç ve SL/TP çizgileri; sembol başına GÖRSEL TEYİT + AL/SAT/BEKLE notu üret. Önemli bulguyu görseliyle birlikte agent_dm ile ANA TRADER\'a ya da ekibe bildir (yakaladığın grafiği paylaş).',
|
|
1921
1926
|
})[String((session && session.financeRole) || '')] || '';
|
|
1922
1927
|
/* ROL → SKILL eşleştirmesi (ayarlar modalı): rol başına TEK ve ZORUNLU
|
|
1923
1928
|
skill; ANA TRADER için ayrıca PLAYBOOK skill'i (roleSkills.trader).
|
|
@@ -1956,12 +1961,20 @@ class Engine {
|
|
|
1956
1961
|
modeBlock2 + '\n' +
|
|
1957
1962
|
(roleBlockFull ? roleBlockFull + '\n' : '') +
|
|
1958
1963
|
(teamLine || '') +
|
|
1959
|
-
'MT5 ARAÇLARI: mt5_status (bağlantı), mt5_account (hesap), mt5_market (canlı fiyat), mt5_positions (açık pozisyonlar), mt5_orders (bekleyen emirler), mt5_history (kapanan işlemler), mt5_trade (piyasa emri), mt5_close (kapat), mt5_modify (SL/TP), mt5_pending (bekleyen emir), mt5_cancel (emir iptal).\n' +
|
|
1964
|
+
'MT5 ARAÇLARI: mt5_status (bağlantı), mt5_account (hesap), mt5_market (canlı fiyat), mt5_positions (açık pozisyonlar), mt5_orders (bekleyen emirler), mt5_history (kapanan işlemler), mt5_ea (BeastFinance grafik panosu: status/ping/chart/note), mt5_trade (piyasa emri), mt5_close (kapat), mt5_modify (SL/TP), mt5_pending (bekleyen emir), mt5_cancel (emir iptal).\n' +
|
|
1965
|
+
'BEASTFINANCE EA (OTOMATİK GRAFİK UZMANI — ENTEGRASYON KANALI): MT5 terminaline bağlanıldığında BeastFinance uzman danışmanı İLK GRAFİĞE OTOMATİK yüklenir, AutoTrading izni açılır (kurulum sistem tarafından yapılır; elle ekleme gerekmez). Grafik panosu + seviye çizgileri + dosya köprüsü (beast_ea.json / beast_cmd.json / beast_note.json) bu EA üzerinden yürür: entegrasyon işlerinde (status/ping/chart/note) mt5_ea kullan; yazdığın not ve çizgiler computer_look screenshot\'ında görünür, entegrasyon bildirimleriyle birlikte çalışır.\n' +
|
|
1960
1966
|
'YETKİLERİN (AÇIK — çekinmeden kullan):\n' +
|
|
1961
1967
|
'- skill: kurulu SKILL.md kataloğunu oku ve uygula — tool yazmadan ÖNCE skill("tool-yazma"), MT5 tarafı işlerden ÖNCE skill("mql5") oku ve prosedürüne birebir uy.\n' +
|
|
1962
1968
|
'- Kişisel tool yazma: %APPDATA%\\beast\\tools\\<slug>\\ içine tool.json + run.js yaz (write_file/edit_file); run_command ile çıktısını (JSON, ok alanlı) doğrula → tool__<slug> ANINDA tüm finance ajanlarında çağrılabilir olur.\n' +
|
|
1963
1969
|
'- MQL5: MT5 tarafında script/gösterge/EA yaz (write_file), metaeditor64.exe /compile ile derle, MQL5\\Files dosya köprüsüyle veriyi Beast\'e taşı; kullanıcıya çalıştırma adımını açıkça söyle.\n' +
|
|
1964
|
-
'- Yerleşik araçlar: run_command, python_run, read_file/write_file/edit_file, web_search/deep_search, browser_
|
|
1970
|
+
'- Yerleşik araçlar: run_command, python_run, read_file/write_file/edit_file, web_search/deep_search, browser_*, computer_look (ekran görüntüsü) — hepsi açık.\n' +
|
|
1971
|
+
'GRAFİK & EKRAN GÖRÜNTÜSÜ (karar öncesi görsel doğrulama):\n' +
|
|
1972
|
+
'- computer_look: masaüstü ekranını yakalar — MT5 grafiği SONRAKİ turda görsel olarak önüne gelir; trend/formasyon/mum yapısı + SL/TP çizgilerini doğrudan gör. Önemli işlem kararından önce grafiği gözle doğrula.\n' +
|
|
1973
|
+
'- mt5_ea action:"note": grafiğe kısa analiz/plan metni + seviye çizgileri (destek/direnç/SL/TP) yazar — BeastFinance EA panosu computer_look screenshot\'ında GÖRÜNÜR; entegrasyon bildirimleriyle birlikte kullan.\n' +
|
|
1974
|
+
'- browser_screenshot: web tabanlı grafikler (TradingView, Investing, MQL5) — browser_open ile aç, ekran görüntüsünü incele.\n' +
|
|
1975
|
+
'- Görsel göremiyorsan (metin-model) ocr_read kullan: source:"screen" masaüstünü, source:"browser" paneli OCR ile okur; grafikteki fiyat/seviyeleri metne çevirir.\n' +
|
|
1976
|
+
'- Grafikte gezinme/ölçek: computer_act ile timeframe, scroll, zoom (arka planda çalışır — kullanıcının faresini çalmaz).\n' +
|
|
1977
|
+
'- EKSİK ARAÇ: özel grafik aracı gerekiyorsa (ör. MT5 grafiğini PNG dosyasına kaydetme, çoklu timeframe tek görüntü, indikatör paneli okuma) VAR SAYMA — tool_request ile TOOL botuna yazdır (doğrulanınca tool__<ad> olarak ANINDA çağrılır); küçük aracı skill("tool-yazma") prosedürüyle kendin de yazabilirsin.\n' +
|
|
1965
1978
|
'VERİ AKIŞI (her değerlendirmede): mt5_account + mt5_positions + mt5_market çağrılarını AYNI turda PARALEL ver; gerekiyorsa mt5_history ile son işlemleri gör.\n' +
|
|
1966
1979
|
'PARALEL + KOORDİNASYON: uzun araştırma/işleri run_background ile paralel finance işçisine devret (parent finance olduğu için işçi mt5 okuma araçlarını görür); koşan ajanlarla konuşmak için agent_dm (to: ajan başlığındaki anahtar kelime, örn "GOLD"; ortak karar için group: "İSİM" ile grup sohbeti kur — mesaj tüm üyelere düşer). Görevin bitince DM/grup sohbetleri otomatik KAPANIR (geçmiş panelde kalır).\n' +
|
|
1967
1980
|
(symbols ? `İZLEME LİSTESİ: ${symbols}\n` : '') +
|
|
@@ -2031,6 +2044,14 @@ class Engine {
|
|
|
2031
2044
|
'# SKILLS\nKullanmadan önce ilgili SKILL.md dosyasını read_file ile oku.\n' + sk.join('\n')
|
|
2032
2045
|
);
|
|
2033
2046
|
}
|
|
2047
|
+
/* BOTLAR: MT5/Beast Finance entegrasyon kanalı — BeastFinance EA'sı otomatik
|
|
2048
|
+
kurulur; botlar grafik/entegrasyon işlerinde bunu bilerek hareket etsin */
|
|
2049
|
+
if (bctx) {
|
|
2050
|
+
parts.push(
|
|
2051
|
+
'# MT5 / BEAST FINANCE ENTEGRASYONU\n' +
|
|
2052
|
+
'Beast Finance açıldığında MT5 terminaline bağlanılır; BeastFinance.mq5 uzman danışmanı İLK GRAFİĞE OTOMATİK kurulur ve AutoTrading açılır. Grafik/entegrasyon işleri bu EA üzerinden yürür (heartbeat beast_ea.json, komut köprüsü beast_cmd.json, grafik panosu/seviyeler beast_note.json; finance oturumlarında mt5_ea status/ping/chart/note) — pano ve çizgiler screenshot\'larda görünür. Elle EA ekleme varsayma; eksik araç gerekiyorsa Tool botuna tool_request at.'
|
|
2053
|
+
);
|
|
2054
|
+
}
|
|
2034
2055
|
/* opencode instruction port (ajan modu): workspace AGENTS/CLAUDE/CONTEXT
|
|
2035
2056
|
talimatları — oturum başına bir kez okunur, epoch boyunca sabit */
|
|
2036
2057
|
const projChat = this._projectInstructions(session);
|
|
@@ -2072,6 +2093,7 @@ class Engine {
|
|
|
2072
2093
|
'Kullanıcı bir tarihte/saatte hatırlatılmasını isterse set_reminder kullan; when değerini ORTAMdaki bugüne göre hesapla (yerel saat). "Her sabah/gün/hafta" gibi tekrarlı isteklerde repeat alanını da ver (daily/weekly/monthly/weekdays veya cron).',
|
|
2073
2094
|
'Kullanıcı kalıcı bir arka plan takibi isterse (fiyat eşiği, pil seviyesi, sayfa değişikliği) watcher_add ile izleyici kur; kurduktan sonra watcher_list ile doğrula ve kullanıcıya koşulu + kontrol sıklığını kısaca bildir.',
|
|
2074
2095
|
'Anlık olay takipleri için (yeni mail, fiyat eşiği, dosya değişimi, webhook) event_subscribe kullan — cron/polling gerekmez; listeyi event_list ile göster, vazgeçirirse event_unsubscribe.',
|
|
2096
|
+
'ARAÇ EKSİKSE ÇEKİNME (CEPHANE): ihtiyacın olan bir araç yoksa/bozuksa tool_request ile TOOL botuna yazdır — tool yazımı onun TEK işidir; task alanına araç adı + ne yapacağı + girdi/çıktı sözleşmesini, context alanına örnek veri/yol/endpoint yaz. Araç doğrulanınca tool__<ad> olarak ANINDA çağrılabilir. Küçük kişisel araçları skill("tool-yazma") prosedürüyle kendin de yazabilirsin — yazdığını run_command ile MUTLAKA doğrula.',
|
|
2075
2097
|
'LOG ZEKASI: "hata var mı / ne oldu / neden çalışmadı" sorularında ya da bir iş beklenmedik bittiğinde/hata verdiğini fark ettiğinde log_analyze ile logları tara — top desenleri okuyup en olası KÖK NEDENİ tek cümlede söyle, somut çözüm öner; aynı desen 3+ tekrarlıysa bunu vurgula. Sürekli log gözetimi istenirse watcher_add ile kind:"logs" kur (örn "hata artarsa bağır" → level:"error", windowMin:10, op:"gt", value:2) ve koşulu kısaca bildir.',
|
|
2076
2098
|
'Kullanıcı "artık hep böyle yap / bunu unutma" tarzı kalıcı talimat verirse kural olarak kaydet: sohbette /rule <metin> kullanmasını söyle VEYA kullanıcı isterse event_subscribe ile olaya bağlan (mail/fiyat/dosya/webhook).',
|
|
2077
2099
|
'Kullanıcının mesajında 2+ ayrı iş/hedef varsa (örn "X yap ve sonra Y\u2019i kontrol et") KODLAMAYA/İŞE BAŞLAMADAN önce todo_write ile plan çıkar ve sırayla yürüt; her adımı tamamlarken güncelle. LİSTE DİSİPLİNİ: her adım bittiği AN status:"done" yap; son cevabını vermeden önce tüm maddeler done olmalı — yapılmayacaksa listeden düş. Listeyi yarım bırakma.',
|
|
@@ -2753,14 +2775,30 @@ class Engine {
|
|
|
2753
2775
|
const jobRec = this._bgJobs && this._bgJobs.get(String(sessionId));
|
|
2754
2776
|
if (jobRec && Array.isArray(jobRec.dmInbox) && jobRec.dmInbox.length) {
|
|
2755
2777
|
const inbox = jobRec.dmInbox.splice(0);
|
|
2756
|
-
const boxText = inbox
|
|
2778
|
+
const boxText = inbox
|
|
2779
|
+
.map((x) => (typeof x === 'string' ? x : String((x && x.text) || '')))
|
|
2780
|
+
.join('\n\n')
|
|
2781
|
+
.slice(0, 6000);
|
|
2782
|
+
/* görselli DM'ler: son 2 görsel bu turun mesajına vision olarak eklenir */
|
|
2783
|
+
const inboxImgs = inbox
|
|
2784
|
+
.map((x) => (x && typeof x === 'object' && /^data:image\//i.test(String(x.image || '')) ? String(x.image) : ''))
|
|
2785
|
+
.filter(Boolean)
|
|
2786
|
+
.slice(-2);
|
|
2757
2787
|
const prefix =
|
|
2758
2788
|
`[BEKLEYEN AJAN DM'LERİ — ${inbox.length} mesaj]\n${boxText}\n` +
|
|
2759
2789
|
`(Tur aralığında biriken DM'ler. Bu turda değerlendir; yalnızca aksiyon/cevap GEREKİYORSA agent_dm ile TEK kısa cevap ver — teşekkür/onay/ack mesajı YAZMA.)\n\n`;
|
|
2760
2790
|
if (typeof msg.content === 'string') {
|
|
2761
|
-
msg.content =
|
|
2762
|
-
|
|
2763
|
-
|
|
2791
|
+
msg.content = inboxImgs.length
|
|
2792
|
+
? [
|
|
2793
|
+
{ type: 'text', text: prefix + msg.content },
|
|
2794
|
+
...inboxImgs.map((u) => ({ type: 'image_url', image_url: { url: u } })),
|
|
2795
|
+
]
|
|
2796
|
+
: prefix + msg.content;
|
|
2797
|
+
} else if (Array.isArray(msg.content)) {
|
|
2798
|
+
if (msg.content[0] && typeof msg.content[0].text === 'string') {
|
|
2799
|
+
msg.content[0] = { ...msg.content[0], text: prefix + msg.content[0].text };
|
|
2800
|
+
}
|
|
2801
|
+
for (const u of inboxImgs) msg.content.push({ type: 'image_url', image_url: { url: u } });
|
|
2764
2802
|
}
|
|
2765
2803
|
}
|
|
2766
2804
|
} catch {}
|
|
@@ -3604,13 +3642,21 @@ class Engine {
|
|
|
3604
3642
|
if (this._deletedSessions && this._deletedSessions.has(sessionId)) continue;
|
|
3605
3643
|
if (continuous) {
|
|
3606
3644
|
job.dmInbox = job.dmInbox || [];
|
|
3607
|
-
job.dmInbox.push(
|
|
3645
|
+
job.dmInbox.push({
|
|
3646
|
+
text: String(r.text || '').slice(0, 4000),
|
|
3647
|
+
...(r.image ? { image: String(r.image) } : {}),
|
|
3648
|
+
});
|
|
3608
3649
|
if (job.dmInbox.length > 20) job.dmInbox.splice(0, job.dmInbox.length - 20);
|
|
3609
3650
|
continue;
|
|
3610
3651
|
}
|
|
3611
3652
|
if (this.isBusy(sessionId)) { rest.push(r); continue; }
|
|
3612
3653
|
let sent = false;
|
|
3613
|
-
try {
|
|
3654
|
+
try {
|
|
3655
|
+
const payload = { text: r.text };
|
|
3656
|
+
/* görselli DM: hedef ajan görüntüyü gerçekten GÖRSÜN (vision mesajı) */
|
|
3657
|
+
if (r.image) payload.attachments = [{ type: 'image', name: 'ekran goruntusu', dataUrl: String(r.image) }];
|
|
3658
|
+
sent = !!this.send(sessionId, payload);
|
|
3659
|
+
} catch {}
|
|
3614
3660
|
if (!sent) rest.push(r);
|
|
3615
3661
|
}
|
|
3616
3662
|
this._pendingReports = rest;
|
|
@@ -3630,6 +3676,7 @@ class Engine {
|
|
|
3630
3676
|
`DOSYA KURALI: dosya işlemlerinde özel araçları kullan — VAR OLAN dosyayı edit_file ile düzenle, yeniyi write_file ile yaz, okuma/arama read_file/grep/glob; run_command terminal işlerindir (build, git, kurulum). Bir dosyayı BİR KEZ oku — içerik bağlamda kalır, tekrar okuma.\n` +
|
|
3631
3677
|
(proj ? `PROJE TALİMATLARI (workspace AGENTS/CLAUDE/CONTEXT — daima uy):\n${proj}\n` : '') +
|
|
3632
3678
|
`HIZ KURALLARI:\n` +
|
|
3679
|
+
`- TOOL İSTEĞİ (CEPHANE): ihtiyacın olan araç yoksa/bozuksa tool_request ile TOOL botuna yazdır (araç doğrulanınca tool__<ad> olarak anında çağrılır); küçük aracı skill("tool-yazma") ile kendin de yaz ve run_command ile doğrula.\n` +
|
|
3633
3680
|
`- Döngülü işleri (çok URL/dosya/sayfa, tekrarlı parse-hesap) TEK python_run betiğinde topluca bitir.\n` +
|
|
3634
3681
|
`- Web için web_search kullan (zincir dahili tarayıcıyla başlar — gerçek Chromium ile Google); tek aramada bulunamazsa veya çok kaynaklı derin araştırma gerekiyorsa deep_search kullan (çoklu sorgu paralel + gizli tarayıcıda tam sayfa okuma). Sayfa açma/göstermenin VARSAYILANI DAHİLİ tarayıcıdır: browser_open → browser_snapshot → browser_click/type/read. Kullanıcı açıkça dış tarayıcı (chrome/firefox/başka/normal/kendi tarayıcım) istediyse run_command ile \`start "" <url>\` çalıştır. Görseli göremiyorsan metni ocr_read ile oku (source:"browser").\n` +
|
|
3635
3682
|
`- Bağımsız araç çağrılarını aynı turda PARALEL ver.\n` +
|
|
@@ -3708,6 +3755,11 @@ class Engine {
|
|
|
3708
3755
|
) {
|
|
3709
3756
|
toolsList = [...toolsList, AGENT_DM_DEF];
|
|
3710
3757
|
}
|
|
3758
|
+
/* TOOL İSTEĞİ (cephane): tool botu hariç TÜM oturumlar — müşteri bot
|
|
3759
|
+
sohbetleri, paralel ajanlar ve finance ajanları dahil */
|
|
3760
|
+
if (session && !session.isBotDm && session.botId !== 'tool') {
|
|
3761
|
+
toolsList = [...toolsList, TOOL_REQUEST_DEF];
|
|
3762
|
+
}
|
|
3711
3763
|
/* panel_run yalnız SANDBOX oturumlarında görünsün — diğer panellerde
|
|
3712
3764
|
modelin alet çantasında olmasın (hook olmadan çalışmaz) */
|
|
3713
3765
|
if (!(session && session.sbSandbox)) {
|
|
@@ -4613,33 +4665,21 @@ const skills = require('./skills');
|
|
|
4613
4665
|
Admin bot, 5 haneli kodla başka bota özel mesaj atar; hedef botun cevabı
|
|
4614
4666
|
senkron döner. İzolasyon: DM turları gizli pair oturumunda yürür, bot_dm
|
|
4615
4667
|
DM oturumlarında KAPALI (döngü koruması). Tüm trafik admin DM Log'ta. */
|
|
4616
|
-
async _botDm(args, sessionId, signal) {
|
|
4617
|
-
const bots = require('./bots');
|
|
4618
|
-
const code = String((args && args.to) || '').replace(/\D/g, '');
|
|
4619
|
-
const message = String((args && args.message) || '').slice(0, 6000);
|
|
4620
|
-
if (!/^\d{5}$/.test(code)) return { ok: false, error: 'geçersiz kod — 5 haneli bot kodu gir' };
|
|
4621
|
-
if (!message.trim()) return { ok: false, error: 'mesaj boş' };
|
|
4622
|
-
|
|
4623
|
-
const session = this.cache.get(String(sessionId)) || this._load(String(sessionId));
|
|
4624
|
-
const senderBotId = (session && session.botId) || 'beast';
|
|
4625
|
-
const senderBot = (typeof this.resolveBot === 'function' && senderBotId) ? this.resolveBot(senderBotId) : null;
|
|
4626
|
-
const senderIsAdmin = !session.botId || !!(senderBot && senderBot.admin);
|
|
4627
|
-
if (!senderIsAdmin) {
|
|
4628
|
-
return { ok: false, error: 'yetki yok — botlar arası DM yalnız yönetici (admin) bot tarafından açılabilir' };
|
|
4629
|
-
}
|
|
4630
|
-
|
|
4631
|
-
const target = bots.byCode(code);
|
|
4632
|
-
if (!target) return { ok: false, error: `bu kotta bot yok: ${code}` };
|
|
4633
|
-
if (target.id === senderBotId) return { ok: false, error: 'kendine DM atılamaz' };
|
|
4634
4668
|
|
|
4635
|
-
|
|
4636
|
-
|
|
4669
|
+
/* Deterministik pair oturumu: dm + (küçük kod + büyük kod) — aynı çift aynı oturum */
|
|
4670
|
+
_botPairId(senderBotId, target) {
|
|
4671
|
+
const sender = (typeof this.resolveBot === 'function' && senderBotId) ? this.resolveBot(senderBotId) : null;
|
|
4672
|
+
const codes = [String(sender ? sender.code || '' : ''), String(target && target.code || '')]
|
|
4637
4673
|
.map((c) => (/^\d{5}$/.test(c) ? c : '00000'))
|
|
4638
4674
|
.sort();
|
|
4639
|
-
|
|
4675
|
+
return 'dm' + codes[0] + codes[1];
|
|
4676
|
+
}
|
|
4640
4677
|
|
|
4678
|
+
/* Ortak bot sohbeti: hedef bota mesajı düşür, tur bitene kadar bekle, son
|
|
4679
|
+
asistan cevabını döndür. bot_dm (admin) + tool_request (tool botu) kullanır. */
|
|
4680
|
+
async _botConverse(senderBotId, target, message, signal, timeoutMs) {
|
|
4681
|
+
const pairId = this._botPairId(senderBotId, target);
|
|
4641
4682
|
let pair = this.cache.get(pairId) || this._load(pairId);
|
|
4642
|
-
const fresh = !pair.isBotDm && !pair.messages.length;
|
|
4643
4683
|
if (!pair.isBotDm) {
|
|
4644
4684
|
try {
|
|
4645
4685
|
fs.appendFileSync(this._file(pairId), JSON.stringify({ t: 'botdm', a: senderBotId, b: target.id, at: nowIso() }) + '\n');
|
|
@@ -4651,24 +4691,24 @@ const skills = require('./skills');
|
|
|
4651
4691
|
/* hedef botun kimliğiyle çalışsın; izolasyon _botSystemBlock'tan gelir */
|
|
4652
4692
|
this.setSessionBot(pairId, target.id);
|
|
4653
4693
|
this.setSessionPerm(pairId, target.perm || 'all');
|
|
4654
|
-
|
|
4694
|
+
const senderBot = (typeof this.resolveBot === 'function' && senderBotId) ? this.resolveBot(senderBotId) : null;
|
|
4655
4695
|
const senderName = senderBot ? senderBot.name : 'Beast';
|
|
4656
|
-
const senderCode = senderBot && /^\d{5}$/.test(String(senderBot.code || '')) ? senderBot.code :
|
|
4657
|
-
const prefix = `[BOT DM — gönderen bot: ${senderName} (kod
|
|
4696
|
+
const senderCode = senderBot && /^\d{5}$/.test(String(senderBot.code || '')) ? senderBot.code : '';
|
|
4697
|
+
const prefix = `[BOT DM — gönderen bot: ${senderName}${senderCode ? ' (kod ' + senderCode + ')' : ''} — cevabını kısa ve net ver, araç kullanman gerekmiyorsa kullanma]`;
|
|
4658
4698
|
const before = pair.messages.length;
|
|
4659
4699
|
const sent = this.send(pairId, { text: prefix + '\n' + message });
|
|
4660
4700
|
if (!sent) return { ok: false, error: 'DM oturumu başlatılamadı' };
|
|
4661
|
-
|
|
4662
|
-
|
|
4701
|
+
/* tur bitene kadar bekle (ctrl kaydı düşer) */
|
|
4702
|
+
const limit = Math.max(30000, Math.min(600000, Number(timeoutMs) || 120000));
|
|
4663
4703
|
const t0 = Date.now();
|
|
4664
|
-
while (Date.now() - t0 <
|
|
4704
|
+
while (Date.now() - t0 < limit) {
|
|
4665
4705
|
if (signal && signal.aborted) return { ok: false, error: 'iptal edildi' };
|
|
4666
4706
|
await new Promise((r) => setTimeout(r, 400));
|
|
4667
4707
|
if (!this.ctrls.has(pairId)) break;
|
|
4668
4708
|
}
|
|
4669
4709
|
if (this.ctrls.has(pairId)) {
|
|
4670
|
-
try { this.interrupt(pairId, 'bot DM zaman aşımına uğradı
|
|
4671
|
-
return { ok: false, error:
|
|
4710
|
+
try { this.interrupt(pairId, 'bot DM zaman aşımına uğradı — tur kesildi'); } catch {}
|
|
4711
|
+
return { ok: false, error: `hedef bot zaman aşımına uğradı (${Math.round(limit / 1000)} sn) — TOOLS panelinden sonucu takip et` };
|
|
4672
4712
|
}
|
|
4673
4713
|
const after = this.cache.get(pairId) || pair;
|
|
4674
4714
|
const newMsgs = after.messages.slice(before);
|
|
@@ -4678,6 +4718,74 @@ const skills = require('./skills');
|
|
|
4678
4718
|
return { ok: true, from: target.name, code: target.code, reply };
|
|
4679
4719
|
}
|
|
4680
4720
|
|
|
4721
|
+
async _botDm(args, sessionId, signal) {
|
|
4722
|
+
const bots = require('./bots');
|
|
4723
|
+
const code = String((args && args.to) || '').replace(/\D/g, '');
|
|
4724
|
+
const message = String((args && args.message) || '').slice(0, 6000);
|
|
4725
|
+
if (!/^\d{5}$/.test(code)) return { ok: false, error: 'geçersiz kod — 5 haneli bot kodu gir' };
|
|
4726
|
+
if (!message.trim()) return { ok: false, error: 'mesaj boş' };
|
|
4727
|
+
|
|
4728
|
+
const session = this.cache.get(String(sessionId)) || this._load(String(sessionId));
|
|
4729
|
+
const senderBotId = (session && session.botId) || 'beast';
|
|
4730
|
+
const senderBot = (typeof this.resolveBot === 'function' && senderBotId) ? this.resolveBot(senderBotId) : null;
|
|
4731
|
+
const senderIsAdmin = !session.botId || !!(senderBot && senderBot.admin);
|
|
4732
|
+
if (!senderIsAdmin) {
|
|
4733
|
+
return { ok: false, error: 'yetki yok — botlar arası DM yalnız yönetici (admin) bot tarafından açılabilir' };
|
|
4734
|
+
}
|
|
4735
|
+
|
|
4736
|
+
const target = bots.byCode(code);
|
|
4737
|
+
if (!target) return { ok: false, error: `bu kotta bot yok: ${code}` };
|
|
4738
|
+
if (target.id === senderBotId) return { ok: false, error: 'kendine DM atılamaz' };
|
|
4739
|
+
return this._botConverse(senderBotId, target, message, signal, 120000);
|
|
4740
|
+
}
|
|
4741
|
+
|
|
4742
|
+
/* TOOL İSTEĞİ (cephane): her oturum/bot eksik aracı TOOL botuna yazdırır.
|
|
4743
|
+
Admin şartı YOK — amaç tüm ajanların tool üretebilmesi; tool botunun
|
|
4744
|
+
kendisi ve DM oturumları hariç (döngü koruması). */
|
|
4745
|
+
async _toolRequest(args, sessionId, signal) {
|
|
4746
|
+
const bots = require('./bots');
|
|
4747
|
+
const task = String((args && args.task) || '').slice(0, 4000);
|
|
4748
|
+
const context = String((args && args.context) || '').slice(0, 4000);
|
|
4749
|
+
if (!task.trim()) return { ok: false, error: 'task gerekli — hangi araç, ne yapacak, girdi/çıktısı ne?' };
|
|
4750
|
+
const session = this.cache.get(String(sessionId)) || this._load(String(sessionId));
|
|
4751
|
+
if (session && session.isBotDm) return { ok: false, error: 'DM oturumunda tool_request kullanılamaz' };
|
|
4752
|
+
const senderBotId = (session && session.botId) || 'beast';
|
|
4753
|
+
if (senderBotId === 'tool') return { ok: false, error: 'Tool botu kendi işini kendisi yapar — doğrudan yaz' };
|
|
4754
|
+
const all = bots.list() || [];
|
|
4755
|
+
const target = all.find((b) => b && b.id === 'tool') || all.find((b) => b && /tool/i.test(String(b.name || '')));
|
|
4756
|
+
if (!target) return { ok: false, error: 'Tool botu bulunamadı — botlar sayfasından oluştur' };
|
|
4757
|
+
const who = (() => {
|
|
4758
|
+
try {
|
|
4759
|
+
const b = typeof this.resolveBot === 'function' ? this.resolveBot(senderBotId) : null;
|
|
4760
|
+
return (b && b.name) || (session && session.bgTitle) || 'Beast';
|
|
4761
|
+
} catch { return 'Beast'; }
|
|
4762
|
+
})();
|
|
4763
|
+
const message =
|
|
4764
|
+
`TOOL İSTEĞİ (gönderen: ${who}):\n` + task + '\n' +
|
|
4765
|
+
(context ? `\nBAĞLAM (kod/yol/örnek veri/endpoint):\n` + context + '\n' : '') +
|
|
4766
|
+
`\nHatırlatma: skill("tool-yazma") oku; %APPDATA%\\beast\\tools\\<slug>\\ içine tool.json + run.js yaz; run_command ile TEST DÖNGÜSÜNÜ işlet (çıktı {ok:true} olana kadar hata oku → edit_file ile düzelt → yeniden test; en fazla 5 deneme). Ancak test geçince yayınla; geçmeyen aracı yayınlama. Raporunda adımları yaz: yazıldı → test sonucu → (varsa) düzeltmeler → YAYINDA/BAŞARISIZ + tek satır çağrı örneği.`;
|
|
4767
|
+
const r = await this._botConverse(senderBotId, target, message, signal, 240000);
|
|
4768
|
+
/* RAPOR: tool yazım/doğrulama adımları bağlı entegrasyonlara (WA/TG/Discord) düşer */
|
|
4769
|
+
const notifyIntegrations = (text) => {
|
|
4770
|
+
try { if (typeof this.integrationNotify === 'function') this.integrationNotify(text); } catch {}
|
|
4771
|
+
};
|
|
4772
|
+
if (!r || !r.ok) {
|
|
4773
|
+
notifyIntegrations('🛠️ Tool botu BAŞARISIZ — isteyen: ' + who + '\nİstenen: ' + task.slice(0, 140) + '\nSebep: ' + String((r && r.error) || 'yanıt yok'));
|
|
4774
|
+
return r || { ok: false, error: 'Tool botu yanıt vermedi' };
|
|
4775
|
+
}
|
|
4776
|
+
notifyIntegrations(
|
|
4777
|
+
'🛠️ Tool botu raporu — isteyen: ' + who + '\n' +
|
|
4778
|
+
'İstenen: ' + task.slice(0, 140) + '\n' +
|
|
4779
|
+
String(r.reply || '').replace(/\s+/g, ' ').slice(0, 500)
|
|
4780
|
+
);
|
|
4781
|
+
return {
|
|
4782
|
+
ok: true,
|
|
4783
|
+
tool_bot: r.from,
|
|
4784
|
+
reply: r.reply,
|
|
4785
|
+
note: 'Araç hazır olduğunda modele tool__<slug> olarak ANINDA açılır (doğrulama testini Tool botu yaptı; adımlar entegrasyonlara bildirildi).',
|
|
4786
|
+
};
|
|
4787
|
+
}
|
|
4788
|
+
|
|
4681
4789
|
/* ADMIN İZLEME: tüm botlar arası DM oturumlarının listesi */
|
|
4682
4790
|
listBotDmSessions() {
|
|
4683
4791
|
const bots = require('./bots');
|
|
@@ -5046,7 +5154,7 @@ const skills = require('./skills');
|
|
|
5046
5154
|
}
|
|
5047
5155
|
/* AJAN DM: ajanlar arası mesaj — hedef koşan ajanın oturumuna düşer */
|
|
5048
5156
|
if (name === 'agent_dm') {
|
|
5049
|
-
return JSON.stringify(this._agentDmSend(sessionId, args));
|
|
5157
|
+
return JSON.stringify(await this._agentDmSend(sessionId, args));
|
|
5050
5158
|
}
|
|
5051
5159
|
/* KİŞİSEL TOOL: %APPDATA%\beast\tools\ — çocuk node prosesinde izole koşar */
|
|
5052
5160
|
if (String(name).startsWith('tool__')) {
|
|
@@ -5236,6 +5344,11 @@ const skills = require('./skills');
|
|
|
5236
5344
|
const r = await this._botDm(args, sessionId, signal);
|
|
5237
5345
|
return JSON.stringify(r);
|
|
5238
5346
|
}
|
|
5347
|
+
/* TOOL İSTEĞİ (cephane): eksik/bozuk aracı TOOL botuna yazdırır —
|
|
5348
|
+
tanım toolsList'e ekleniyordu ama dispatch'e bağlı değildi, burada bağlanır */
|
|
5349
|
+
if (name === 'tool_request') {
|
|
5350
|
+
return JSON.stringify(await this._toolRequest(args || {}, sessionId, signal));
|
|
5351
|
+
}
|
|
5239
5352
|
if (name === 'send_file') {
|
|
5240
5353
|
if (typeof this.fileSend !== 'function') {
|
|
5241
5354
|
return JSON.stringify({ ok: false, error: 'dosya gönderim köprüsü yok' });
|
|
@@ -5610,7 +5723,7 @@ const AGENT_DM_DEF = {
|
|
|
5610
5723
|
function: {
|
|
5611
5724
|
name: 'agent_dm',
|
|
5612
5725
|
description:
|
|
5613
|
-
'Send a short DM to another running agent (parallel agents / finance agents) to coordinate: share findings, ask status, warn about risk, hand off work, and MAKE JOINT DECISIONS. `to` = target session id OR a keyword from the agent title (e.g. "GOLD", "Trader"). `topic` = short subject label — replies to the same topic stay in the SAME conversation thread, so ALWAYS reuse the topic you were DMed with when replying. `group` = optional group-chat name (e.g. "GOLD EKIP"): creates or reuses a group conversation, adds the target agent as a member, and your message is delivered to EVERY member — use groups when a decision needs multiple agents.',
|
|
5726
|
+
'Send a short DM to another running agent (parallel agents / finance agents) to coordinate: share findings, ask status, warn about risk, hand off work, and MAKE JOINT DECISIONS. `to` = target session id OR a keyword from the agent title (e.g. "GOLD", "Trader"). `topic` = short subject label — replies to the same topic stay in the SAME conversation thread, so ALWAYS reuse the topic you were DMed with when replying. `group` = optional group-chat name (e.g. "GOLD EKIP"): creates or reuses a group conversation, adds the target agent as a member, and your message is delivered to EVERY member — use groups when a decision needs multiple agents. `image:true` attaches your last screenshot (fresh capture if none) — the receiving agent and the AJAN DM panel see it as an actual image; use it to share chart/screen findings.',
|
|
5614
5727
|
parameters: {
|
|
5615
5728
|
type: 'object',
|
|
5616
5729
|
properties: {
|
|
@@ -5618,12 +5731,32 @@ const AGENT_DM_DEF = {
|
|
|
5618
5731
|
topic: { type: 'string', description: 'Short subject label for the conversation thread, e.g. "GOLD pozisyon riski"' },
|
|
5619
5732
|
message: { type: 'string', description: 'Short message (1-3 sentences)' },
|
|
5620
5733
|
group: { type: 'string', description: 'Optional group-chat name — send to ALL members of that group (creates it on first use, adds the target agent)' },
|
|
5734
|
+
image: { type: 'boolean', description: 'true ise son ekran görüntünü mesaja iliştirir (yoksa taze ekran yakalar) — panelde ve karşı ajanda görsel olarak açılır; grafik/ekran bulgusunu paylaşmak için kullan' },
|
|
5621
5735
|
},
|
|
5622
5736
|
required: ['message'],
|
|
5623
5737
|
},
|
|
5624
5738
|
},
|
|
5625
5739
|
};
|
|
5626
5740
|
|
|
5741
|
+
/* TOOL İSTEĞİ (cephane kuralı): eksik/bozuk araç TOOL botuna yazdırılır.
|
|
5742
|
+
Tool botunun kendisi ve bot-DM oturumları hariç TÜM oturumlara açılır. */
|
|
5743
|
+
const TOOL_REQUEST_DEF = {
|
|
5744
|
+
type: 'function',
|
|
5745
|
+
function: {
|
|
5746
|
+
name: 'tool_request',
|
|
5747
|
+
description:
|
|
5748
|
+
'İhtiyaç duyduğun bir araç eksikse ya da bozuksa TOOL botuna yazdırır ve doğrulanmış aracın raporunu döndürür. Tool yazımı Tool botunun TEK işidir — sen tool yazmaya çalışma. task: araç adı + ne yapacak + girdi/çıktı sözleşmesi; context: örnek veri, dosya yolu, endpoint veya hata çıktısı. Araç hazır olunca tool__<ad> olarak ANINDA çağrılabilir.',
|
|
5749
|
+
parameters: {
|
|
5750
|
+
type: 'object',
|
|
5751
|
+
properties: {
|
|
5752
|
+
task: { type: 'string', description: 'Araç ihtiyacı: ad, işlev, girdi/çıktı sözleşmesi' },
|
|
5753
|
+
context: { type: 'string', description: 'Örnek veri, yol, endpoint ya da hata çıktısı' },
|
|
5754
|
+
},
|
|
5755
|
+
required: ['task'],
|
|
5756
|
+
},
|
|
5757
|
+
},
|
|
5758
|
+
};
|
|
5759
|
+
|
|
5627
5760
|
const TOOLS = [
|
|
5628
5761
|
...tools.definitions,
|
|
5629
5762
|
{
|
|
@@ -6409,11 +6542,14 @@ Engine.prototype.clearTodos = function (sid) {
|
|
|
6409
6542
|
/* Ajan DM gönder: hedef koşan paralel/finance ajanı (id YA DA başlık
|
|
6410
6543
|
anahtar kelimesi). Teslim _pendingReports kuyruğuyla yapılır — hedef
|
|
6411
6544
|
meşgulse mesaj done olunca düşer, kaybolmaz. Panel agent-dms.json'dan. */
|
|
6412
|
-
Engine.prototype._agentDmSend = function (fromSid, args) {
|
|
6545
|
+
Engine.prototype._agentDmSend = async function (fromSid, args) {
|
|
6413
6546
|
try {
|
|
6414
6547
|
const to = String((args && args.to) || '').trim();
|
|
6415
6548
|
const text = String((args && args.message) || '').trim().slice(0, 1200);
|
|
6416
6549
|
if (!text) return { ok: false, error: 'mesaj boş' };
|
|
6550
|
+
/* GÖRSEL DM: son ekran görüntüsü (yoksa taze yakalama) mesaja iliştirilir */
|
|
6551
|
+
const withImage = !!(args && args.image);
|
|
6552
|
+
const image = withImage ? await this._agentDmCaptureImage(fromSid) : '';
|
|
6417
6553
|
const groupName = String((args && args.group) || '').replace(/\s+/g, ' ').trim().slice(0, 40);
|
|
6418
6554
|
const jobs = this._bgJobs || new Map();
|
|
6419
6555
|
const fromJob = jobs.get(String(fromSid));
|
|
@@ -6538,6 +6674,7 @@ Engine.prototype._agentDmSend = function (fromSid, args) {
|
|
|
6538
6674
|
groupTitle: g.title,
|
|
6539
6675
|
topic,
|
|
6540
6676
|
text,
|
|
6677
|
+
...(image ? { image } : {}),
|
|
6541
6678
|
};
|
|
6542
6679
|
this._pushAgentDm(dm);
|
|
6543
6680
|
/* canlı event TEK SEFER — üye başına emit edilirse panelde çoğalır */
|
|
@@ -6549,6 +6686,7 @@ Engine.prototype._agentDmSend = function (fromSid, args) {
|
|
|
6549
6686
|
text:
|
|
6550
6687
|
`[AJAN DM (grup: "${g.title}") — ${dm.fromTitle} · konu: "${topic}"]\n${text}\n` +
|
|
6551
6688
|
`(Cevap yalnızca aksiyon/karar GEREKİYORSA ver — agent_dm group: "${g.title}", to: "${dm.fromTitle}", topic: "${topic}"; teşekkür/onay yazma.)`,
|
|
6689
|
+
...(image ? { image } : {}),
|
|
6552
6690
|
});
|
|
6553
6691
|
this.flushPendingReports(m);
|
|
6554
6692
|
}
|
|
@@ -6564,7 +6702,7 @@ Engine.prototype._agentDmSend = function (fromSid, args) {
|
|
|
6564
6702
|
|
|
6565
6703
|
/* BİREYSEL DM — DÜZ CHAT OTURUMUNA (sahibin sohbet geçmişi) ENJEKTE
|
|
6566
6704
|
ETMEYİZ: DM trafik yalnız AJAN DM konsolunda görünür. */
|
|
6567
|
-
const dm = { at, from: String(fromSid), fromTitle, to: String(target), toTitle, topic, text };
|
|
6705
|
+
const dm = { at, from: String(fromSid), fromTitle, to: String(target), toTitle, topic, text, ...(image ? { image } : {}) };
|
|
6568
6706
|
this._pushAgentDm(dm);
|
|
6569
6707
|
this._persistAgentDms();
|
|
6570
6708
|
emitSafe(this, target, { type: 'agent-dm', ...dm });
|
|
@@ -6574,6 +6712,7 @@ Engine.prototype._agentDmSend = function (fromSid, args) {
|
|
|
6574
6712
|
text:
|
|
6575
6713
|
`[AJAN DM — ${dm.fromTitle} · konu: "${topic}"]\n${text}\n` +
|
|
6576
6714
|
`(Cevap yalnızca aksiyon/karar GEREKİYORSA ver — agent_dm to: "${dm.fromTitle}", topic: "${topic}"; teşekkür/onay yazma.)`,
|
|
6715
|
+
...(image ? { image } : {}),
|
|
6577
6716
|
});
|
|
6578
6717
|
this.flushPendingReports(target);
|
|
6579
6718
|
}
|
|
@@ -6583,6 +6722,35 @@ Engine.prototype._agentDmSend = function (fromSid, args) {
|
|
|
6583
6722
|
}
|
|
6584
6723
|
};
|
|
6585
6724
|
|
|
6725
|
+
/* AJAN DM görseli: gönderenin oturumundaki EN SON ekran görüntüsünü (yoksa
|
|
6726
|
+
taze yakalama) data URL olarak döndürür. Çok büyük görseller DM kaydını
|
|
6727
|
+
şişirmesin diye 2.5MB üstü atlanır. */
|
|
6728
|
+
Engine.prototype._agentDmCaptureImage = async function (sid) {
|
|
6729
|
+
let found = '';
|
|
6730
|
+
const sess = this.cache.get(String(sid || '')) || null;
|
|
6731
|
+
const msgs = (sess && Array.isArray(sess.messages) ? sess.messages : []);
|
|
6732
|
+
for (let i = msgs.length - 1; i >= 0 && !found; i--) {
|
|
6733
|
+
const c = msgs[i] && msgs[i].content;
|
|
6734
|
+
if (!Array.isArray(c)) continue;
|
|
6735
|
+
for (let j = c.length - 1; j >= 0; j--) {
|
|
6736
|
+
const p = c[j];
|
|
6737
|
+
if (p && p.type === 'image_url' && p.image_url && /^data:image\//i.test(String(p.image_url.url || ''))) {
|
|
6738
|
+
found = String(p.image_url.url);
|
|
6739
|
+
break;
|
|
6740
|
+
}
|
|
6741
|
+
}
|
|
6742
|
+
}
|
|
6743
|
+
if (!found && this.computer && typeof this.computer.look === 'function') {
|
|
6744
|
+
try {
|
|
6745
|
+
const shot = await this.computer.look();
|
|
6746
|
+
const url = typeof shot === 'string' ? shot : (shot && (shot.image || shot.dataUrl || shot.__injectImage)) || '';
|
|
6747
|
+
if (/^data:image\//i.test(String(url || ''))) found = String(url);
|
|
6748
|
+
} catch {}
|
|
6749
|
+
}
|
|
6750
|
+
if (!found || found.length > 2500000) return '';
|
|
6751
|
+
return found;
|
|
6752
|
+
};
|
|
6753
|
+
|
|
6586
6754
|
/* İki ajanın ORTAK üyesi olduğu AÇIK grup var mı — 1:1 DM'leri grup içine
|
|
6587
6755
|
yönlendirirken kullanılır (ekip içi trafik tek thread'de toplanır). */
|
|
6588
6756
|
Engine.prototype._agentDmSharedGroup = function (a, b) {
|
|
@@ -6735,7 +6903,16 @@ Engine.prototype._persistAgentDms = function () {
|
|
|
6735
6903
|
try {
|
|
6736
6904
|
const groups = {};
|
|
6737
6905
|
for (const [, g] of this._agentGroups || new Map()) groups[g.id] = g;
|
|
6738
|
-
|
|
6906
|
+
/* görsel bütçesi: disk şişmesin — en yeni görseller tutulur (~24MB) */
|
|
6907
|
+
const dms = (this._agentDms || []).slice();
|
|
6908
|
+
let budget = 24 * 1024 * 1024;
|
|
6909
|
+
for (let i = dms.length - 1; i >= 0; i--) {
|
|
6910
|
+
const d = dms[i];
|
|
6911
|
+
if (!d || typeof d.image !== 'string' || !d.image) continue;
|
|
6912
|
+
if (d.image.length <= budget) { budget -= d.image.length; continue; }
|
|
6913
|
+
dms[i] = { ...d, image: '', imageOmitted: true };
|
|
6914
|
+
}
|
|
6915
|
+
this._atomicWrite(this._agentDmsFile, JSON.stringify({ dms, groups }, null, 2));
|
|
6739
6916
|
} catch {}
|
|
6740
6917
|
};
|
|
6741
6918
|
|