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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "beast-agent",
3
3
  "productName": "Beast Agent",
4
- "version": "2.9.0",
4
+ "version": "2.11.0",
5
5
  "description": "Ultra-fast local agent shell for Windows.",
6
6
  "author": "algokodcom (AlgoKod)",
7
7
  "license": "MIT",
@@ -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
- out = `*Beast Agent v${beastVersion()}*\nGüncelleme için: /update (kurulum hazır olunca /update now)`;
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
- let sid = tgChats.get(chatId) || tgSingleSid;
2654
- if (sid && engine.isBusy(sid)) {
2655
- /* oturum meşgul — WA ile aynı: kaybetme, iş bitene dek yeniden dene */
2656
- await new Promise((r) => setTimeout(r, TG_DEBOUNCE_MS));
2657
- return processTgMessage(chatId, payload, requeues + 1);
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
- let sid = dcChats.get(channelId) || dcSingleSid;
2868
- if (sid && engine.isBusy(sid)) {
2869
- /* oturum meşgul — WA/TG ile aynı: kaybetme, iş bitene dek yeniden dene */
2870
- await new Promise((r) => setTimeout(r, DC_DEBOUNCE_MS));
2871
- return processDcMessage(channelId, payload, 1);
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
- desktopEcho(sessionId, t, `**Beast Agent v${beastVersion()}**\nGüncelleme: **/update** (yeni sürüm kontrolü) · **/update now** (hemen kur)`);
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') {