beast-agent 2.4.5 → 2.6.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 +46 -0
- package/src/agent/nightref.js +35 -0
- package/src/agent/perception.js +95 -47
- package/src/main.js +321 -108
- package/src/preload.js +4 -0
- package/src/renderer/i18n.js +18 -10
- package/src/renderer/index.html +8 -12
- package/src/renderer/renderer.js +199 -130
- package/src/renderer/style.css +98 -51
package/src/main.js
CHANGED
|
@@ -229,17 +229,20 @@ startHealthServer(); /* splash/boot aşamasından itibaren /health ayakta */
|
|
|
229
229
|
try { setSearchChain(settings.searchChain); } catch {}
|
|
230
230
|
try { setTinyfishKey(settings.tinyfishKey || null); } catch {}
|
|
231
231
|
let wa = null;
|
|
232
|
-
let waChats = new Map(); // jid -> aktif session id
|
|
232
|
+
let waChats = new Map(); // jid -> aktif session id (hepsi KANAL TEK OTURUMUNA bağlı)
|
|
233
|
+
let waSingleSid = null; // KANAL TEK OTURUMU: WhatsApp için BİR oturum — silinmedikçe hep aynı
|
|
233
234
|
let waHistory = new Map(); // jid -> [sid,...] bu sohbete ait tüm oturumlar
|
|
234
235
|
let waBcMode = new Set(); // jid -> BeastCode modu AKTİF (WhatsApp'tan uzaktan kodlama)
|
|
235
236
|
let waJidPn = new Map(); // jid -> gerçek telefon numarası (LID fallback için)
|
|
236
237
|
const WA_HISTORY_CAP = 20;
|
|
237
238
|
let tg = null;
|
|
238
|
-
let tgChats = new Map(); // telegram chatId -> aktif session id
|
|
239
|
+
let tgChats = new Map(); // telegram chatId -> aktif session id (hepsi KANAL TEK OTURUMUNA bağlı)
|
|
240
|
+
let tgSingleSid = null; // KANAL TEK OTURUMU: Telegram için BİR oturum
|
|
239
241
|
let tgHistory = new Map(); // chatId -> [sid,...]
|
|
240
242
|
const TG_HISTORY_CAP = 20;
|
|
241
243
|
let dc = null;
|
|
242
|
-
let dcChats = new Map(); // discord channelId -> aktif session id
|
|
244
|
+
let dcChats = new Map(); // discord channelId -> aktif session id (hepsi KANAL TEK OTURUMUNA bağlı)
|
|
245
|
+
let dcSingleSid = null; // KANAL TEK OTURUMU: Discord için BİR oturum
|
|
243
246
|
let dcHistory = new Map(); // channelId -> [sid,...]
|
|
244
247
|
const DC_HISTORY_CAP = 20;
|
|
245
248
|
const DC_CHATS_FILE = path.join(APP_DIR, 'dc-chats.json');
|
|
@@ -278,6 +281,8 @@ try {
|
|
|
278
281
|
if (!h.includes(s)) h.push(s);
|
|
279
282
|
waHistory.set(j, h.slice(-WA_HISTORY_CAP));
|
|
280
283
|
}
|
|
284
|
+
/* kanal tek oturumu: kayıtlı aktif id (geçersizse ensure yeniden seçer) */
|
|
285
|
+
if (typeof raw.active === 'string' && raw.active) waSingleSid = raw.active;
|
|
281
286
|
/* BeastCode modu: hangi sohbetler uzaktan kodlama yapıyor */
|
|
282
287
|
if (Array.isArray(raw.bcMode)) {
|
|
283
288
|
for (const j of raw.bcMode) if (typeof j === 'string') waBcMode.add(j);
|
|
@@ -293,6 +298,7 @@ function saveWaChats() {
|
|
|
293
298
|
chats: Object.fromEntries(waChats),
|
|
294
299
|
history: Object.fromEntries([...waHistory.entries()].map(([j, a]) => [j, a.slice(-WA_HISTORY_CAP)])),
|
|
295
300
|
bcMode: [...waBcMode],
|
|
301
|
+
active: waSingleSid || '',
|
|
296
302
|
})
|
|
297
303
|
);
|
|
298
304
|
} catch {}
|
|
@@ -1268,12 +1274,26 @@ async function tryWaSlash(jid, rawText, senderNum, payload0) {
|
|
|
1268
1274
|
if (cmd === 'help') {
|
|
1269
1275
|
out = waSlashHelp();
|
|
1270
1276
|
} else if (cmd === 'new') {
|
|
1277
|
+
/* /new: kanalın TEK oturumunu kapat, yenisini aç — aynı anda iki
|
|
1278
|
+
WhatsApp sohbet oturumu olmaz; eski oturum silinir */
|
|
1279
|
+
const oldSid = waSingleSid || waChats.get(jid) || '';
|
|
1280
|
+
if (oldSid) {
|
|
1281
|
+
let olds = null;
|
|
1282
|
+
try { olds = engine.cache.get(oldSid) || null; } catch {}
|
|
1283
|
+
if (!olds || !olds.bcCode) {
|
|
1284
|
+
/* Beast Code panel oturumuysa dokunma — yalnız pointer taşınır */
|
|
1285
|
+
try { engine.deleteSession(oldSid); } catch {}
|
|
1286
|
+
for (const [j, h] of waHistory.entries()) waHistory.set(j, h.filter((x) => x !== oldSid));
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1271
1289
|
const v = engine.createSession();
|
|
1290
|
+
waSingleSid = v.id;
|
|
1291
|
+
for (const j of [...waChats.keys()]) waChats.set(j, v.id);
|
|
1272
1292
|
waChats.set(jid, v.id);
|
|
1273
1293
|
waRememberSession(jid, v.id);
|
|
1274
1294
|
saveWaChats();
|
|
1275
1295
|
wa.setWatchJids([...waChats.keys()]);
|
|
1276
|
-
out = `*Yeni oturum* \`${v.code}\` açıldı —
|
|
1296
|
+
out = `*Yeni oturum* \`${v.code}\` açıldı — eski oturum kapatıldı, artık buradan devam.\nVar olan başka oturuma geçiş: \`/open <kod>\``;
|
|
1277
1297
|
} else if (cmd === 'open') {
|
|
1278
1298
|
if (!arg) {
|
|
1279
1299
|
out = 'Kullanım: `/open <kod>` — kodları görmek için /sessions';
|
|
@@ -1282,7 +1302,9 @@ async function tryWaSlash(jid, rawText, senderNum, payload0) {
|
|
|
1282
1302
|
if (!hit) {
|
|
1283
1303
|
out = `\`${arg.toUpperCase()}\` kodlu oturum bulunamadı. Listeyi görmek için /sessions`;
|
|
1284
1304
|
} else {
|
|
1285
|
-
|
|
1305
|
+
/* /open: kanal TEK oturumunu bu oturuma çevirir — tüm jid'ler bağlanır */
|
|
1306
|
+
waSingleSid = hit.id;
|
|
1307
|
+
for (const j of [...waChats.keys()]) waChats.set(j, hit.id);
|
|
1286
1308
|
waRememberSession(jid, hit.id);
|
|
1287
1309
|
saveWaChats();
|
|
1288
1310
|
wa.setWatchJids([...waChats.keys()]);
|
|
@@ -1564,14 +1586,15 @@ async function tryWaSlash(jid, rawText, senderNum, payload0) {
|
|
|
1564
1586
|
try { engine.interrupt(sid, 'kullanıcı /beastagent ile sohbet moduna döndü'); } catch {}
|
|
1565
1587
|
}
|
|
1566
1588
|
waBcMode.delete(jid);
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1589
|
+
/* KANAL TEK OTURUMU: yeni oturum AÇILMAZ — sohbet oturumuna dönülür
|
|
1590
|
+
(silinmediyse hep aynı; ilk kez ise burada oluşur) */
|
|
1591
|
+
const chatSid = ensureWaSession(jid);
|
|
1592
|
+
const chatS = engine.cache.get(chatSid);
|
|
1570
1593
|
saveWaChats();
|
|
1571
1594
|
if (wa) wa.setWatchJids([...waChats.keys()]);
|
|
1572
1595
|
emitWaEventSafe({ type: 'bc-screen', on: false });
|
|
1573
1596
|
out =
|
|
1574
|
-
`*💬 Sohbet moduna dönüldü* — masaüstünde chat ekranı açıldı,
|
|
1597
|
+
`*💬 Sohbet moduna dönüldü* — masaüstünde chat ekranı açıldı, sohbet oturumu \`${(chatS && chatS.code) || '?'}\`.\n` +
|
|
1575
1598
|
`Kodlar duruyor: \`${waBcWorkspace()}\`\n` +
|
|
1576
1599
|
`Tekrar kodlamak için: /beastcode`;
|
|
1577
1600
|
}
|
|
@@ -1682,19 +1705,58 @@ function waGroupSenderInfo(payload) {
|
|
|
1682
1705
|
return { label, name: (hitP && hitP.name) || '', isOwner: !!(hitP && hitP.owner) };
|
|
1683
1706
|
}
|
|
1684
1707
|
|
|
1685
|
-
/*
|
|
1708
|
+
/* ---------- KANAL TEK OTURUMU (WA/TG/DC) ----------
|
|
1709
|
+
Her kanalın BİR aktif sohbet oturumu vardır; eskisi silinmedikçe hep
|
|
1710
|
+
AYNI oturumdan devam edilir — Beast kendi kendine oturum kapatıp
|
|
1711
|
+
yenisiyle değiştirmez. Yenisi yalnızca: (1) kayıtlı oturum dosyası
|
|
1712
|
+
yoksa (kullanıcı UI'dan sildi), (2) kullanıcı WA'da /new yazarsa.
|
|
1713
|
+
Masaüstü chat UI'daki "+ Yeni Sohbet" bu kuralın dışındadır. */
|
|
1714
|
+
function sessionFileAlive(sid) {
|
|
1715
|
+
try {
|
|
1716
|
+
return !!sid && fs.existsSync(path.join(engine.sessionsDir, String(sid) + '.jsonl'));
|
|
1717
|
+
} catch {
|
|
1718
|
+
return false;
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
/* kanalın yaşayan tek oturumunu döndürür; geçersizse eski bağlamdan devralır,
|
|
1723
|
+
o da yoksa (ilk kullanım) yeni açar ve tüm jid'leri ona bağlar */
|
|
1686
1724
|
function ensureWaSession(jid) {
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1725
|
+
if (!waSingleSid || !sessionFileAlive(waSingleSid)) {
|
|
1726
|
+
let best = '';
|
|
1727
|
+
let bestTs = '';
|
|
1728
|
+
for (const c of new Set([...waChats.values(), waSingleSid])) {
|
|
1729
|
+
if (!c || !sessionFileAlive(c)) continue;
|
|
1730
|
+
let ts = '';
|
|
1731
|
+
try {
|
|
1732
|
+
const s = engine.cache.get(c) || engine._load(c);
|
|
1733
|
+
ts = String((s && s.updatedAt) || '');
|
|
1734
|
+
} catch {}
|
|
1735
|
+
if (!best || ts > bestTs) {
|
|
1736
|
+
best = c;
|
|
1737
|
+
bestTs = ts;
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
waSingleSid = best || engine.createSession().id;
|
|
1741
|
+
saveWaChats();
|
|
1742
|
+
}
|
|
1743
|
+
let dirty = false;
|
|
1744
|
+
for (const [j, s] of waChats.entries()) {
|
|
1745
|
+
if (s !== waSingleSid) {
|
|
1746
|
+
waChats.set(j, waSingleSid);
|
|
1747
|
+
dirty = true;
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
if (jid != null && waChats.get(String(jid)) !== waSingleSid) {
|
|
1751
|
+
waChats.set(String(jid), waSingleSid);
|
|
1752
|
+
dirty = true;
|
|
1753
|
+
}
|
|
1754
|
+
waRememberSession(String(jid), waSingleSid);
|
|
1755
|
+
if (dirty) {
|
|
1692
1756
|
saveWaChats();
|
|
1693
1757
|
if (wa) wa.setWatchJids([...waChats.keys()]);
|
|
1694
|
-
} else {
|
|
1695
|
-
waRememberSession(jid, sid);
|
|
1696
1758
|
}
|
|
1697
|
-
return
|
|
1759
|
+
return waSingleSid;
|
|
1698
1760
|
}
|
|
1699
1761
|
|
|
1700
1762
|
/* ---------- GRUP BAĞLAM AKIŞI (mentionOnly + seeAll) ----------
|
|
@@ -2232,7 +2294,7 @@ async function processWaMessage(jid, payload, senderNum, requeues = 0) {
|
|
|
2232
2294
|
waLog(`skip flush: izinli eşleşme yok (sender=+${senderNum || '?'})`);
|
|
2233
2295
|
return;
|
|
2234
2296
|
}
|
|
2235
|
-
let sid = waChats.get(jid);
|
|
2297
|
+
let sid = waChats.get(jid) || waSingleSid;
|
|
2236
2298
|
if (sid && engine.isBusy(sid)) {
|
|
2237
2299
|
/* oturum hâlâ önceki işle uğraşıyor — KAYBETME: sınırı kaldırdık,
|
|
2238
2300
|
iş bitene dek her debounce turunda yeniden deneriz; kullanıcıya
|
|
@@ -2246,16 +2308,8 @@ async function processWaMessage(jid, payload, senderNum, requeues = 0) {
|
|
|
2246
2308
|
if (!isGroup && requeues > 0) {
|
|
2247
2309
|
// retry sonrası izin yeniden kontrol edilir (yukarıda hit zaten alınıyor)
|
|
2248
2310
|
}
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
sid = v.id;
|
|
2252
|
-
waChats.set(jid, sid);
|
|
2253
|
-
waRememberSession(jid, sid);
|
|
2254
|
-
saveWaChats();
|
|
2255
|
-
if (wa) wa.setWatchJids([...waChats.keys()]);
|
|
2256
|
-
} else {
|
|
2257
|
-
waRememberSession(jid, sid);
|
|
2258
|
-
}
|
|
2311
|
+
/* KANAL TEK OTURUMU: eskisi silinmedikçe hep aynı oturumdan devam */
|
|
2312
|
+
sid = ensureWaSession(jid);
|
|
2259
2313
|
// Cevap verilecek — karşı telefonda "yazıyor…" göstergesi (medya işlenene dek sürer)
|
|
2260
2314
|
wa.setComposing(jid, true);
|
|
2261
2315
|
// Kişi bazlı granül izin: all/web/read/chat
|
|
@@ -2462,6 +2516,8 @@ function ensureWa() {
|
|
|
2462
2516
|
if (Array.isArray(arr)) tgHistory.set(c, arr.filter((x) => typeof x === 'string').slice(-TG_HISTORY_CAP));
|
|
2463
2517
|
}
|
|
2464
2518
|
}
|
|
2519
|
+
/* kanal tek oturumu: kayıtlı aktif id (geçersizse ensure yeniden seçer) */
|
|
2520
|
+
if (raw && typeof raw.active === 'string' && raw.active) tgSingleSid = raw.active;
|
|
2465
2521
|
for (const [c, s] of tgChats.entries()) {
|
|
2466
2522
|
const h = tgHistory.get(c) || [];
|
|
2467
2523
|
if (!h.includes(s)) h.push(s);
|
|
@@ -2477,6 +2533,7 @@ function saveTgChats() {
|
|
|
2477
2533
|
JSON.stringify({
|
|
2478
2534
|
chats: Object.fromEntries(tgChats),
|
|
2479
2535
|
history: Object.fromEntries([...tgHistory.entries()].map(([c, a]) => [c, a.slice(-TG_HISTORY_CAP)])),
|
|
2536
|
+
active: tgSingleSid || '',
|
|
2480
2537
|
})
|
|
2481
2538
|
);
|
|
2482
2539
|
} catch {}
|
|
@@ -2549,21 +2606,14 @@ async function processTgMessage(chatId, payload, requeues = 0) {
|
|
|
2549
2606
|
tgLog(`skip flush: izinli eşleşme yok (sender=${payload.senderId || '?'})`);
|
|
2550
2607
|
return;
|
|
2551
2608
|
}
|
|
2552
|
-
let sid = tgChats.get(chatId);
|
|
2609
|
+
let sid = tgChats.get(chatId) || tgSingleSid;
|
|
2553
2610
|
if (sid && engine.isBusy(sid)) {
|
|
2554
2611
|
/* oturum meşgul — WA ile aynı: kaybetme, iş bitene dek yeniden dene */
|
|
2555
2612
|
await new Promise((r) => setTimeout(r, TG_DEBOUNCE_MS));
|
|
2556
2613
|
return processTgMessage(chatId, payload, requeues + 1);
|
|
2557
2614
|
}
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
sid = v.id;
|
|
2561
|
-
tgChats.set(chatId, sid);
|
|
2562
|
-
tgRememberSession(chatId, sid);
|
|
2563
|
-
saveTgChats();
|
|
2564
|
-
} else {
|
|
2565
|
-
tgRememberSession(chatId, sid);
|
|
2566
|
-
}
|
|
2615
|
+
/* KANAL TEK OTURUMU: eskisi silinmedikçe hep aynı oturumdan devam */
|
|
2616
|
+
sid = ensureTgSession(chatId);
|
|
2567
2617
|
/* Kişi bazlı granül izin: all/web/read/chat */
|
|
2568
2618
|
let perm = hit.perm || (hit.lockdown ? 'chat' : 'all');
|
|
2569
2619
|
engine.setSessionPerm(sid, perm);
|
|
@@ -2686,6 +2736,8 @@ function dcFind(senderId, username) {
|
|
|
2686
2736
|
if (Array.isArray(arr)) dcHistory.set(c, arr.filter((x) => typeof x === 'string').slice(-DC_HISTORY_CAP));
|
|
2687
2737
|
}
|
|
2688
2738
|
}
|
|
2739
|
+
/* kanal tek oturumu: kayıtlı aktif id (geçersizse ensure yeniden seçer) */
|
|
2740
|
+
if (raw && typeof raw.active === 'string' && raw.active) dcSingleSid = raw.active;
|
|
2689
2741
|
for (const [c, s] of dcChats.entries()) {
|
|
2690
2742
|
const h = dcHistory.get(c) || [];
|
|
2691
2743
|
if (!h.includes(s)) h.push(s);
|
|
@@ -2701,6 +2753,7 @@ function saveDcChats() {
|
|
|
2701
2753
|
JSON.stringify({
|
|
2702
2754
|
chats: Object.fromEntries(dcChats),
|
|
2703
2755
|
history: Object.fromEntries([...dcHistory.entries()].map(([c, a]) => [c, a.slice(-DC_HISTORY_CAP)])),
|
|
2756
|
+
active: dcSingleSid || '',
|
|
2704
2757
|
})
|
|
2705
2758
|
);
|
|
2706
2759
|
} catch {}
|
|
@@ -2767,21 +2820,14 @@ async function processDcMessage(channelId, payload) {
|
|
|
2767
2820
|
dcLog(`skip flush: izinli eşleşme yok (sender=${payload.senderId || '?'})`);
|
|
2768
2821
|
return;
|
|
2769
2822
|
}
|
|
2770
|
-
let sid = dcChats.get(channelId);
|
|
2823
|
+
let sid = dcChats.get(channelId) || dcSingleSid;
|
|
2771
2824
|
if (sid && engine.isBusy(sid)) {
|
|
2772
2825
|
/* oturum meşgul — WA/TG ile aynı: kaybetme, iş bitene dek yeniden dene */
|
|
2773
2826
|
await new Promise((r) => setTimeout(r, DC_DEBOUNCE_MS));
|
|
2774
2827
|
return processDcMessage(channelId, payload, 1);
|
|
2775
2828
|
}
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
sid = v.id;
|
|
2779
|
-
dcChats.set(channelId, sid);
|
|
2780
|
-
dcRememberSession(channelId, sid);
|
|
2781
|
-
saveDcChats();
|
|
2782
|
-
} else {
|
|
2783
|
-
dcRememberSession(channelId, sid);
|
|
2784
|
-
}
|
|
2829
|
+
/* KANAL TEK OTURUMU: eskisi silinmedikçe hep aynı oturumdan devam */
|
|
2830
|
+
sid = ensureDcSession(channelId);
|
|
2785
2831
|
/* Kişi bazlı granül izin: all/web/read/chat */
|
|
2786
2832
|
let perm = hit.perm || (hit.lockdown ? 'chat' : 'all');
|
|
2787
2833
|
engine.setSessionPerm(sid, perm);
|
|
@@ -3404,7 +3450,7 @@ function isDevServerUrl(url) {
|
|
|
3404
3450
|
/* Tarayıcı state: visible=false → ajanlar GİZLİ kullanır (headless);
|
|
3405
3451
|
göz ikonuyla görünür mod açılır. open=view aktif, visible=panelde görünürlük */
|
|
3406
3452
|
const browser = { view: null, open: false, visible: false, width: 0, attached: false, started: false, phone: false, mobile: false, mobileRect: null, deviceKey: 'iphone14', bottomInset: 0, desktopUA: '' };
|
|
3407
|
-
browser.mobile =
|
|
3453
|
+
browser.mobile = false; // mobil önizleme (telefon silueti) şimdilik devre dışı
|
|
3408
3454
|
if (PHONE_DEVICES[settings.browserDevice]) browser.deviceKey = settings.browserDevice;
|
|
3409
3455
|
|
|
3410
3456
|
function browserEmit(payload) {
|
|
@@ -4584,19 +4630,37 @@ function resyncBrowserUi() {
|
|
|
4584
4630
|
}
|
|
4585
4631
|
}
|
|
4586
4632
|
|
|
4587
|
-
win.on('resize',
|
|
4633
|
+
win.on('resize', () => {
|
|
4634
|
+
layoutBrowser();
|
|
4635
|
+
/* resize sürerken son boyutu yakala: maximize/restore bitiminde dock KESİN
|
|
4636
|
+
yeni pencere boyutuna otursun (BrowserView bayat bounds bırakmasın) */
|
|
4637
|
+
clearTimeout(win._bzRzT);
|
|
4638
|
+
win._bzRzT = setTimeout(() => { try { layoutBrowser(); } catch {} }, 120);
|
|
4639
|
+
});
|
|
4588
4640
|
win.on('maximize', () => {
|
|
4589
4641
|
layoutBrowser();
|
|
4590
4642
|
resyncBrowserUi();
|
|
4643
|
+
setTimeout(() => { try { layoutBrowser(); resyncBrowserUi(); } catch {} }, 80);
|
|
4644
|
+
setTimeout(() => { try { layoutBrowser(); resyncBrowserUi(); } catch {} }, 300);
|
|
4591
4645
|
try { if (win && !win.isDestroyed()) win.webContents.send('agent:event', { type: 'win-max', maximized: true }); } catch {}
|
|
4592
4646
|
});
|
|
4593
4647
|
win.on('unmaximize', () => {
|
|
4594
4648
|
layoutBrowser();
|
|
4595
4649
|
resyncBrowserUi();
|
|
4650
|
+
setTimeout(() => { try { layoutBrowser(); resyncBrowserUi(); } catch {} }, 80);
|
|
4651
|
+
setTimeout(() => { try { layoutBrowser(); resyncBrowserUi(); } catch {} }, 300);
|
|
4596
4652
|
try { if (win && !win.isDestroyed()) win.webContents.send('agent:event', { type: 'win-max', maximized: false }); } catch {}
|
|
4597
4653
|
});
|
|
4598
|
-
win.on('enter-full-screen', () => {
|
|
4599
|
-
|
|
4654
|
+
win.on('enter-full-screen', () => {
|
|
4655
|
+
layoutBrowser(); resyncBrowserUi();
|
|
4656
|
+
setTimeout(() => { try { layoutBrowser(); resyncBrowserUi(); } catch {} }, 80);
|
|
4657
|
+
setTimeout(() => { try { layoutBrowser(); resyncBrowserUi(); } catch {} }, 300);
|
|
4658
|
+
});
|
|
4659
|
+
win.on('leave-full-screen', () => {
|
|
4660
|
+
layoutBrowser(); resyncBrowserUi();
|
|
4661
|
+
setTimeout(() => { try { layoutBrowser(); resyncBrowserUi(); } catch {} }, 80);
|
|
4662
|
+
setTimeout(() => { try { layoutBrowser(); resyncBrowserUi(); } catch {} }, 300);
|
|
4663
|
+
});
|
|
4600
4664
|
win.on('show', layoutBrowser);
|
|
4601
4665
|
// X'e basınca gizle — tepside yaşamaya devam, WhatsApp bağlantısı sürer
|
|
4602
4666
|
win.on('close', (e) => {
|
|
@@ -6201,9 +6265,10 @@ function empatiCfg() {
|
|
|
6201
6265
|
return empati.mergeCfg(settings.empati || {});
|
|
6202
6266
|
}
|
|
6203
6267
|
|
|
6204
|
-
/* EMPATİ HAFIZASI: sohbet akışını kaydet
|
|
6205
|
-
- user mesajı → hafızaya yaz
|
|
6206
|
-
|
|
6268
|
+
/* EMPATİ HAFIZASI: sohbet akışını kaydet (ilgi çıkarımının ham verisi).
|
|
6269
|
+
- user/assistant mesajı → hafızaya yaz (konuşmanın iki yanı da kalsın)
|
|
6270
|
+
İlgi alanları burada MESAJ BAŞINA öğrenilmez — gece yansımasında
|
|
6271
|
+
(günde bir) LLM bu birikimden konu etiketleri çıkarır (nightref adım 3b).
|
|
6207
6272
|
Beast Code/Studio iş mesajları, /komutlar ve bağlam enjeksiyonları kayda girmez. */
|
|
6208
6273
|
function empatiRememberFromEvent(ev) {
|
|
6209
6274
|
if (!ev || ev.type !== 'message' || !ev.message || !ev.message.role) return;
|
|
@@ -6222,7 +6287,6 @@ function empatiRememberFromEvent(ev) {
|
|
|
6222
6287
|
if (bc) return; /* kod işi — ilgi alanını bulanıklaştırır */
|
|
6223
6288
|
if (m.role === 'user') {
|
|
6224
6289
|
empati.rememberConversation(txt, 'sohbet');
|
|
6225
|
-
empati.learnInterests(txt);
|
|
6226
6290
|
} else {
|
|
6227
6291
|
empati.rememberConversation(txt, 'beast');
|
|
6228
6292
|
}
|
|
@@ -6261,7 +6325,9 @@ async function empatiSignalSelf() {
|
|
|
6261
6325
|
}
|
|
6262
6326
|
|
|
6263
6327
|
async function empatiSignalNews() {
|
|
6264
|
-
|
|
6328
|
+
/* haber konuları İlgi Alanları'ndan OTOMATİK türetilir — seçime gerek yok */
|
|
6329
|
+
const topics = String(empati.combinedInterests(empatiCfg()) || '')
|
|
6330
|
+
.split(',').map((s) => s.trim()).filter((s) => s.length > 2);
|
|
6265
6331
|
if (!topics.length) return [];
|
|
6266
6332
|
return empati.fetchNews(topics);
|
|
6267
6333
|
}
|
|
@@ -6309,6 +6375,22 @@ function empatiLlmCompose(prompt) {
|
|
|
6309
6375
|
KENDİSİNİN attığını bilir — aynı oturum, kesintisiz bağlam. */
|
|
6310
6376
|
const PROACTIVE_MARK = '🫡 *Beast proaktif:*';
|
|
6311
6377
|
|
|
6378
|
+
/* bildirimin ALTINA YAZILAN KAYNAK: haberin gerçek linki varsa o, yoksa kaynak adı.
|
|
6379
|
+
Kullanıcı "bu proje neymiş?" diye sorduğunda linkten bulabilsin.
|
|
6380
|
+
TEK SATIR kuralı: satır sonu/boşluklar temizlenir, uzunsa sona "..." gelir. */
|
|
6381
|
+
function empatiSourceLine(ev) {
|
|
6382
|
+
if (!ev) return '';
|
|
6383
|
+
const oneLine = (s) =>
|
|
6384
|
+
String(s || '').replace(/\s*\n+\s*/g, ' ').replace(/\s{2,}/g, ' ').trim();
|
|
6385
|
+
const ELLIPSIS = '...';
|
|
6386
|
+
const cap = (s, max) =>
|
|
6387
|
+
oneLine(s).length > max ? oneLine(s).slice(0, max - ELLIPSIS.length) + ELLIPSIS : oneLine(s);
|
|
6388
|
+
const url = oneLine(ev.url);
|
|
6389
|
+
if (/^https?:\/\//i.test(url)) return '🔗 ' + cap(url, 100);
|
|
6390
|
+
const src = oneLine(ev.source);
|
|
6391
|
+
return src ? '🔗 kaynak: ' + cap(src, 80) : '';
|
|
6392
|
+
}
|
|
6393
|
+
|
|
6312
6394
|
function empatiInjectToSession(sid, out) {
|
|
6313
6395
|
try {
|
|
6314
6396
|
if (!sid || engine.isBusy(sid)) return; /* tur ortasında geçmişi karıştırma — bildirim kanala zaten gitti */
|
|
@@ -6316,28 +6398,88 @@ function empatiInjectToSession(sid, out) {
|
|
|
6316
6398
|
} catch {}
|
|
6317
6399
|
}
|
|
6318
6400
|
|
|
6319
|
-
/*
|
|
6401
|
+
/* kanala giden metin + Beast'in İÇ bağlamı ayrıdır: kullanıcı linki silse bile
|
|
6402
|
+
model olayın başlığını, detayını ve linkini KENDİSİ görür — "bu neymiş?"
|
|
6403
|
+
sorusuna insansı cevap verebilir */
|
|
6404
|
+
function empatiInjectText(ev, out) {
|
|
6405
|
+
if (!ev) return out;
|
|
6406
|
+
return (
|
|
6407
|
+
out + '\n\n[BAĞLAM — kullanıcı bu bildirimi sorarsa bununla cevapla]\n' +
|
|
6408
|
+
'Olay: ' + String(ev.title || '').slice(0, 200) + '\n' +
|
|
6409
|
+
(ev.detail ? 'Detay: ' + String(ev.detail).slice(0, 200) + '\n' : '') +
|
|
6410
|
+
(ev.url ? 'Link: ' + String(ev.url) + '\n' : '') +
|
|
6411
|
+
'Kaynak: ' + String(ev.source || '').slice(0, 80)
|
|
6412
|
+
);
|
|
6413
|
+
}
|
|
6414
|
+
|
|
6415
|
+
/* kanalın yaşayan tek oturumu (WA kuralının aynısı — Telegram/Discord) */
|
|
6320
6416
|
function ensureTgSession(chatId) {
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
|
|
6417
|
+
if (!tgSingleSid || !sessionFileAlive(tgSingleSid)) {
|
|
6418
|
+
let best = '';
|
|
6419
|
+
let bestTs = '';
|
|
6420
|
+
for (const c of new Set([...tgChats.values(), tgSingleSid])) {
|
|
6421
|
+
if (!c || !sessionFileAlive(c)) continue;
|
|
6422
|
+
let ts = '';
|
|
6423
|
+
try {
|
|
6424
|
+
const s = engine.cache.get(c) || engine._load(c);
|
|
6425
|
+
ts = String((s && s.updatedAt) || '');
|
|
6426
|
+
} catch {}
|
|
6427
|
+
if (!best || ts > bestTs) {
|
|
6428
|
+
best = c;
|
|
6429
|
+
bestTs = ts;
|
|
6430
|
+
}
|
|
6431
|
+
}
|
|
6432
|
+
tgSingleSid = best || engine.createSession().id;
|
|
6327
6433
|
saveTgChats();
|
|
6328
6434
|
}
|
|
6329
|
-
|
|
6435
|
+
let dirty = false;
|
|
6436
|
+
for (const [c, s] of tgChats.entries()) {
|
|
6437
|
+
if (s !== tgSingleSid) {
|
|
6438
|
+
tgChats.set(c, tgSingleSid);
|
|
6439
|
+
dirty = true;
|
|
6440
|
+
}
|
|
6441
|
+
}
|
|
6442
|
+
if (chatId != null && tgChats.get(String(chatId)) !== tgSingleSid) {
|
|
6443
|
+
tgChats.set(String(chatId), tgSingleSid);
|
|
6444
|
+
dirty = true;
|
|
6445
|
+
}
|
|
6446
|
+
tgRememberSession(String(chatId), tgSingleSid);
|
|
6447
|
+
if (dirty) saveTgChats();
|
|
6448
|
+
return tgSingleSid;
|
|
6330
6449
|
}
|
|
6331
6450
|
function ensureDcSession(channelId) {
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6451
|
+
if (!dcSingleSid || !sessionFileAlive(dcSingleSid)) {
|
|
6452
|
+
let best = '';
|
|
6453
|
+
let bestTs = '';
|
|
6454
|
+
for (const c of new Set([...dcChats.values(), dcSingleSid])) {
|
|
6455
|
+
if (!c || !sessionFileAlive(c)) continue;
|
|
6456
|
+
let ts = '';
|
|
6457
|
+
try {
|
|
6458
|
+
const s = engine.cache.get(c) || engine._load(c);
|
|
6459
|
+
ts = String((s && s.updatedAt) || '');
|
|
6460
|
+
} catch {}
|
|
6461
|
+
if (!best || ts > bestTs) {
|
|
6462
|
+
best = c;
|
|
6463
|
+
bestTs = ts;
|
|
6464
|
+
}
|
|
6465
|
+
}
|
|
6466
|
+
dcSingleSid = best || engine.createSession().id;
|
|
6338
6467
|
saveDcChats();
|
|
6339
6468
|
}
|
|
6340
|
-
|
|
6469
|
+
let dirty = false;
|
|
6470
|
+
for (const [c, s] of dcChats.entries()) {
|
|
6471
|
+
if (s !== dcSingleSid) {
|
|
6472
|
+
dcChats.set(c, dcSingleSid);
|
|
6473
|
+
dirty = true;
|
|
6474
|
+
}
|
|
6475
|
+
}
|
|
6476
|
+
if (channelId != null && dcChats.get(String(channelId)) !== dcSingleSid) {
|
|
6477
|
+
dcChats.set(String(channelId), dcSingleSid);
|
|
6478
|
+
dirty = true;
|
|
6479
|
+
}
|
|
6480
|
+
dcRememberSession(String(channelId), dcSingleSid);
|
|
6481
|
+
if (dirty) saveDcChats();
|
|
6482
|
+
return dcSingleSid;
|
|
6341
6483
|
}
|
|
6342
6484
|
|
|
6343
6485
|
/* Masaüstü yedeği: en güncel (bg/bot-DM'siz, meşgul olmayan) sohbet — yoksa yeni */
|
|
@@ -6354,16 +6496,18 @@ function empatiDesktopSid() {
|
|
|
6354
6496
|
Hiçbir entegrasyon yazılamazsa masaüstü chat UI (toast) kalır. */
|
|
6355
6497
|
function empatiNotify(text, ev) {
|
|
6356
6498
|
const cfg = empatiCfg();
|
|
6499
|
+
const src = empatiSourceLine(ev);
|
|
6500
|
+
const out = PROACTIVE_MARK + '\n' + text + (src ? '\n' + src : '');
|
|
6501
|
+
const inject = empatiInjectText(ev, out);
|
|
6357
6502
|
const senders = [];
|
|
6358
6503
|
const tryWa = () => {
|
|
6359
6504
|
try {
|
|
6360
6505
|
const own = waOwnerNum();
|
|
6361
6506
|
if (own && wa && wa.connected) {
|
|
6362
6507
|
const jid = own + '@s.whatsapp.net';
|
|
6363
|
-
const out = PROACTIVE_MARK + '\n' + text;
|
|
6364
6508
|
senders.push(() =>
|
|
6365
6509
|
Promise.resolve(sendWaSafe(jid, out))
|
|
6366
|
-
.then(() => empatiInjectToSession(ensureWaSession(jid),
|
|
6510
|
+
.then(() => empatiInjectToSession(ensureWaSession(jid), inject))
|
|
6367
6511
|
.catch(() => {})
|
|
6368
6512
|
);
|
|
6369
6513
|
}
|
|
@@ -6372,11 +6516,10 @@ function empatiNotify(text, ev) {
|
|
|
6372
6516
|
const tryTg = () => {
|
|
6373
6517
|
try {
|
|
6374
6518
|
if (tg && tg.connected) {
|
|
6375
|
-
const out = PROACTIVE_MARK + '\n' + text;
|
|
6376
6519
|
for (const id of tgOwnerIds()) {
|
|
6377
6520
|
senders.push(() =>
|
|
6378
6521
|
Promise.resolve(sendTgSafe(id, out))
|
|
6379
|
-
.then(() => empatiInjectToSession(ensureTgSession(String(id)),
|
|
6522
|
+
.then(() => empatiInjectToSession(ensureTgSession(String(id)), inject))
|
|
6380
6523
|
.catch(() => {})
|
|
6381
6524
|
);
|
|
6382
6525
|
}
|
|
@@ -6386,11 +6529,11 @@ function empatiNotify(text, ev) {
|
|
|
6386
6529
|
const tryDc = () => {
|
|
6387
6530
|
try {
|
|
6388
6531
|
if (dc && dc.connected) {
|
|
6389
|
-
const
|
|
6532
|
+
const outDc = out.replace('🫡 *Beast proaktif:*', '🫡 **Beast proaktif:**');
|
|
6390
6533
|
for (const id of dcOwnerIds()) {
|
|
6391
6534
|
senders.push(() =>
|
|
6392
|
-
Promise.resolve(sendDcSafe(id,
|
|
6393
|
-
.then(() => empatiInjectToSession(ensureDcSession(String(id)),
|
|
6535
|
+
Promise.resolve(sendDcSafe(id, outDc))
|
|
6536
|
+
.then(() => empatiInjectToSession(ensureDcSession(String(id)), inject))
|
|
6394
6537
|
.catch(() => {})
|
|
6395
6538
|
);
|
|
6396
6539
|
}
|
|
@@ -6409,8 +6552,8 @@ function empatiNotify(text, ev) {
|
|
|
6409
6552
|
metin güncel sohbete de asistan mesajı olarak işlenir */
|
|
6410
6553
|
try {
|
|
6411
6554
|
if (!sent && win && !win.isDestroyed()) {
|
|
6412
|
-
empatiInjectToSession(empatiDesktopSid(),
|
|
6413
|
-
win.webContents.send('agent:event', { type: 'proactive', id: ev.id, level: ev.level, title: ev.title, text });
|
|
6555
|
+
empatiInjectToSession(empatiDesktopSid(), inject);
|
|
6556
|
+
win.webContents.send('agent:event', { type: 'proactive', id: ev.id, level: ev.level, title: ev.title, text: out });
|
|
6414
6557
|
}
|
|
6415
6558
|
} catch {}
|
|
6416
6559
|
}
|
|
@@ -6798,7 +6941,8 @@ function termShellSpawn() {
|
|
|
6798
6941
|
}
|
|
6799
6942
|
|
|
6800
6943
|
ipcMain.handle('terminal:toggle', () => {
|
|
6801
|
-
|
|
6944
|
+
/* terminal artık tarayıcıyla AYNI alanı paylaşmıyor (Beast Code'da kod
|
|
6945
|
+
bölmesinde) — açılışı/kapanışı tarayıcıya DOKUNMAZ */
|
|
6802
6946
|
return { ok: true, cwd: termShellCwd || (engine && engine.workspace) || settings.workspace || app.getPath('home') };
|
|
6803
6947
|
});
|
|
6804
6948
|
|
|
@@ -6895,11 +7039,23 @@ function bcGetSession(folder) {
|
|
|
6895
7039
|
JSON.stringify({ t: 'meta2', bgOf: '', title: 'Beast Code', at: new Date().toISOString() }) + '\n'
|
|
6896
7040
|
);
|
|
6897
7041
|
} catch {}
|
|
7042
|
+
bcMarkWs(s, folder);
|
|
6898
7043
|
engine.cache.set(s.id, s);
|
|
6899
7044
|
bcSessions.set(folder, s.id);
|
|
6900
7045
|
return s;
|
|
6901
7046
|
}
|
|
6902
7047
|
|
|
7048
|
+
/* Beast Code oturumuna çalışma klasörünü işle: sohbet geçmişi listesinde
|
|
7049
|
+
hangi klasörde çalışıldığı görünür; oturum tekrar açılınca aynı klasöre
|
|
7050
|
+
bağlanır. Kayıt oturum dosyasına bcws satırı olarak YAZILIR. */
|
|
7051
|
+
function bcMarkWs(s, folder) {
|
|
7052
|
+
try {
|
|
7053
|
+
if (s.bcWs === folder) return;
|
|
7054
|
+
s.bcWs = folder;
|
|
7055
|
+
fs.appendFileSync(engine._file(s.id), JSON.stringify({ t: 'bcws', ws: folder, at: new Date().toISOString() }) + '\n');
|
|
7056
|
+
} catch {}
|
|
7057
|
+
}
|
|
7058
|
+
|
|
6903
7059
|
/* Beast Code motoru: TAMAMEN BEAST MOTORU — opencode'in döngü mantığı
|
|
6904
7060
|
(compaction, prune, prompt-cache, doom-loop, yetim onarım, proje
|
|
6905
7061
|
talimatları) engine.js'e native port edildi; köprü/alt süreç yok. */
|
|
@@ -7071,6 +7227,85 @@ ipcMain.handle('beastcode:new', async () => {
|
|
|
7071
7227
|
return { ok: true };
|
|
7072
7228
|
});
|
|
7073
7229
|
|
|
7230
|
+
/* ---------------- Beast Code SOHBET GEÇMİŞİ ----------------
|
|
7231
|
+
Soldaki dosya panelinin alt yarısında eski Beast Code oturumları listelenir.
|
|
7232
|
+
Ana sohbet geçmişinden (bgTitle gizli oturumlar) ve Studio'dan TAMAMEN AYRIDIR.
|
|
7233
|
+
Oturuma tıklayınca panele açılır, kaldığı yerden devam edilir. */
|
|
7234
|
+
ipcMain.handle('bc:history', async () => {
|
|
7235
|
+
try {
|
|
7236
|
+
return { ok: true, items: engine.listBcSessions(100) };
|
|
7237
|
+
} catch (e) {
|
|
7238
|
+
return { ok: false, error: String((e && e.message) || e), items: [] };
|
|
7239
|
+
}
|
|
7240
|
+
});
|
|
7241
|
+
|
|
7242
|
+
function bcMsgText(m) {
|
|
7243
|
+
const t = Array.isArray(m && m.content)
|
|
7244
|
+
? m.content.filter((p) => p && p.type === 'text').map((p) => String(p.text || '')).join('\n')
|
|
7245
|
+
: String((m && m.content) || '');
|
|
7246
|
+
return t.replace(/\s+/g, ' ').trim();
|
|
7247
|
+
}
|
|
7248
|
+
|
|
7249
|
+
ipcMain.handle('bc:open', async (_e, payload) => {
|
|
7250
|
+
const id = String((payload && payload.id) || '');
|
|
7251
|
+
if (!engine) return { ok: false, error: 'ajan hazır değil' };
|
|
7252
|
+
if (!id) return { ok: false, error: 'oturum belirtilmedi' };
|
|
7253
|
+
let s;
|
|
7254
|
+
try { s = engine._load(id); } catch { return { ok: false, error: 'oturum açılamadı' }; }
|
|
7255
|
+
if (s.bgTitle && s.bgTitle !== 'Beast Code') return { ok: false, error: 'bu oturum Beast Code oturumu değil' };
|
|
7256
|
+
/* mevcut klasöre bağlan: sonraki mesajlar BU oturumda sürer */
|
|
7257
|
+
const ws = ideRoot();
|
|
7258
|
+
s.workspace = ws;
|
|
7259
|
+
s.bcCode = true;
|
|
7260
|
+
bcMarkWs(s, ws);
|
|
7261
|
+
engine.cache.set(s.id, s);
|
|
7262
|
+
bcSessions.set(ws, s.id);
|
|
7263
|
+
const msgs = [];
|
|
7264
|
+
for (const m of s.messages || []) {
|
|
7265
|
+
if (m.tool_calls) continue;
|
|
7266
|
+
const txt = bcMsgText(m);
|
|
7267
|
+
if (!txt) continue;
|
|
7268
|
+
msgs.push({ role: m.role === 'assistant' ? 'assistant' : 'user', text: txt.slice(0, 4000) });
|
|
7269
|
+
}
|
|
7270
|
+
return {
|
|
7271
|
+
ok: true,
|
|
7272
|
+
sessionId: s.id,
|
|
7273
|
+
busy: !!engine.isBusy(s.id),
|
|
7274
|
+
mode: s.bcMode || '',
|
|
7275
|
+
messages: msgs.slice(-200),
|
|
7276
|
+
};
|
|
7277
|
+
});
|
|
7278
|
+
|
|
7279
|
+
/* TEK oturum silme (soldaki geçmiş listesindeki × butonu) */
|
|
7280
|
+
ipcMain.handle('bc:delete', async (_e, payload) => {
|
|
7281
|
+
const id = String((payload && payload.id) || '');
|
|
7282
|
+
if (!engine || !id) return { ok: false, error: 'oturum belirtilmedi' };
|
|
7283
|
+
let s;
|
|
7284
|
+
try { s = engine._load(id); } catch { return { ok: false, error: 'oturum açılamadı' }; }
|
|
7285
|
+
if (s.bgTitle && s.bgTitle !== 'Beast Code') return { ok: false, error: 'yalnız Beast Code oturumu silinir' };
|
|
7286
|
+
if (engine.isBusy(id)) return { ok: false, error: 'oturum çalışıyor — önce ■ ile durdur' };
|
|
7287
|
+
for (const [folder, sid] of [...bcSessions.entries()]) {
|
|
7288
|
+
if (String(sid) === id) bcSessions.delete(folder);
|
|
7289
|
+
}
|
|
7290
|
+
try { engine.deleteSession(id); } catch {}
|
|
7291
|
+
return { ok: true };
|
|
7292
|
+
});
|
|
7293
|
+
|
|
7294
|
+
/* TÜM Beast Code oturumlarını sil — çalışanlar atlanır */
|
|
7295
|
+
ipcMain.handle('bc:deleteAll', async () => {
|
|
7296
|
+
if (!engine) return { ok: false, error: 'ajan hazır değil' };
|
|
7297
|
+
let deleted = 0;
|
|
7298
|
+
let skipped = 0;
|
|
7299
|
+
for (const it of engine.listBcSessions(200)) {
|
|
7300
|
+
if (engine.isBusy(it.id)) { skipped++; continue; }
|
|
7301
|
+
for (const [folder, sid] of [...bcSessions.entries()]) {
|
|
7302
|
+
if (String(sid) === it.id) bcSessions.delete(folder);
|
|
7303
|
+
}
|
|
7304
|
+
try { engine.deleteSession(it.id); deleted++; } catch {}
|
|
7305
|
+
}
|
|
7306
|
+
return { ok: true, deleted, skipped };
|
|
7307
|
+
});
|
|
7308
|
+
|
|
7074
7309
|
/* ---------------- Beast Studio paneli (video yapma/düzenleme modu) ----------------
|
|
7075
7310
|
Beast Code ile AYRI ve ÖZEL dünya: kendi çalışma klasörü (studioRoot), kendi
|
|
7076
7311
|
gizli engine oturumları (klasör bazlı), kendi sohbet kuyruğu. Studio
|
|
@@ -7901,27 +8136,8 @@ ipcMain.handle('ide:previewFile', async (_e, rel) => {
|
|
|
7901
8136
|
ipcMain.handle('ide:preview', async () => {
|
|
7902
8137
|
try {
|
|
7903
8138
|
const root = ideRoot();
|
|
7904
|
-
/* MOBİL
|
|
7905
|
-
|
|
7906
|
-
const mob = ideMobileProject(root);
|
|
7907
|
-
if (mob.mobile) {
|
|
7908
|
-
let url = '';
|
|
7909
|
-
/* ajanın kendi dev sunucusu canlıysa öncelikli */
|
|
7910
|
-
if (bcLastServerUrl && isDevServerUrl(bcLastServerUrl)) {
|
|
7911
|
-
const alive = await probeDevUrl(bcLastServerUrl, 800).catch(() => false);
|
|
7912
|
-
if (alive) url = bcLastServerUrl;
|
|
7913
|
-
}
|
|
7914
|
-
if (!url) {
|
|
7915
|
-
const r = await mobilePreviewStart(root);
|
|
7916
|
-
if (!r.ok) return { ok: false, error: r.error };
|
|
7917
|
-
url = r.url;
|
|
7918
|
-
}
|
|
7919
|
-
setBrowserMobile(true); /* siluet + görünür tarayıcı */
|
|
7920
|
-
try { browser.view.webContents.loadURL(url).catch(() => {}); } catch {}
|
|
7921
|
-
browserEmit({ open: true, width: browserShownWidth(browserW()), url, mobile: true, phoneRect: browser.mobileRect });
|
|
7922
|
-
bcTellMobileServe(url);
|
|
7923
|
-
return { ok: true, url, mobile: true };
|
|
7924
|
-
}
|
|
8139
|
+
/* MOBİL ÖNİZLEME kaldırıldı: mobil projeler de normal tarayıcı dock'unda
|
|
8140
|
+
açılır — ajanın dev sunucusu varsa o adres, yoksa dahili statik sunucu. */
|
|
7925
8141
|
const pick = (name) => {
|
|
7926
8142
|
const p = path.join(root, name);
|
|
7927
8143
|
try { return fs.existsSync(p) ? p : null; } catch { return null; }
|
|
@@ -7982,10 +8198,7 @@ ipcMain.handle('ide:previewUrl', async (_e, url) => {
|
|
|
7982
8198
|
} else {
|
|
7983
8199
|
return { ok: false, error: 'yalnız localhost adresleri önizlenebilir' };
|
|
7984
8200
|
}
|
|
7985
|
-
/*
|
|
7986
|
-
if (/^https?:\/\/(?:localhost|127\.0\.0\.1):(8081|19000|19001|19002|3000|5173)\//i.test(target)) {
|
|
7987
|
-
if (!browser.phone) setBrowserPhone(true);
|
|
7988
|
-
}
|
|
8201
|
+
/* mobil önizleme otomatik telefon modu kaldırıldı — önizleme normal dockta açılır */
|
|
7989
8202
|
/* forceVisible: otomatik ve GÖRÜNÜR açılır */
|
|
7990
8203
|
setBrowserOpen(true, true);
|
|
7991
8204
|
browser.view.webContents.loadURL(target).catch(() => {});
|