beast-agent 2.9.0 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/agent/engine.js +4 -0
- package/src/main.js +130 -22
package/package.json
CHANGED
package/src/agent/engine.js
CHANGED
|
@@ -3402,6 +3402,10 @@ class Engine {
|
|
|
3402
3402
|
session.messages.slice(preLen).some((m) => m.role === 'user') ||
|
|
3403
3403
|
this._flushSteer(sid, session, emit)
|
|
3404
3404
|
) {
|
|
3405
|
+
/* ARA CEVAP: bu cevap 'done' değil (tur steer'le sürüyor) —
|
|
3406
|
+
bağlı kanallara (WA/TG/DC) tek tek iletilir; SON cevap yine
|
|
3407
|
+
done'da gider (çift yok: bu artık 'son' değil). */
|
|
3408
|
+
emit({ type: 'interim-final', message: assistant });
|
|
3405
3409
|
continue;
|
|
3406
3410
|
}
|
|
3407
3411
|
/* GÖREV LİSTESİ DİSİPLİNİ: ajan işi bitti sanıyor ama listede hâlâ
|
package/src/main.js
CHANGED
|
@@ -75,6 +75,73 @@ function emitUpdateEvent() {
|
|
|
75
75
|
} catch {}
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
/* /version ORTAK METNİ — tüm kanallar (desktop/WA/TG/DC): güncel sürüm +
|
|
79
|
+
npm'deki en son sürüm (yeni varsa vurgulu; 10dk cache'li getNpmLatest). */
|
|
80
|
+
async function versionText(waStyle) {
|
|
81
|
+
const cur = beastVersion();
|
|
82
|
+
const latest = await getNpmLatest();
|
|
83
|
+
const b = waStyle ? '*' : '**';
|
|
84
|
+
if (latest && isNewerVersion(latest, cur)) {
|
|
85
|
+
return (
|
|
86
|
+
`${b}Beast Agent v${cur}${b} — ${b}yeni sürüm var: v${latest}${b}\n` +
|
|
87
|
+
`Güncelleme: ${b}/update${b} (kontrol) · ${b}/update now${b} (hemen kur)`
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
if (latest) {
|
|
91
|
+
return `${b}Beast Agent v${cur}${b} — güncel ✓\nGüncelleme kontrolü: ${b}/update${b} · hemen kur: ${b}/update now${b}`;
|
|
92
|
+
}
|
|
93
|
+
return `${b}Beast Agent v${cur}${b}\nGüncelleme: ${b}/update${b} (yeni sürüm kontrolü) · ${b}/update now${b} (hemen kur)`;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* SÜRÜM GÜNCELLEMESİ BİLGİSİ: sürüm değiştiyse İLK AÇILIŞTA kullanıcı'nın
|
|
97
|
+
olduğu yere kısa bilgi düşer — en güncel oturum (desktop) + o oturuma
|
|
98
|
+
BĞLI kanal (WA/TG/DC; hangisindeyse oraya). settings.lastRunVersion
|
|
99
|
+
yazıldığı için sürüm başına YALNIZ BİR KEZ çalışır. */
|
|
100
|
+
function notifyVersionUpdate() {
|
|
101
|
+
const cur = beastVersion();
|
|
102
|
+
const prev = String(settings.lastRunVersion || '');
|
|
103
|
+
settings.lastRunVersion = cur;
|
|
104
|
+
saveSettings();
|
|
105
|
+
if (!prev || prev === cur) return; /* ilk kurulum ya da sürüm değişmedi */
|
|
106
|
+
const waStyleTxt =
|
|
107
|
+
`🔄 *Beast Agent güncellendi:* v${prev} → *v${cur}*\n` +
|
|
108
|
+
`Yenilikler: GitHub Releases · Sürüm: /version · Güncelleme: /update`;
|
|
109
|
+
let sid = '';
|
|
110
|
+
try { sid = reuseOrLatestSession(''); } catch {}
|
|
111
|
+
/* desktop: en güncel oturuma bilgi balonu */
|
|
112
|
+
try {
|
|
113
|
+
if (win && !win.isDestroyed() && sid) {
|
|
114
|
+
const mdTxt = waStyleTxt.replace(/\*/g, '**');
|
|
115
|
+
win.webContents.send('agent:event', { sessionId: sid, type: 'message', message: { role: 'assistant', content: mdTxt } });
|
|
116
|
+
win.webContents.send('agent:event', { sessionId: sid, type: 'done', usage: null });
|
|
117
|
+
}
|
|
118
|
+
} catch {}
|
|
119
|
+
/* kanallar: SADECE bu oturuma bağlı kanal (kullanıcı oradaydı) */
|
|
120
|
+
(async () => {
|
|
121
|
+
try {
|
|
122
|
+
if (wa && wa.connected) {
|
|
123
|
+
const own = waOwnerNum();
|
|
124
|
+
const jid = own ? own + '@s.whatsapp.net' : '';
|
|
125
|
+
if (jid && [...waChats.entries()].some(([j, s]) => j === jid && String(s) === String(sid))) {
|
|
126
|
+
await sendWaSafe(jid, waStyleTxt);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
} catch {}
|
|
130
|
+
try {
|
|
131
|
+
if (tg && tg.connected) {
|
|
132
|
+
const hit = [...tgChats.entries()].find(([, s]) => String(s) === String(sid));
|
|
133
|
+
if (hit) await sendTgSafe(hit[0], waStyleTxt);
|
|
134
|
+
}
|
|
135
|
+
} catch {}
|
|
136
|
+
try {
|
|
137
|
+
if (dc && dc.connected) {
|
|
138
|
+
const hit = [...dcChats.entries()].find(([, s]) => String(s) === String(sid));
|
|
139
|
+
if (hit) await sendDcSafe(hit[0], waStyleTxt);
|
|
140
|
+
}
|
|
141
|
+
} catch {}
|
|
142
|
+
})();
|
|
143
|
+
}
|
|
144
|
+
|
|
78
145
|
function replyUpdate(text) {
|
|
79
146
|
try {
|
|
80
147
|
for (const sid of updateReplies.sids) desktopEcho(sid, '/update', text);
|
|
@@ -1623,7 +1690,8 @@ async function tryWaSlash(jid, rawText, senderNum, payload0) {
|
|
|
1623
1690
|
out = 'Bu komut yalnız BeastCode modunda çalışır — önce /beastcode yaz.';
|
|
1624
1691
|
}
|
|
1625
1692
|
} else if (cmd === 'version') {
|
|
1626
|
-
|
|
1693
|
+
/* npm'deki en son sürümü de göster */
|
|
1694
|
+
out = await versionText(true);
|
|
1627
1695
|
} else {
|
|
1628
1696
|
out = `Bilinmeyen komut: /${cmd}\nListe için /help yaz.`;
|
|
1629
1697
|
}
|
|
@@ -2334,17 +2402,10 @@ async function processWaMessage(jid, payload, senderNum, requeues = 0) {
|
|
|
2334
2402
|
waLog(`skip flush: izinli eşleşme yok (sender=+${senderNum || '?'})`);
|
|
2335
2403
|
return;
|
|
2336
2404
|
}
|
|
2405
|
+
/* OPENCODE STEER: oturum meşgulse mesaj bekleMEZ — engine.send tamponuna
|
|
2406
|
+
ekler, koşan tur sonraki istekte görür ve cevaplar (eski cevap bozulmaz).
|
|
2407
|
+
Sıra korunur: floş katmanı debounceli ve sıralı işler. */
|
|
2337
2408
|
let sid = waChats.get(jid) || waSingleSid;
|
|
2338
|
-
if (sid && engine.isBusy(sid)) {
|
|
2339
|
-
/* oturum hâlâ önceki işle uğraşıyor — KAYBETME: sınırı kaldırdık,
|
|
2340
|
-
iş bitene dek her debounce turunda yeniden deneriz; kullanıcıya
|
|
2341
|
-
"işleyemedim" denmez, mesaj boşa gitmez. */
|
|
2342
|
-
if (requeues === 1) {
|
|
2343
|
-
waLog(`flush: oturum meşgul, mesaj kuyrukta bekliyor sid=${sid}`);
|
|
2344
|
-
}
|
|
2345
|
-
await new Promise((r) => setTimeout(r, WA_DEBOUNCE_MS));
|
|
2346
|
-
return processWaMessage(jid, payload, senderNum, requeues + 1);
|
|
2347
|
-
}
|
|
2348
2409
|
if (!isGroup && requeues > 0) {
|
|
2349
2410
|
// retry sonrası izin yeniden kontrol edilir (yukarıda hit zaten alınıyor)
|
|
2350
2411
|
}
|
|
@@ -2650,12 +2711,17 @@ async function processTgMessage(chatId, payload, requeues = 0) {
|
|
|
2650
2711
|
tgLog(`skip flush: izinli eşleşme yok (sender=${payload.senderId || '?'})`);
|
|
2651
2712
|
return;
|
|
2652
2713
|
}
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2714
|
+
/* /version HER KANALDA: sürüm + npm'deki en son sürüm (izin kontrolü üstte) */
|
|
2715
|
+
const tgRaw = String((payload && payload.text) || '').trim();
|
|
2716
|
+
if (tgRaw === '/version' || tgRaw.startsWith('/version ')) {
|
|
2717
|
+
versionText(true)
|
|
2718
|
+
.then((txt) => sendTgSafe(chatId, txt))
|
|
2719
|
+
.catch(() => {});
|
|
2720
|
+
return;
|
|
2658
2721
|
}
|
|
2722
|
+
/* OPENCODE STEER: meşgulse bekleme — engine.send tampona ekler, koşan tur
|
|
2723
|
+
sonraki istekte görür (WA ile aynı mantık) */
|
|
2724
|
+
let sid = tgChats.get(chatId) || tgSingleSid;
|
|
2659
2725
|
/* KANAL TEK OTURUMU: eskisi silinmedikçe hep aynı oturumdan devam */
|
|
2660
2726
|
sid = ensureTgSession(chatId);
|
|
2661
2727
|
/* Kişi bazlı granül izin: all/web/read/chat */
|
|
@@ -2864,12 +2930,17 @@ async function processDcMessage(channelId, payload) {
|
|
|
2864
2930
|
dcLog(`skip flush: izinli eşleşme yok (sender=${payload.senderId || '?'})`);
|
|
2865
2931
|
return;
|
|
2866
2932
|
}
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2933
|
+
/* /version HER KANALDA: sürüm + npm'deki en son sürüm (izin kontrolü üstte) */
|
|
2934
|
+
const dcRaw = String((payload && payload.text) || '').trim();
|
|
2935
|
+
if (dcRaw === '/version' || dcRaw.startsWith('/version ')) {
|
|
2936
|
+
versionText(true)
|
|
2937
|
+
.then((txt) => sendDcSafe(channelId, txt))
|
|
2938
|
+
.catch(() => {});
|
|
2939
|
+
return;
|
|
2872
2940
|
}
|
|
2941
|
+
/* OPENCODE STEER: meşgulse bekleme — engine.send tampona ekler, koşan tur
|
|
2942
|
+
sonraki istekte görür (WA/TG ile aynı mantık) */
|
|
2943
|
+
let sid = dcChats.get(channelId) || dcSingleSid;
|
|
2873
2944
|
/* KANAL TEK OTURUMU: eskisi silinmedikçe hep aynı oturumdan devam */
|
|
2874
2945
|
sid = ensureDcSession(channelId);
|
|
2875
2946
|
/* Kişi bazlı granül izin: all/web/read/chat */
|
|
@@ -3115,6 +3186,34 @@ function reloadBackend() {
|
|
|
3115
3186
|
})();
|
|
3116
3187
|
}
|
|
3117
3188
|
}
|
|
3189
|
+
/* OPENCODE STEER ARA CEVABI: koşan tur sırasında gelen mesajın cevabı.
|
|
3190
|
+
'done' YOK (tur steer'le sürüyor) — bu yüzden done akışı YAZMAZ.
|
|
3191
|
+
Bağlı kanallara (WA/TG/DC) tek tek gider; SON cevap yine done'da. */
|
|
3192
|
+
if (ev.type === 'interim-final' && ev.message) {
|
|
3193
|
+
const txt = typeof ev.message.content === 'string' ? ev.message.content.trim() : '';
|
|
3194
|
+
if (txt) {
|
|
3195
|
+
(async () => {
|
|
3196
|
+
try {
|
|
3197
|
+
if (wa && wa.connected) {
|
|
3198
|
+
const jid = waReplyJid(ev.sessionId);
|
|
3199
|
+
if (jid) await sendWaSafe(jid, txt);
|
|
3200
|
+
}
|
|
3201
|
+
} catch {}
|
|
3202
|
+
try {
|
|
3203
|
+
if (tg && tg.connected) {
|
|
3204
|
+
const hit = [...tgChats.entries()].find(([, s]) => s === ev.sessionId);
|
|
3205
|
+
if (hit) await sendTgSafe(hit[0], txt);
|
|
3206
|
+
}
|
|
3207
|
+
} catch {}
|
|
3208
|
+
try {
|
|
3209
|
+
if (dc && dc.connected) {
|
|
3210
|
+
const hit = [...dcChats.entries()].find(([, s]) => s === ev.sessionId);
|
|
3211
|
+
if (hit) await sendDcSafe(hit[0], txt);
|
|
3212
|
+
}
|
|
3213
|
+
} catch {}
|
|
3214
|
+
})();
|
|
3215
|
+
}
|
|
3216
|
+
}
|
|
3118
3217
|
// Telegram oturumlarının son cevabını geri gönder (WA ile aynı akış)
|
|
3119
3218
|
if ((ev.type === 'done' || ev.type === 'error') && tg && tg.connected) {
|
|
3120
3219
|
const hitT = [...tgChats.entries()].find(([, s]) => s === ev.sessionId);
|
|
@@ -3398,6 +3497,12 @@ app.whenReady().then(() => {
|
|
|
3398
3497
|
ensureDc().start().catch((e) => dcLog('autostart failed: ' + String((e && e.message) || e)));
|
|
3399
3498
|
}
|
|
3400
3499
|
|
|
3500
|
+
/* SÜRÜM GÜNCELLENDİYSE ilk açılışta bilgi: kanalların bağlanmasına 5 sn tanı,
|
|
3501
|
+
sonra kullanıcının olduğu yere (en güncel oturum + bağlı kanal) düşer */
|
|
3502
|
+
setTimeout(() => {
|
|
3503
|
+
try { notifyVersionUpdate(); } catch {}
|
|
3504
|
+
}, 5000);
|
|
3505
|
+
|
|
3401
3506
|
app.on('activate', () => {
|
|
3402
3507
|
if (BrowserWindow.getAllWindows().length === 0) createWindow();
|
|
3403
3508
|
});
|
|
@@ -4793,7 +4898,10 @@ ipcMain.handle('agent:send', (_e, { sessionId, text }) => {
|
|
|
4793
4898
|
return true;
|
|
4794
4899
|
}
|
|
4795
4900
|
if (t === '/version') {
|
|
4796
|
-
|
|
4901
|
+
/* npm registry'den en son sürümü de göster (10dk cache'li) */
|
|
4902
|
+
versionText(false)
|
|
4903
|
+
.then((txt) => desktopEcho(sessionId, t, txt))
|
|
4904
|
+
.catch(() => desktopEcho(sessionId, t, `**Beast Agent v${beastVersion()}**`));
|
|
4797
4905
|
return true;
|
|
4798
4906
|
}
|
|
4799
4907
|
if (t === '/help') {
|