beast-agent 2.4.1 → 2.4.5

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.4.1",
4
+ "version": "2.4.5",
5
5
  "description": "Ultra-fast local agent shell for Windows.",
6
6
  "author": "algokodcom (AlgoKod)",
7
7
  "license": "MIT",
@@ -987,9 +987,11 @@ class Engine {
987
987
  if (session.code) this._codeIndex.set(session.code, session.id);
988
988
  }
989
989
 
990
- /* Oturum dosyasındaki son 'msg' satırını (user) güncel içerikle değiştir —
991
- yanıtsız kalmış user mesajıyla yeni mesaj birleştirildiğinde kullanılır */
992
- _rewriteLastMsg(id, content, attachments) {
990
+ /* Oturum dosyasındaki son 'msg' satırını güncel içerikle değiştir —
991
+ yanıtsız kalmış user mesajıyla yeni mesaj birleştirildiğinde (role:'user')
992
+ ya da proaktif not son asistan mesajına birleştirildiğinde (role:'assistant') */
993
+ _rewriteLastMsg(id, content, attachments, role) {
994
+ const wantRole = role === 'assistant' ? 'assistant' : 'user';
993
995
  try {
994
996
  const file = this._file(String(id));
995
997
  const lines = fs.readFileSync(file, 'utf8').split('\n');
@@ -997,8 +999,8 @@ class Engine {
997
999
  if (!lines[i].trim()) continue;
998
1000
  let r;
999
1001
  try { r = JSON.parse(lines[i]); } catch { continue; }
1000
- if (r.t === 'msg' && r.role === 'user') {
1001
- const out = { t: 'msg', role: 'user', content: String(content || '') };
1002
+ if (r.t === 'msg' && r.role === wantRole) {
1003
+ const out = { t: 'msg', role: wantRole, content: String(content || '') };
1002
1004
  if (Array.isArray(attachments) && attachments.length) out.attachments = attachments;
1003
1005
  lines[i] = JSON.stringify(out);
1004
1006
  break;
@@ -2284,6 +2286,40 @@ class Engine {
2284
2286
  return true;
2285
2287
  }
2286
2288
 
2289
+ /* PROAKTİF MESAJ ENJEKSİYONU (Empati Loop): ajanın az önce KULLANICIYA
2290
+ bildirdiği metni, yeni bir tur BAŞLATMADAN geçmişe kendi asistan
2291
+ mesajı olarak işler. Model bir sonraki turda bu mesajı bağlamında
2292
+ "benim söylediğim söz" olarak görür — kullanıcı cevap verdiğinde
2293
+ sohbet aynı oturumda kopmadan devam eder. Son mesaj araçsız bir
2294
+ asistan mesajıysa metin ona BİRLEŞTİRİLİR — katı sağlayıcılarda
2295
+ art arda asistan mesajı gitmez. */
2296
+ injectAssistant(sessionId, text) {
2297
+ const s = this._load(String(sessionId));
2298
+ if (!s) return false;
2299
+ const body = String(text || '').slice(0, USER_MAX);
2300
+ if (!body.trim()) return false;
2301
+ const lastMsg = s.messages[s.messages.length - 1];
2302
+ if (
2303
+ lastMsg &&
2304
+ lastMsg.role === 'assistant' &&
2305
+ typeof lastMsg.content === 'string' &&
2306
+ !(Array.isArray(lastMsg.tool_calls) && lastMsg.tool_calls.length)
2307
+ ) {
2308
+ lastMsg.content = (lastMsg.content + '\n\n' + body).slice(0, USER_MAX);
2309
+ this._rewriteLastMsg(s.id, lastMsg.content, null, 'assistant');
2310
+ this.emit({ type: 'sessions' });
2311
+ return true;
2312
+ }
2313
+ const msg = { role: 'assistant', content: body };
2314
+ s.messages.push(msg);
2315
+ try {
2316
+ this._append(s, msg);
2317
+ } catch {}
2318
+ this.emit({ type: 'message', sessionId: s.id, message: msg });
2319
+ this.emit({ type: 'sessions' });
2320
+ return true;
2321
+ }
2322
+
2287
2323
  /* Paralel ajan GEÇMİŞİNİ topluca sil: çalışanlar/ bekleyenler iptal edilir,
2288
2324
  tüm bg oturum dosyaları + kalıcı kayıt temizlenir. Döndürür: silinen iş sayısı */
2289
2325
  clearAllBgJobs() {
package/src/main.js CHANGED
@@ -6212,6 +6212,7 @@ function empatiRememberFromEvent(ev) {
6212
6212
  const txt = typeof m.content === 'string' ? m.content : '';
6213
6213
  if (!txt.trim()) return;
6214
6214
  if (txt.startsWith((engine && engine.OBSERVE_MARK) || '[BAĞLAM')) return; /* sessiz bağlam — sohbet değil */
6215
+ if (txt.startsWith('🫡 *Beast proaktif:') || txt.startsWith('🫡 **Beast proaktif:')) return; /* proaktif not — döngü '[proaktif]' etiketiyle zaten hafızaya yazdı */
6215
6216
  if (m.role === 'user' && txt.startsWith('/')) return; /* slash komut gürültüsü */
6216
6217
  let bc = false;
6217
6218
  try {
@@ -6302,6 +6303,53 @@ function empatiLlmCompose(prompt) {
6302
6303
  .finally(() => clearTimeout(kill));
6303
6304
  }
6304
6305
 
6306
+ /* PROAKTİF NOT → OTURUM BAĞLAMI: bildirim hangi kanala gittiyse AYNI metin
6307
+ o kanalın sohbet oturumuna asistan mesajı olarak da işlenir (yeni tur
6308
+ başlamaz). Böylece kullanıcı bildirime cevap verdiğinde model o mesajı
6309
+ KENDİSİNİN attığını bilir — aynı oturum, kesintisiz bağlam. */
6310
+ const PROACTIVE_MARK = '🫡 *Beast proaktif:*';
6311
+
6312
+ function empatiInjectToSession(sid, out) {
6313
+ try {
6314
+ if (!sid || engine.isBusy(sid)) return; /* tur ortasında geçmişi karıştırma — bildirim kanala zaten gitti */
6315
+ engine.injectAssistant(sid, out);
6316
+ } catch {}
6317
+ }
6318
+
6319
+ /* Oturum yoksa oluştur (processTgMessage/processDcMessage ile aynı kalıp) */
6320
+ function ensureTgSession(chatId) {
6321
+ let sid = tgChats.get(chatId);
6322
+ if (!sid) {
6323
+ const v = engine.createSession();
6324
+ sid = v.id;
6325
+ tgChats.set(chatId, sid);
6326
+ tgRememberSession(chatId, sid);
6327
+ saveTgChats();
6328
+ }
6329
+ return sid;
6330
+ }
6331
+ function ensureDcSession(channelId) {
6332
+ let sid = dcChats.get(channelId);
6333
+ if (!sid) {
6334
+ const v = engine.createSession();
6335
+ sid = v.id;
6336
+ dcChats.set(channelId, sid);
6337
+ dcRememberSession(channelId, sid);
6338
+ saveDcChats();
6339
+ }
6340
+ return sid;
6341
+ }
6342
+
6343
+ /* Masaüstü yedeği: en güncel (bg/bot-DM'siz, meşgul olmayan) sohbet — yoksa yeni */
6344
+ function empatiDesktopSid() {
6345
+ try {
6346
+ for (const v of engine.listSessions()) {
6347
+ if (!engine.isBusy(v.id)) return String(v.id);
6348
+ }
6349
+ } catch {}
6350
+ return engine.createSession().id;
6351
+ }
6352
+
6305
6353
  /* bildirim hedefi: sekmeden seçilen entegrasyon; seçilmemişse bağlı olanlar.
6306
6354
  Hiçbir entegrasyon yazılamazsa masaüstü chat UI (toast) kalır. */
6307
6355
  function empatiNotify(text, ev) {
@@ -6310,17 +6358,43 @@ function empatiNotify(text, ev) {
6310
6358
  const tryWa = () => {
6311
6359
  try {
6312
6360
  const own = waOwnerNum();
6313
- if (own && wa && wa.connected) senders.push(() => sendWaSafe(own + '@s.whatsapp.net', '🫡 *Beast proaktif:*\n' + text));
6361
+ if (own && wa && wa.connected) {
6362
+ const jid = own + '@s.whatsapp.net';
6363
+ const out = PROACTIVE_MARK + '\n' + text;
6364
+ senders.push(() =>
6365
+ Promise.resolve(sendWaSafe(jid, out))
6366
+ .then(() => empatiInjectToSession(ensureWaSession(jid), out))
6367
+ .catch(() => {})
6368
+ );
6369
+ }
6314
6370
  } catch {}
6315
6371
  };
6316
6372
  const tryTg = () => {
6317
6373
  try {
6318
- if (tg && tg.connected) for (const id of tgOwnerIds()) senders.push(() => sendTgSafe(id, '🫡 *Beast proaktif:*\n' + text));
6374
+ if (tg && tg.connected) {
6375
+ const out = PROACTIVE_MARK + '\n' + text;
6376
+ for (const id of tgOwnerIds()) {
6377
+ senders.push(() =>
6378
+ Promise.resolve(sendTgSafe(id, out))
6379
+ .then(() => empatiInjectToSession(ensureTgSession(String(id)), out))
6380
+ .catch(() => {})
6381
+ );
6382
+ }
6383
+ }
6319
6384
  } catch {}
6320
6385
  };
6321
6386
  const tryDc = () => {
6322
6387
  try {
6323
- if (dc && dc.connected) for (const id of dcOwnerIds()) senders.push(() => sendDcSafe(id, '🫡 **Beast proaktif:**\n' + text));
6388
+ if (dc && dc.connected) {
6389
+ const out = '🫡 **Beast proaktif:**\n' + text;
6390
+ for (const id of dcOwnerIds()) {
6391
+ senders.push(() =>
6392
+ Promise.resolve(sendDcSafe(id, out))
6393
+ .then(() => empatiInjectToSession(ensureDcSession(String(id)), out))
6394
+ .catch(() => {})
6395
+ );
6396
+ }
6397
+ }
6324
6398
  } catch {}
6325
6399
  };
6326
6400
  if (cfg.notifyTarget === 'whatsapp') tryWa();
@@ -6331,9 +6405,11 @@ function empatiNotify(text, ev) {
6331
6405
  for (const fn of senders) {
6332
6406
  try { fn(); sent++; } catch {}
6333
6407
  }
6334
- /* hiçbir entegrasyona yazılamadıysa yalnız masaüstü chat UI'a düş */
6408
+ /* hiçbir entegrasyona yazılamadıysa yalnız masaüstü chat UI'a düş
6409
+ metin güncel sohbete de asistan mesajı olarak işlenir */
6335
6410
  try {
6336
6411
  if (!sent && win && !win.isDestroyed()) {
6412
+ empatiInjectToSession(empatiDesktopSid(), PROACTIVE_MARK + '\n' + text);
6337
6413
  win.webContents.send('agent:event', { type: 'proactive', id: ev.id, level: ev.level, title: ev.title, text });
6338
6414
  }
6339
6415
  } catch {}