beast-agent 0.24.5 → 0.25.1
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 +68 -96
- package/src/agent/tools.js +1 -1
- package/src/main.js +226 -60
- package/src/preload.js +1 -1
- package/src/renderer/i18n.js +2 -4
- package/src/renderer/index.html +45 -9
- package/src/renderer/renderer.js +351 -143
- package/src/renderer/style.css +195 -30
package/src/main.js
CHANGED
|
@@ -620,29 +620,29 @@ function emitWaEventSafe(ev) {
|
|
|
620
620
|
function waSlashHelp() {
|
|
621
621
|
return [
|
|
622
622
|
'*Beast komutları*',
|
|
623
|
-
'•
|
|
624
|
-
'•
|
|
625
|
-
'•
|
|
626
|
-
'•
|
|
627
|
-
'•
|
|
628
|
-
'•
|
|
629
|
-
'•
|
|
630
|
-
'•
|
|
631
|
-
'•
|
|
632
|
-
'•
|
|
633
|
-
'•
|
|
634
|
-
'•
|
|
635
|
-
'•
|
|
636
|
-
'•
|
|
637
|
-
'•
|
|
638
|
-
'•
|
|
639
|
-
'•
|
|
640
|
-
'•
|
|
641
|
-
'•
|
|
642
|
-
'•
|
|
643
|
-
'•
|
|
644
|
-
'•
|
|
645
|
-
'•
|
|
623
|
+
'• */help* – bu liste',
|
|
624
|
+
'• */new* – yeni oturum aç (kod verilir)',
|
|
625
|
+
'• */open* <kod> – o koddaki oturuma geç',
|
|
626
|
+
'• */sessions* – bu sohbetin oturumları',
|
|
627
|
+
'• */stop* – koşan işleri durdur (ajanlar+turlar; cron/izleyici/olay sürer)',
|
|
628
|
+
'• */start* – durdurulan servisleri devam ettir',
|
|
629
|
+
'• */restart* – uygulamayı yeniden başlat',
|
|
630
|
+
'• */change* – modelleri listele (*/change 5* ile 5.modele geç)',
|
|
631
|
+
'• */notes* – bu oturumun notlarını göster',
|
|
632
|
+
'• */notify* on|off – hata mail bildirimini aç/kapa',
|
|
633
|
+
'• */think* <0-5> – düşünme seviyesi (0 kapalı · 1 low · 2 medium · 3 high · 4 xhigh · 5 max)',
|
|
634
|
+
'• */clear* – bu oturumun geçmişini temizle',
|
|
635
|
+
'• */screenshot* – masaüstü ekran görüntüsünü gönder',
|
|
636
|
+
'• */rule* <metin> – kalıcı kural ekle (*/rules*: liste)',
|
|
637
|
+
'• */allow* <isim> <numara> – WhatsApp allow listesine kişi ekle (örn: /allow batu 905414178456)',
|
|
638
|
+
'• */block* – allow listesini numaralarıyla listele (*/block 3*: 3. kişiyi çıkar; 1 = sahip, silinemez)',
|
|
639
|
+
'• */approve* – bekleyen riskli işlemi onayla (*/approve always*: bir daha sorulmasın · */deny*: reddet)',
|
|
640
|
+
'• */update* – yeni sürüm kontrolü (*/update now*: indirileni hemen kur)',
|
|
641
|
+
'• */model* – aktif modeli göster (*/model* <isim> ile değiştir)',
|
|
642
|
+
'• */skills* – kurulu skill\u2019ler',
|
|
643
|
+
'• */usage* – bugünkü kullanım',
|
|
644
|
+
'• */backup* – tüm veriyi ŞİFRELİ yedekle (Beast Kodu imzalı, Masaüstü\\Beast-Backups)',
|
|
645
|
+
'• */status* – bağlantı ve servis durumu',
|
|
646
646
|
'',
|
|
647
647
|
'Gruplarda beni @mention ile çağır; ardışık mesajlarını tek cevapta birleştiririm.',
|
|
648
648
|
].join('\n');
|
|
@@ -2117,6 +2117,19 @@ function reloadBackend() {
|
|
|
2117
2117
|
}
|
|
2118
2118
|
} catch {}
|
|
2119
2119
|
}
|
|
2120
|
+
/* WA ara yorumları: ajanın araç çağrıları ARASINDAKİ açıklama metinleri
|
|
2121
|
+
("işe başlıyorum…" vb.) da WhatsApp'a gitsin. Son cevap 'done'da
|
|
2122
|
+
gönderildiği için burada yalnız tool_calls TAŞIYAN ara mesajlar alınır. */
|
|
2123
|
+
if (ev.type === 'message' && ev.message && ev.message.role === 'assistant' && wa && wa.connected) {
|
|
2124
|
+
const mtxt = typeof ev.message.content === 'string' ? ev.message.content.trim() : '';
|
|
2125
|
+
const isInterim = Array.isArray(ev.message.tool_calls) && ev.message.tool_calls.length > 0;
|
|
2126
|
+
if (mtxt && isInterim) {
|
|
2127
|
+
try {
|
|
2128
|
+
const hit = [...waChats.entries()].find(([, s]) => s === ev.sessionId);
|
|
2129
|
+
if (hit) sendWaSafe(hit[0], mtxt).catch(() => {});
|
|
2130
|
+
} catch {}
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2120
2133
|
/* #14 paralel ajan: arka plan oturumu bitince ana sohbete özet bas.
|
|
2121
2134
|
aborted (öz-kurtarma/wrap-up kick) turları BİTİŞ değildir — rapor basma */
|
|
2122
2135
|
if (ev.type === 'done' && ev.sessionId && !ev.aborted) {
|
|
@@ -2555,7 +2568,31 @@ function setBrowserOpen(v, forceVisible) {
|
|
|
2555
2568
|
browserEmit({ open: true, width: browser.width, url });
|
|
2556
2569
|
}
|
|
2557
2570
|
|
|
2571
|
+
/* --- Paralel ajan trafik düzeni: ajanlar aynı saniyede sorgu atınca Google
|
|
2572
|
+
"olağandışı trafik" uyarısı veriyor. Gezinme/arama isteklerini tek kuyrukta
|
|
2573
|
+
sıraya alıp aralarına min 1.2 sn + rastgele 0-600 ms jitter koyuyoruz.
|
|
2574
|
+
Kuyruğu tutan işin İÇİNDEN yapılan gezinmeler kapıyı atlar (kilitlenme olmaz). --- */
|
|
2575
|
+
const BROWSER_TRAFFIC_GAP = 1200;
|
|
2576
|
+
let __trafficLast = 0;
|
|
2577
|
+
let __trafficTail = Promise.resolve();
|
|
2578
|
+
function browserTrafficWait() {
|
|
2579
|
+
const wait = Math.max(0, __trafficLast + BROWSER_TRAFFIC_GAP + Math.floor(Math.random() * 600) - Date.now());
|
|
2580
|
+
__trafficLast = Date.now() + wait;
|
|
2581
|
+
return wait > 0 ? new Promise((r) => setTimeout(r, wait)) : Promise.resolve();
|
|
2582
|
+
}
|
|
2583
|
+
function browserGate(job) {
|
|
2584
|
+
const p = __trafficTail.then(job, job);
|
|
2585
|
+
__trafficTail = p.catch(() => {});
|
|
2586
|
+
return p;
|
|
2587
|
+
}
|
|
2558
2588
|
async function browserNavigate(raw, signal) {
|
|
2589
|
+
return browserGate(async () => {
|
|
2590
|
+
await browserTrafficWait();
|
|
2591
|
+
return browserNavigateNow(raw, signal);
|
|
2592
|
+
});
|
|
2593
|
+
}
|
|
2594
|
+
|
|
2595
|
+
async function browserNavigateNow(raw, signal) {
|
|
2559
2596
|
let url = String(raw || '').trim();
|
|
2560
2597
|
if (!url) return { ok: false, error: 'boş adres' };
|
|
2561
2598
|
if (!/^https?:\/\//i.test(url)) {
|
|
@@ -2585,7 +2622,21 @@ async function browserNavigate(raw, signal) {
|
|
|
2585
2622
|
try { title = wc.getTitle(); finalUrl = wc.getURL() || url; } catch {}
|
|
2586
2623
|
browserEmit({ open: true, width: browser.width, url: finalUrl });
|
|
2587
2624
|
flushBrowserStorage(); // oturum çerezleri diske — ani kapanışta kaybolmasın
|
|
2588
|
-
|
|
2625
|
+
/* açılışta snapshot da göm — model ayrı snapshot çağırmadan ref'lere başlar */
|
|
2626
|
+
let snap = null;
|
|
2627
|
+
try {
|
|
2628
|
+
const sraw = await wc.executeJavaScript(BROWSER_SNAPSHOT_JS, true);
|
|
2629
|
+
const sobj = JSON.parse(sraw);
|
|
2630
|
+
if (sobj && typeof sobj.count === 'number') snap = sobj;
|
|
2631
|
+
} catch {}
|
|
2632
|
+
return {
|
|
2633
|
+
ok: true,
|
|
2634
|
+
url: finalUrl,
|
|
2635
|
+
title,
|
|
2636
|
+
...(snap
|
|
2637
|
+
? { snapshot: snap.snapshot, refCount: snap.count, note: 'sayfa acildi — güncel snapshot hazır (' + snap.count + ' ref); ref numarasıyla browser_click/browser_type ile devam et' }
|
|
2638
|
+
: { note: 'sayfa acildi — etkileşimli elemanlar için browser_snapshot al' }),
|
|
2639
|
+
};
|
|
2589
2640
|
}
|
|
2590
2641
|
|
|
2591
2642
|
async function browserRead(signal) {
|
|
@@ -2650,6 +2701,14 @@ async function ocrRead({ image, lang = 'tur+eng' } = {}) {
|
|
|
2650
2701
|
yapmak (kullanıcının console'da yaptığı gibi) — sayfa bile değişmeden
|
|
2651
2702
|
DOMParser ile sonuç çekilir. Fetch olmazsa direk gezinme fallback'i var. */
|
|
2652
2703
|
async function browserSearch(query, signal) {
|
|
2704
|
+
/* paralel ajan sorguları trafik kapısından sırayla geçer */
|
|
2705
|
+
return browserGate(async () => {
|
|
2706
|
+
await browserTrafficWait();
|
|
2707
|
+
return browserSearchNow(query, signal);
|
|
2708
|
+
});
|
|
2709
|
+
}
|
|
2710
|
+
|
|
2711
|
+
async function browserSearchNow(query, signal) {
|
|
2653
2712
|
try {
|
|
2654
2713
|
if (!win || win.isDestroyed()) return null;
|
|
2655
2714
|
if (signal && signal.aborted) return null;
|
|
@@ -2663,7 +2722,7 @@ async function browserSearch(query, signal) {
|
|
|
2663
2722
|
let cur = '';
|
|
2664
2723
|
try { cur = wc.getURL() || ''; } catch {}
|
|
2665
2724
|
if (!cur.startsWith('https://www.google.com')) {
|
|
2666
|
-
await
|
|
2725
|
+
await browserNavigateNow('https://www.google.com/', signal);
|
|
2667
2726
|
}
|
|
2668
2727
|
if (!browser.view || !browser.open) return null;
|
|
2669
2728
|
|
|
@@ -2733,7 +2792,7 @@ async function browserSearch(query, signal) {
|
|
|
2733
2792
|
|
|
2734
2793
|
/* fallback: fetch yerine direk gezinme + DOM'dan çek */
|
|
2735
2794
|
if (!results.length) {
|
|
2736
|
-
await
|
|
2795
|
+
await browserNavigateNow(
|
|
2737
2796
|
'https://www.google.com/search?q=' + encodeURIComponent(q) + '&num=10&hl=tr&pws=0&aep=1',
|
|
2738
2797
|
signal
|
|
2739
2798
|
);
|
|
@@ -2789,7 +2848,14 @@ async function browserSearch(query, signal) {
|
|
|
2789
2848
|
results = parsed.rows || [];
|
|
2790
2849
|
}
|
|
2791
2850
|
|
|
2792
|
-
if (!results.length && !parsed.ai)
|
|
2851
|
+
if (!results.length && !parsed.ai) {
|
|
2852
|
+
/* CAPTCHA / olağandışı trafik sinyali — zincir TinyFish'e kaymalı */
|
|
2853
|
+
let blocked = false;
|
|
2854
|
+
try { blocked = /google\.com\/sorry/i.test(wc.getURL() || ''); } catch {}
|
|
2855
|
+
return blocked
|
|
2856
|
+
? { ok: false, blocked: true, engine: 'browser-google', query: q, error: 'unusual traffic (CAPTCHA)' }
|
|
2857
|
+
: null;
|
|
2858
|
+
}
|
|
2793
2859
|
flushBrowserStorage();
|
|
2794
2860
|
const out = { ok: true, engine: 'browser-google', query: q, results };
|
|
2795
2861
|
if (parsed.ai) out.ai = parsed.ai;
|
|
@@ -2853,26 +2919,37 @@ const BROWSER_JS_HELPERS = `
|
|
|
2853
2919
|
|
|
2854
2920
|
const BROWSER_SNAPSHOT_JS = `(function(){
|
|
2855
2921
|
${BROWSER_JS_HELPERS}
|
|
2856
|
-
const sel='a[href],button,input:not([type="hidden"]),textarea,select,[role="button"],[role="link"],[role="tab"],[contenteditable="true"],summary';
|
|
2857
|
-
|
|
2922
|
+
const sel='a[href],button,input:not([type="hidden"]),textarea,select,[role="button"],[role="link"],[role="tab"],[role="option"],[role="menuitem"],[role="gridcell"],[role="checkbox"],[role="switch"],[role="combobox"],[role="textbox"],[role="searchbox"],[contenteditable="true"],summary';
|
|
2923
|
+
/* açık popup/takvim/dialog varsa içindekiler ÖNCE listelenir (tarih seçici, özel dropdown vb.) */
|
|
2924
|
+
const popSel='[role="dialog"],dialog,[role="listbox"],[role="menu"],.flatpickr-calendar,.ui-datepicker,[class*="datepicker" i],[class*="calendar" i],[class*="dropdown" i],[class*="popup" i]';
|
|
2925
|
+
const pops=[...document.querySelectorAll(popSel)].filter(__vis);
|
|
2926
|
+
const inPop=new Set();
|
|
2927
|
+
for(const p of pops){[...p.querySelectorAll(sel)].forEach(e=>inPop.add(e));}
|
|
2858
2928
|
window.__beMap={};
|
|
2929
|
+
const seen=new Set();
|
|
2859
2930
|
const lines=[];
|
|
2860
2931
|
let i=0;
|
|
2861
|
-
|
|
2862
|
-
if(!
|
|
2863
|
-
|
|
2932
|
+
function add(e){
|
|
2933
|
+
if(!e||seen.has(e)) return;
|
|
2934
|
+
seen.add(e);
|
|
2935
|
+
if(!__vis(e)||e.disabled||e.getAttribute('aria-disabled')==='true') return;
|
|
2864
2936
|
i++;
|
|
2865
2937
|
window.__beMap[i]=e;
|
|
2866
2938
|
const tag=e.tagName.toLowerCase();
|
|
2867
|
-
const type=e.getAttribute('type');
|
|
2939
|
+
const type=(e.getAttribute&&e.getAttribute('type'))||'';
|
|
2868
2940
|
let s='['+i+'] <'+tag+(type?' type='+type:'')+'>';
|
|
2869
2941
|
const l=__label(e);
|
|
2870
2942
|
if(l) s+=' "'+l+'"';
|
|
2871
|
-
if(tag==='input'
|
|
2943
|
+
if(tag==='input'&&/^(text|email|password|search|tel|url|number|date|time|month|datetime-local)$/.test(type)&&e.value) s+=' deger="'+String(e.value).slice(0,30)+'"';
|
|
2872
2944
|
if(tag==='select'){s+=' secenekler=['+[...e.options].slice(0,6).map(o=>o.text.trim()).filter(Boolean).join('|').slice(0,60)+']';}
|
|
2873
2945
|
lines.push(s);
|
|
2874
|
-
if(i>=100) break;
|
|
2875
2946
|
}
|
|
2947
|
+
if(inPop.size){
|
|
2948
|
+
lines.push('--- ACIK POPUP/TAKVIM ICINDEKILER (once bunlari kullan) ---');
|
|
2949
|
+
for(const e of inPop){ add(e); if(i>=60) break; }
|
|
2950
|
+
lines.push('--- SAYFA ---');
|
|
2951
|
+
}
|
|
2952
|
+
for(const e of document.querySelectorAll(sel)){ if(i>=100) break; add(e); }
|
|
2876
2953
|
return JSON.stringify({count:i,title:document.title,url:location.href,snapshot:lines.join('\\n')});
|
|
2877
2954
|
})()`;
|
|
2878
2955
|
|
|
@@ -2905,10 +2982,52 @@ function browserActionJs(kind, args) {
|
|
|
2905
2982
|
if (kind === 'type') {
|
|
2906
2983
|
const text = JSON.stringify(String(args.text ?? ''));
|
|
2907
2984
|
const submit = args.submit ? 'true' : 'false';
|
|
2908
|
-
return `(function(){${BROWSER_JS_HELPERS}${resolveTarget}
|
|
2985
|
+
return `(function(){${BROWSER_JS_HELPERS}${resolveTarget}
|
|
2986
|
+
/*__DT_HELPERS_START__*/
|
|
2987
|
+
function __norm(s){return String(s).toLowerCase().split('').map(function(c){return {'ş':'s','ğ':'g','ü':'u','ı':'i','ö':'o','ç':'c','İ':'i'}[c]||c;}).join('');}
|
|
2988
|
+
function __parseDate(raw){
|
|
2989
|
+
raw=String(raw||'').trim(); if(!raw) return null;
|
|
2990
|
+
const MON={ocak:1,subat:2,mart:3,nisan:4,mayis:5,haziran:6,temmuz:7,agustos:8,eylul:9,ekim:10,kasim:11,aralik:12,jan:1,feb:2,mar:3,apr:4,may:5,jun:6,jul:7,aug:8,sep:9,oct:10,nov:11,dec:12,january:1,february:2,march:3,april:4,june:6,july:7,august:8,september:9,october:10,november:11,december:12};
|
|
2991
|
+
let m=raw.match(/^(\\d{4})[\\-.\\/,](\\d{1,2})[\\-.\\/,](\\d{1,2})$/);
|
|
2992
|
+
if(m) return [+m[1],+m[2],+m[3]];
|
|
2993
|
+
m=raw.match(/^(\\d{1,2})[\\-.\\/ ](\\d{1,2})[\\-.\\/ ](\\d{2,4})$/);
|
|
2994
|
+
if(m){let d=+m[1],mo=+m[2],y=+m[3];if(y<100)y+=2000;if(mo>12&&d<=12){const t=d;d=mo;mo=t;}return [y,mo,d];}
|
|
2995
|
+
m=raw.match(/^(\\d{1,2})[\\-.\\/ ]+([a-zçğıöşü]+)[\\-.\\/ ]+(\\d{2,4})$/i);
|
|
2996
|
+
if(m){const mo=MON[__norm(m[2])];if(mo){let y=+m[3];if(y<100)y+=2000;return [y,mo,+m[1]];}}
|
|
2997
|
+
return null;
|
|
2998
|
+
}
|
|
2999
|
+
function __parseTime(raw){
|
|
3000
|
+
const m=String(raw||'').trim().match(/^(\\d{1,2})[:.h](\\d{2})/);
|
|
3001
|
+
if(!m) return null;
|
|
3002
|
+
return [Math.min(23,+m[1]),Math.min(59,+m[2])];
|
|
3003
|
+
}
|
|
3004
|
+
/*__DT_HELPERS_END__*/
|
|
3005
|
+
return new Promise((res)=>{try{
|
|
2909
3006
|
const t=__target();
|
|
2910
3007
|
if(!t) return res(JSON.stringify({typed:false,reason:'eleman bulunamadi (ref eski olabilir - browser_snapshot al)'}));
|
|
2911
3008
|
const how=t.how,el=t.el;
|
|
3009
|
+
/* tarih/saat alanları: programatik değer + input/change event — native takvim popup'ı hiç açılmaz */
|
|
3010
|
+
const it=(el.tagName==='INPUT'?(el.type||'').toLowerCase():'');
|
|
3011
|
+
if(it==='date'||it==='month'||it==='time'||it==='datetime-local'){
|
|
3012
|
+
const RAW=${text};
|
|
3013
|
+
let v=null;
|
|
3014
|
+
if(it==='time'){
|
|
3015
|
+
const p=__parseTime(RAW); if(p) v=p.map(function(n){return String(n).padStart(2,'0');}).join(':');
|
|
3016
|
+
} else {
|
|
3017
|
+
const p=__parseDate(RAW);
|
|
3018
|
+
if(p&&p.every(Number.isFinite)&&p[1]>=1&&p[1]<=12&&p[2]>=1&&p[2]<=31){
|
|
3019
|
+
const pad=function(n){return String(n).padStart(2,'0');};
|
|
3020
|
+
const ymd=p[0]+'-'+pad(p[1])+'-'+pad(p[2]);
|
|
3021
|
+
v = it==='month' ? (p[0]+'-'+pad(p[1])) : it==='datetime-local' ? (ymd+'T'+((__parseTime(RAW)||[12,0])).map(pad).join(':')) : ymd;
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
3024
|
+
if(!v) return res(JSON.stringify({typed:false,inputType:it,reason:'tarih/saat alanı — metin anlaşılamadı. "2026-03-15", "15.03.2026" veya "15 Mart 2026" gibi gönder'}));
|
|
3025
|
+
const setter=Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,'value').set;
|
|
3026
|
+
setter.call(el,v);
|
|
3027
|
+
el.dispatchEvent(new Event('input',{bubbles:true}));
|
|
3028
|
+
el.dispatchEvent(new Event('change',{bubbles:true}));
|
|
3029
|
+
return res(JSON.stringify({typed:true,target:how+' <input type='+it+'>',value:v,note:'tarih/saat programatik ayarlandi — takvim tiklamak gerekmez'}));
|
|
3030
|
+
}
|
|
2912
3031
|
el.scrollIntoView({block:'center'});el.focus();
|
|
2913
3032
|
setTimeout(()=>{try{
|
|
2914
3033
|
if(el.isContentEditable){el.textContent=${text};}
|
|
@@ -3035,6 +3154,14 @@ async function browserAct(kind, args, signal) {
|
|
|
3035
3154
|
: (obj.reason || 'tamam')
|
|
3036
3155
|
);
|
|
3037
3156
|
|
|
3157
|
+
/* HIZ: eylem cevabına taze snapshot göm — model ayrı browser_snapshot çağırmaz (tur sayısı yarıya iner) */
|
|
3158
|
+
let freshSnap = null;
|
|
3159
|
+
try {
|
|
3160
|
+
const sraw = await wc.executeJavaScript(BROWSER_SNAPSHOT_JS, true);
|
|
3161
|
+
const sobj = JSON.parse(sraw);
|
|
3162
|
+
if (sobj && typeof sobj.count === 'number') freshSnap = sobj;
|
|
3163
|
+
} catch {}
|
|
3164
|
+
|
|
3038
3165
|
return {
|
|
3039
3166
|
ok: true,
|
|
3040
3167
|
action: kind,
|
|
@@ -3042,7 +3169,12 @@ async function browserAct(kind, args, signal) {
|
|
|
3042
3169
|
url: wc.getURL(),
|
|
3043
3170
|
title: wc.getTitle(),
|
|
3044
3171
|
navigated,
|
|
3045
|
-
...(
|
|
3172
|
+
...(freshSnap ? { snapshot: freshSnap.snapshot, refCount: freshSnap.count } : {}),
|
|
3173
|
+
...(navigated
|
|
3174
|
+
? { note: 'sayfa degisti — yanıtta güncel snapshot var; refler eskiyse yeni browser_snapshot al' }
|
|
3175
|
+
: freshSnap
|
|
3176
|
+
? { note: 'yanıtta güncel snapshot (' + freshSnap.count + ' ref) — sonraki hamlede bunları kullan, ayrıca snapshot alma' }
|
|
3177
|
+
: {}),
|
|
3046
3178
|
recent: recentLog(),
|
|
3047
3179
|
};
|
|
3048
3180
|
} catch (e) {
|
|
@@ -4403,22 +4535,9 @@ ipcMain.handle('terminal:toggle', () => {
|
|
|
4403
4535
|
return { ok: true, cwd: (engine && engine.workspace) || settings.workspace || app.getPath('home') };
|
|
4404
4536
|
});
|
|
4405
4537
|
|
|
4406
|
-
/* Git Bash kuruluysa yolunu bulur; yoksa null döner */
|
|
4407
|
-
function findGitBash() {
|
|
4408
|
-
const cands = [];
|
|
4409
|
-
if (process.env['ProgramFiles']) cands.push(path.join(process.env['ProgramFiles'], 'Git', 'bin', 'bash.exe'));
|
|
4410
|
-
if (process.env['ProgramFiles(x86)']) cands.push(path.join(process.env['ProgramFiles(x86)'], 'Git', 'bin', 'bash.exe'));
|
|
4411
|
-
if (process.env['LocalAppData']) cands.push(path.join(process.env['LocalAppData'], 'Programs', 'Git', 'bin', 'bash.exe'));
|
|
4412
|
-
cands.push('C:\\Program Files\\Git\\bin\\bash.exe');
|
|
4413
|
-
for (const c of cands) {
|
|
4414
|
-
try { if (fs.existsSync(c)) return c; } catch {}
|
|
4415
|
-
}
|
|
4416
|
-
return null;
|
|
4417
|
-
}
|
|
4418
|
-
|
|
4419
4538
|
ipcMain.handle('terminal:run', (_e, payload) => {
|
|
4420
4539
|
const cmd = String((payload && payload.cmd) || '').trim();
|
|
4421
|
-
const shell = String((payload && payload.shell) || '
|
|
4540
|
+
const shell = String((payload && payload.shell) || 'cmd');
|
|
4422
4541
|
if (!cmd) return { ok: false, error: 'boş komut' };
|
|
4423
4542
|
if (termChild) return { ok: false, error: 'önceki komut sürüyor — ■ ile durdurabilirsin' };
|
|
4424
4543
|
const cwd = (engine && engine.workspace) || settings.workspace || app.getPath('home');
|
|
@@ -4427,12 +4546,8 @@ ipcMain.handle('terminal:run', (_e, payload) => {
|
|
|
4427
4546
|
if (shell === 'cmd') {
|
|
4428
4547
|
file = 'cmd.exe';
|
|
4429
4548
|
args = ['/d', '/s', '/c', cmd];
|
|
4430
|
-
} else if (shell === 'bash') {
|
|
4431
|
-
const bash = findGitBash();
|
|
4432
|
-
if (!bash) return { ok: false, error: 'Git Bash bulunamadı — Git for Windows kurulu mu? (https://git-scm.com)' };
|
|
4433
|
-
file = bash;
|
|
4434
|
-
args = ['-c', cmd];
|
|
4435
4549
|
} else {
|
|
4550
|
+
/* geriye dönük uyumluluk — UI artık yalnız CMD gönderir */
|
|
4436
4551
|
file = 'powershell.exe';
|
|
4437
4552
|
args = ['-NoProfile', '-NoLogo', '-NonInteractive', '-ExecutionPolicy', 'Bypass', '-Command', cmd];
|
|
4438
4553
|
}
|
|
@@ -5425,10 +5540,61 @@ ipcMain.handle('bots:add', (_e, input) => {
|
|
|
5425
5540
|
ipcMain.handle('bots:dm:list', () => engine.listBotDmSessions());
|
|
5426
5541
|
ipcMain.handle('bots:dm:read', (_e, id) => engine.readBotDm(id));
|
|
5427
5542
|
|
|
5428
|
-
/*
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5543
|
+
/* GITHUB MODALI → Trending / Tüm Repolar: GitHub Search API.
|
|
5544
|
+
opts.mode: 'trend' (varsayılan) | 'all' (tüm repolar — yıldız tabanı yok)
|
|
5545
|
+
opts.range: all | 6m | 1m | 2w | 1w (tüm zamanlar / 6 ay / 1 ay / 2 hafta / 1 hafta)
|
|
5546
|
+
opts.order: desc (azalan) | asc (artan) — yıldız sırası
|
|
5547
|
+
opts.q: arama terimi (trend modunda tarih filtresi UYGULANMAZ — her zaman tüm zamanlar)
|
|
5548
|
+
Kimliksiz 60 istek/saat limiti var — 403'te UI bilgi gösterir. */
|
|
5549
|
+
ipcMain.handle('github:trending', async (_e, opts) => {
|
|
5550
|
+
const o = opts && typeof opts === 'object' ? opts : {};
|
|
5551
|
+
const mode = o.mode === 'all' ? 'all' : 'trend';
|
|
5552
|
+
const range = ['all', '6m', '1m', '2w', '1w'].includes(o.range) ? o.range : '2w';
|
|
5553
|
+
const order = o.order === 'asc' ? 'asc' : 'desc';
|
|
5554
|
+
const q = String(o.q || '').trim().slice(0, 120);
|
|
5555
|
+
const days = { all: 0, '6m': 180, '1m': 30, '2w': 14, '1w': 7 }[range];
|
|
5556
|
+
const since = days ? new Date(Date.now() - days * 86400000).toISOString().slice(0, 10) : '';
|
|
5557
|
+
/* aralık başına yıldız tabanı: listeler anlamlı kalsın diye */
|
|
5558
|
+
const floor = { all: 5000, '6m': 200, '1m': 50, '2w': 20, '1w': 10 }[range];
|
|
5559
|
+
let query;
|
|
5560
|
+
let useSort = true; /* 'all' + best eşleşmede sort param gönderilmez */
|
|
5561
|
+
if (mode === 'all') {
|
|
5562
|
+
if (!q) return { ok: true, items: [] };
|
|
5563
|
+
query = q; /* yıldız tabanı YOK — 0 yıldızlı dahil tüm repolar bulunur */
|
|
5564
|
+
if (o.allSort === 'best') useSort = false;
|
|
5565
|
+
} else if (q) {
|
|
5566
|
+
/* arama modu: tarih filtresi YOK — her zaman tüm zamanlar içinde arar,
|
|
5567
|
+
yıldız sırasına göre döner (küçük taban: çöp listelenmesin diye) */
|
|
5568
|
+
query = q + ' stars:>=10';
|
|
5569
|
+
} else if (range === 'all') {
|
|
5570
|
+
query = 'stars:>=' + floor;
|
|
5571
|
+
} else {
|
|
5572
|
+
query = 'created:>=' + since + ' stars:>=' + floor;
|
|
5573
|
+
}
|
|
5574
|
+
let url = 'https://api.github.com/search/repositories?q=' + encodeURIComponent(query).replace(/%20/g, '+') + '&per_page=20';
|
|
5575
|
+
if (useSort) url += '&sort=stars&order=' + order;
|
|
5576
|
+
try {
|
|
5577
|
+
const res = await fetch(url, {
|
|
5578
|
+
headers: { Accept: 'application/vnd.github+json', 'User-Agent': 'beast-agent' },
|
|
5579
|
+
signal: AbortSignal.timeout(15000),
|
|
5580
|
+
});
|
|
5581
|
+
if (res.status === 403 || res.status === 429) {
|
|
5582
|
+
return { ok: false, error: 'GitHub API limiti doldu (403) — bir saat sonra tekrar dene' };
|
|
5583
|
+
}
|
|
5584
|
+
if (!res.ok) return { ok: false, error: 'GitHub API ' + res.status };
|
|
5585
|
+
const data = await res.json();
|
|
5586
|
+
const items = (data.items || []).map((r) => ({
|
|
5587
|
+
full_name: r.full_name,
|
|
5588
|
+
html_url: r.html_url,
|
|
5589
|
+
description: String(r.description || '').slice(0, 240),
|
|
5590
|
+
language: r.language || '',
|
|
5591
|
+
stars: r.stargazers_count || 0,
|
|
5592
|
+
pushed_at: r.pushed_at || '',
|
|
5593
|
+
}));
|
|
5594
|
+
return { ok: true, items };
|
|
5595
|
+
} catch (e) {
|
|
5596
|
+
return { ok: false, error: String((e && e.message) || e) };
|
|
5597
|
+
}
|
|
5432
5598
|
});
|
|
5433
5599
|
|
|
5434
5600
|
ipcMain.handle('bots:update', (_e, { id, patch }) => {
|
package/src/preload.js
CHANGED
|
@@ -143,7 +143,7 @@ contextBridge.exposeInMainWorld('beast', {
|
|
|
143
143
|
botsAdd: (input) => ipcRenderer.invoke('bots:add', input),
|
|
144
144
|
botsDmList: () => ipcRenderer.invoke('bots:dm:list'),
|
|
145
145
|
botsDmRead: (id) => ipcRenderer.invoke('bots:dm:read', id),
|
|
146
|
-
|
|
146
|
+
githubTrending: (opts) => ipcRenderer.invoke('github:trending', opts),
|
|
147
147
|
botsUpdate: (id, patch) => ipcRenderer.invoke('bots:update', { id, patch }),
|
|
148
148
|
botsRemove: (id) => ipcRenderer.invoke('bots:remove', id),
|
|
149
149
|
botsStats: () => ipcRenderer.invoke('bots:stats'),
|
package/src/renderer/i18n.js
CHANGED
|
@@ -445,8 +445,6 @@
|
|
|
445
445
|
bot_bind_title: 'Bu numarayı hangi bot karşılasın?',
|
|
446
446
|
bot_sel_empty: '— bot seçme —',
|
|
447
447
|
bot_code_title: 'Botun benzersiz 5 haneli kodu — botlar arası DM adresi',
|
|
448
|
-
bot_vis: 'Ana sohbete davet edilebilir (sohbet görünürlüğü)',
|
|
449
|
-
tipGuestBot: 'Konuşmaya bot davet et — davetli botlara ajan bot_dm ile danışır',
|
|
450
448
|
bot_switch_hint: 'Tıkla: bu botta çalış · ⚙: yönet',
|
|
451
449
|
bot_switched: 'bottasın — sohbetler bu botun kimliğiyle gider',
|
|
452
450
|
bot_manage: 'Botu yönet',
|
|
@@ -472,6 +470,7 @@
|
|
|
472
470
|
q_flushed: '${n} kuyruktaki mesaj gönderiliyor',
|
|
473
471
|
bot_num_ro_hint: 'Numara ekleme/kişi adı Ayarlar → Entegrasyonlar (WhatsApp izin listesi) üzerinden yapılır; burada yalnızca bağlı numaralar görünür.',
|
|
474
472
|
tipStore: 'Skills Store',
|
|
473
|
+
tipGithub: 'GitHub Trending — depoları favorile, chate at, ajana araştır',
|
|
475
474
|
tipIde: 'IDE Modu — dosyalar + chat + preview',
|
|
476
475
|
ide_files: 'DOSYALAR',
|
|
477
476
|
ide_pick: 'Klasör seç',
|
|
@@ -1022,8 +1021,6 @@
|
|
|
1022
1021
|
bot_bind_title: 'Which bot should answer this number?',
|
|
1023
1022
|
bot_sel_empty: '— no bot —',
|
|
1024
1023
|
bot_code_title: "This bot's unique 5-digit code — the inter-bot DM address",
|
|
1025
|
-
bot_vis: 'Invitable to the main chat (chat visibility)',
|
|
1026
|
-
tipGuestBot: 'Invite a bot to this chat — the agent consults invited bots via bot_dm',
|
|
1027
1024
|
bot_switch_hint: 'Click: work as this bot · ⚙: manage',
|
|
1028
1025
|
bot_switched: 'active — chats run with this bot\u2019s identity',
|
|
1029
1026
|
bot_manage: 'Manage bot',
|
|
@@ -1049,6 +1046,7 @@
|
|
|
1049
1046
|
q_flushed: '${n} queued message(s) being sent',
|
|
1050
1047
|
bot_num_ro_hint: 'Add numbers / person names via Settings → Integrations (WhatsApp allow list); only linked numbers are shown here.',
|
|
1051
1048
|
tipStore: 'Skills Store',
|
|
1049
|
+
tipGithub: 'GitHub Trending — favorite repos, send to chat, ask the agent',
|
|
1052
1050
|
tipIde: 'IDE Mode — files + chat + preview',
|
|
1053
1051
|
ide_files: 'FILES',
|
|
1054
1052
|
ide_pick: 'Choose folder',
|
package/src/renderer/index.html
CHANGED
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
<button id="themeBtn" title="Koyu tema">☾</button>
|
|
40
40
|
<button id="langBtn" title="Dil değiştir / Switch language" data-i18n-title="tipLang"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="9"/><path d="M3 12h18"/><path d="M12 3c2.6 2.6 2.6 15.4 0 18M12 3c-2.6 2.6-2.6 15.4 0 18"/></svg></button>
|
|
41
41
|
<button id="storeBtn" title="Skills Store" data-i18n-title="tipStore"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16l-1.3 12.1a2 2 0 0 1-2 1.9H7.3a2 2 0 0 1-2-1.9L4 7z"/><path d="M8 10V6a4 4 0 0 1 8 0v4"/></svg></button>
|
|
42
|
+
<button id="gitBtn" title="GitHub Trending" data-i18n-title="tipGithub"><svg viewBox="0 0 24 24" width="15" height="15" fill="currentColor" aria-hidden="true"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></button>
|
|
42
43
|
<button id="ideBtn" title="IDE Modu" data-i18n-title="tipIde"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 6l-5 6 5 6"/><path d="M16 6l5 6-5 6"/><path d="M13.5 4l-3 16"/></svg></button>
|
|
43
44
|
</div>
|
|
44
45
|
</aside>
|
|
@@ -70,11 +71,9 @@
|
|
|
70
71
|
<div id="cfgList" class="dd-list"></div>
|
|
71
72
|
</div>
|
|
72
73
|
</div>
|
|
73
|
-
<button id="railBtn" class="dd-btn dd-icon-btn
|
|
74
|
+
<button id="railBtn" class="dd-btn dd-icon-btn" title="Paralel Ajan Konsolu" data-i18n-title="tipRail">▤</button>
|
|
74
75
|
<button id="watchBtn" class="dd-btn dd-icon-btn" title="İzleyiciler (Watchers)" data-i18n-title="tipWatch">◎</button>
|
|
75
76
|
<button id="cronBtn" class="dd-btn dd-icon-btn" title="Cron Görevler" data-i18n-title="tipCron">⏱︎</button>
|
|
76
|
-
<button id="termBtn" class="dd-btn dd-icon-btn" title="Terminal (PowerShell)" data-i18n-title="tipTerm">></button>
|
|
77
|
-
<button id="termGBtn" class="dd-btn dd-icon-btn" title="Git Bash terminali" data-i18n-title="tipTermG">◈</button>
|
|
78
77
|
<button id="termCBtn" class="dd-btn dd-icon-btn" title="CMD terminali" data-i18n-title="tipTermC">❯︎</button>
|
|
79
78
|
<button id="browserBtn" class="dd-btn dd-icon-btn" title="Dahili tarayıcı" data-i18n-title="tipBrowser">⧉</button>
|
|
80
79
|
<button id="eyeBtn" class="dd-btn dd-icon-btn" title="Ajan tarayıcısı görünür/gizli — göz açıkken aramalar panelde izlenir, kapalıyken gizli çalışır" data-i18n-title="tipEye"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7z"/><circle cx="12" cy="12" r="3"/><line class="eye-slash" x1="4" y1="4" x2="20" y2="20"/></svg></button>
|
|
@@ -91,15 +90,13 @@
|
|
|
91
90
|
|
|
92
91
|
<div id="composerWrap">
|
|
93
92
|
<div id="todoPanel" hidden></div>
|
|
94
|
-
<div id="statusPill" hidden></div>
|
|
93
|
+
<div id="statusRow"><div id="statusPill" hidden></div><div id="toast" hidden></div></div>
|
|
95
94
|
<div id="chips" hidden></div>
|
|
96
95
|
<div id="slashMenu" hidden></div>
|
|
97
96
|
<div id="composer">
|
|
98
97
|
<div id="composerLeft" class="dd">
|
|
99
98
|
<button id="attachBtn" title="Dosya / resim ekle" data-i18n-title="tipAttach">+</button>
|
|
100
99
|
<button id="micBtn" title="Sesli komut — konuş, bırakınca yazıya çevirsin" data-i18n-title="tipMic"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="2" width="6" height="12" rx="3"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><path d="M12 19v3"/></svg></button>
|
|
101
|
-
<button id="guestBotBtn" title="Konuşmaya bot davet et — davetli botlara ajan bot_dm ile danışır" data-i18n-title="tipGuestBot" hidden><span style="filter:grayscale(1)">🤖</span></button>
|
|
102
|
-
<div id="guestBotMenu" class="dd-menu" hidden></div>
|
|
103
100
|
</div>
|
|
104
101
|
<textarea id="input" rows="1" placeholder="Bir şey sor ya da görev ver… (Enter: gönder · Shift+Enter: satır · /: komutlar)" data-i18n-ph="composerPh"></textarea>
|
|
105
102
|
<button id="stopBtn" title="Durdur" hidden data-i18n-title="tipStop">■</button>
|
|
@@ -272,6 +269,47 @@
|
|
|
272
269
|
</div>
|
|
273
270
|
</div>
|
|
274
271
|
|
|
272
|
+
<div id="ghOverlay" hidden>
|
|
273
|
+
<div id="ghDialog">
|
|
274
|
+
<div id="ghHead">
|
|
275
|
+
<span id="ghTitle">GITHUB TRENDING</span>
|
|
276
|
+
<span class="store-spacer"></span>
|
|
277
|
+
<button id="ghClose" class="mini-close" title="Kapat" data-i18n-title="btn_close">×</button>
|
|
278
|
+
</div>
|
|
279
|
+
<div id="ghBody">
|
|
280
|
+
<section id="ghTrendPane" class="gh-pane">
|
|
281
|
+
<div class="gh-pane-tabs">
|
|
282
|
+
<button class="gh-tab on" data-ghtab="trend">Trend Depolar</button>
|
|
283
|
+
<button class="gh-tab" data-ghtab="all">Tüm Repolar</button>
|
|
284
|
+
</div>
|
|
285
|
+
<div class="gh-pane-subline" id="ghTrendSub">— son 2 haftanın yıldız yükselenleri</div>
|
|
286
|
+
<div id="ghTrendTools" class="gh-filters">
|
|
287
|
+
<div class="gh-ranges" id="ghRanges">
|
|
288
|
+
<button data-range="all" title="Tüm zamanlar">Tümü</button>
|
|
289
|
+
<button data-range="6m" title="Son 6 ay">6 Ay</button>
|
|
290
|
+
<button data-range="1m" title="Son 1 ay">1 Ay</button>
|
|
291
|
+
<button data-range="2w" class="on" title="Son 2 hafta">2 Hafta</button>
|
|
292
|
+
<button data-range="1w" title="Son 1 hafta">1 Hafta</button>
|
|
293
|
+
</div>
|
|
294
|
+
<button id="ghSortBtn" title="Yıldız sırası: azalan / artan">↓ Yıldız</button>
|
|
295
|
+
<input id="ghSearch" placeholder="Repo ara… (Enter)" spellcheck="false" />
|
|
296
|
+
<button id="ghTrendRefresh" class="gh-refresh" title="Sıfırla ve yenile — modal ilk açıldığı gibi">⟳</button>
|
|
297
|
+
</div>
|
|
298
|
+
<div id="ghAllTools" class="gh-filters" hidden>
|
|
299
|
+
<input id="ghAllSearch" placeholder="Tüm GitHub'da ara… (Enter)" spellcheck="false" />
|
|
300
|
+
<button id="ghAllSortBtn" title="Sıralama: en iyi eşleşme / yıldız">⭐ En İyi</button>
|
|
301
|
+
<button id="ghAllRefresh" class="gh-refresh" title="Sıfırla ve yenile">⟳</button>
|
|
302
|
+
</div>
|
|
303
|
+
<div id="ghTrendList" class="gh-pane-list"></div>
|
|
304
|
+
</section>
|
|
305
|
+
<section id="ghFavPane" class="gh-pane">
|
|
306
|
+
<div class="gh-pane-title">Favoriler <span class="gh-pane-sub">— yıldızladıkların burada saklanır</span></div>
|
|
307
|
+
<div id="ghFavList" class="gh-pane-list"></div>
|
|
308
|
+
</section>
|
|
309
|
+
</div>
|
|
310
|
+
</div>
|
|
311
|
+
</div>
|
|
312
|
+
|
|
275
313
|
<div id="watchOverlay" class="mini-overlay" hidden>
|
|
276
314
|
<div class="mini-dialog">
|
|
277
315
|
<div class="mini-head">
|
|
@@ -318,15 +356,13 @@
|
|
|
318
356
|
<div id="termOut"></div>
|
|
319
357
|
</div>
|
|
320
358
|
<div id="termInputRow">
|
|
321
|
-
<span id="termPrompt">
|
|
359
|
+
<span id="termPrompt">CMD></span>
|
|
322
360
|
<input id="termInput" spellcheck="false" autocomplete="off" placeholder="komut yaz, Enter'la çalıştır…" data-i18n-ph="term_ph" />
|
|
323
361
|
<button id="termStop" title="Çalışan komutu durdur" hidden data-i18n-title="term_stop">■︎</button>
|
|
324
362
|
</div>
|
|
325
363
|
</div>
|
|
326
364
|
<div id="termResize" hidden title="Sürükleyerek boyutlandır"></div>
|
|
327
365
|
|
|
328
|
-
<div id="toast"></div>
|
|
329
|
-
|
|
330
366
|
<div id="fileCtxMenu" hidden></div>
|
|
331
367
|
|
|
332
368
|
<input type="file" id="fileInput" multiple hidden
|