beast-agent 2.3.2 → 2.3.3
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/main.js +93 -0
- package/src/preload.js +2 -0
- package/src/renderer/i18n.js +4 -2
- package/src/renderer/index.html +2 -0
- package/src/renderer/renderer.js +73 -3
package/package.json
CHANGED
package/src/main.js
CHANGED
|
@@ -3248,6 +3248,15 @@ app.whenReady().then(() => {
|
|
|
3248
3248
|
waLog('STT aktif: ' + sttEngineLabel() + ' — yerel model kullanılmayacak');
|
|
3249
3249
|
}
|
|
3250
3250
|
|
|
3251
|
+
/* EMBEDDING modeli (hafıza semantik arama) — açılışta otomatik indir */
|
|
3252
|
+
setTimeout(() => {
|
|
3253
|
+
try {
|
|
3254
|
+
require('./agent/mem0').search('beast', 'warmup')
|
|
3255
|
+
.then(() => waLog('embedding modeli hazır (all-MiniLM-L6-v2)'))
|
|
3256
|
+
.catch(() => {});
|
|
3257
|
+
} catch {}
|
|
3258
|
+
}, 20000);
|
|
3259
|
+
|
|
3251
3260
|
// WhatsApp köprüsünü otomatik başlat (eşleme varsa direkt bağlanır)
|
|
3252
3261
|
ensureWa().start().catch((e) => waLog('autostart failed: ' + (e && e.message)));
|
|
3253
3262
|
|
|
@@ -5825,6 +5834,90 @@ ipcMain.handle('stt:prefetch', () => {
|
|
|
5825
5834
|
.catch((e) => waLog('STT prefetch hata: ' + String((e && e.message) || e)));
|
|
5826
5835
|
return { ok: true, loading: true };
|
|
5827
5836
|
});
|
|
5837
|
+
|
|
5838
|
+
/* KURULUM SEKMESİ: gerekli bileşenlerin durum taraması */
|
|
5839
|
+
ipcMain.handle('install:status', async () => {
|
|
5840
|
+
const rows = [];
|
|
5841
|
+
const pkgOk = (id) => { try { require.resolve(id); return true; } catch { return false; } };
|
|
5842
|
+
const scanModel = (rel) => {
|
|
5843
|
+
const dir = path.join(APP_DIR, 'models', ...rel.split('/'));
|
|
5844
|
+
let files = [];
|
|
5845
|
+
try {
|
|
5846
|
+
files = fs.readdirSync(dir, { recursive: true, withFileTypes: true })
|
|
5847
|
+
.filter((d) => d.isFile())
|
|
5848
|
+
.map((d) => path.join(d.parentPath || d.path, d.name));
|
|
5849
|
+
} catch {}
|
|
5850
|
+
let bytes = 0, tmp = 0, onnx = 0, hasCfg = false;
|
|
5851
|
+
for (const p of files) {
|
|
5852
|
+
try {
|
|
5853
|
+
bytes += fs.statSync(p).size;
|
|
5854
|
+
if (/\.tmp/i.test(p)) tmp++;
|
|
5855
|
+
else if (/\.onnx$/i.test(p)) onnx++;
|
|
5856
|
+
else if (/config\.json$/i.test(p)) hasCfg = true;
|
|
5857
|
+
} catch {}
|
|
5858
|
+
}
|
|
5859
|
+
return { files, bytes, tmp, onnx, hasCfg };
|
|
5860
|
+
};
|
|
5861
|
+
|
|
5862
|
+
/* 1) STT modeli */
|
|
5863
|
+
if (sttProvider() !== 'local') {
|
|
5864
|
+
rows.push({ id: 'stt', name: 'STT modeli — ' + sttModelName(), state: 'cloud', detail: 'bulut motoru — indirme gerekmez' });
|
|
5865
|
+
} else {
|
|
5866
|
+
const s = scanModel(sttModelName());
|
|
5867
|
+
let state;
|
|
5868
|
+
if (sttPipeline) state = 'ok';
|
|
5869
|
+
else if (sttLoading) state = 'loading';
|
|
5870
|
+
else if (s.hasCfg && s.onnx >= 2 && s.tmp === 0) state = 'downloaded';
|
|
5871
|
+
else if (s.files.length) state = 'partial';
|
|
5872
|
+
else state = 'missing';
|
|
5873
|
+
rows.push({ id: 'stt', name: 'STT modeli — whisper-large-v3-turbo', state, detail: sttEngineLabel(), mb: Math.round(s.bytes / 1048576) });
|
|
5874
|
+
}
|
|
5875
|
+
|
|
5876
|
+
/* 2) Embedding modeli (hafıza semantik arama) */
|
|
5877
|
+
{
|
|
5878
|
+
const s = scanModel('Xenova/all-MiniLM-L6-v2');
|
|
5879
|
+
const state = s.hasCfg && s.onnx >= 1 && s.tmp === 0 ? 'ok' : (s.files.length ? 'partial' : 'missing');
|
|
5880
|
+
rows.push({ id: 'emb', name: 'Embedding modeli — all-MiniLM-L6-v2', state, detail: 'hafıza semantik arama', mb: Math.round(s.bytes / 1048576) });
|
|
5881
|
+
}
|
|
5882
|
+
|
|
5883
|
+
/* 3) ffmpeg */
|
|
5884
|
+
let ffOk = false;
|
|
5885
|
+
try { const p = require('ffmpeg-static'); ffOk = !!p && fs.existsSync(p); } catch {}
|
|
5886
|
+
rows.push({ id: 'ffmpeg', name: 'ffmpeg — ses/video dönüşüm', state: ffOk ? 'ok' : 'missing', detail: ffOk ? 'kurulu' : 'npm paketi eksik' });
|
|
5887
|
+
|
|
5888
|
+
/* 4) çalışma zamanı npm paketleri */
|
|
5889
|
+
rows.push({ id: 'hf', name: 'Transformers.js — STT çalışma zamanı', state: pkgOk('@huggingface/transformers') ? 'ok' : 'missing', detail: 'npm paketi' });
|
|
5890
|
+
rows.push({ id: 'ort', name: 'ONNX Runtime — model motoru', state: pkgOk('onnxruntime-node') ? 'ok' : 'missing', detail: 'npm paketi' });
|
|
5891
|
+
|
|
5892
|
+
/* 5) OCR */
|
|
5893
|
+
rows.push({ id: 'ocr', name: 'OCR — Tesseract (ekran okuma)', state: pkgOk('tesseract.js') ? 'ok' : 'missing', detail: pkgOk('tesseract.js') ? 'kurulu — dil verisi ilk kullanımda iner' : 'npm paketi eksik' });
|
|
5894
|
+
|
|
5895
|
+
/* 6) Python (opsiyonel — betikler) */
|
|
5896
|
+
let pyVer = '';
|
|
5897
|
+
for (const cmd of ['python -c "import sys;print(sys.version.split()[0])"', 'py -3 -c "import sys;print(sys.version.split()[0])"']) {
|
|
5898
|
+
try {
|
|
5899
|
+
pyVer = String(require('child_process').execSync(cmd, { timeout: 4000, stdio: 'pipe', encoding: 'utf8' })).trim();
|
|
5900
|
+
if (pyVer) break;
|
|
5901
|
+
} catch {}
|
|
5902
|
+
}
|
|
5903
|
+
rows.push({ id: 'python', name: 'Python — betikler / web arama', state: pyVer ? 'ok' : 'optional', detail: pyVer ? 'v' + pyVer : 'sistemde bulunamadı — opsiyonel' });
|
|
5904
|
+
|
|
5905
|
+
/* 7) Edge TTS (bulut) */
|
|
5906
|
+
rows.push({ id: 'edge', name: 'Edge TTS — seslendirme', state: 'cloud', detail: 'bulut — kurulum gerekmez' });
|
|
5907
|
+
|
|
5908
|
+
return rows;
|
|
5909
|
+
});
|
|
5910
|
+
|
|
5911
|
+
/* embedding modelini şimdi indir (mem0 arama yolu ısıtılır) */
|
|
5912
|
+
ipcMain.handle('embed:prefetch', () => {
|
|
5913
|
+
try {
|
|
5914
|
+
const mem0 = require('./agent/mem0');
|
|
5915
|
+
mem0.search('beast', 'warmup')
|
|
5916
|
+
.then(() => waLog('embedding modeli hazır'))
|
|
5917
|
+
.catch(() => {});
|
|
5918
|
+
} catch {}
|
|
5919
|
+
return { ok: true, loading: true };
|
|
5920
|
+
});
|
|
5828
5921
|
ipcMain.handle('stt:lang:set', (_e, lang) => {
|
|
5829
5922
|
const v = ['auto', 'tr', 'en'].includes(String(lang)) ? String(lang) : 'tr';
|
|
5830
5923
|
settings.sttLang = v;
|
package/src/preload.js
CHANGED
|
@@ -55,6 +55,8 @@ contextBridge.exposeInMainWorld('beast', {
|
|
|
55
55
|
sttLangGet: () => ipcRenderer.invoke('stt:lang:get'),
|
|
56
56
|
sttStatus: () => ipcRenderer.invoke('stt:status'),
|
|
57
57
|
sttPrefetchNow: () => ipcRenderer.invoke('stt:prefetch'),
|
|
58
|
+
installStatus: () => ipcRenderer.invoke('install:status'),
|
|
59
|
+
embedPrefetch: () => ipcRenderer.invoke('embed:prefetch'),
|
|
58
60
|
sttLangSet: (lang) => ipcRenderer.invoke('stt:lang:set', lang),
|
|
59
61
|
updateStatus: () => ipcRenderer.invoke('update:status'),
|
|
60
62
|
updateCheck: () => ipcRenderer.invoke('update:check'),
|
package/src/renderer/i18n.js
CHANGED
|
@@ -69,7 +69,8 @@
|
|
|
69
69
|
tab_notes: 'Oturum Notları',
|
|
70
70
|
tab_history: 'Oturum Geçmişi',
|
|
71
71
|
tab_agents: 'Paralel Ajanlar',
|
|
72
|
-
tab_tts: 'Sesli Yanıt',
|
|
72
|
+
tab_tts: 'Sesli Yanıt',
|
|
73
|
+
tab_install: 'Kurulum',
|
|
73
74
|
tab_email: 'E-posta',
|
|
74
75
|
tab_integrations: 'Entegrasyonlar',
|
|
75
76
|
tab_websearch: 'Web Arama',
|
|
@@ -645,7 +646,8 @@
|
|
|
645
646
|
tab_notes: 'Session Notes',
|
|
646
647
|
tab_history: 'Session History',
|
|
647
648
|
tab_agents: 'Parallel Agents',
|
|
648
|
-
tab_tts: 'Voice Reply',
|
|
649
|
+
tab_tts: 'Voice Reply',
|
|
650
|
+
tab_install: 'Setup',
|
|
649
651
|
tab_email: 'E-mail',
|
|
650
652
|
tab_integrations: 'Integrations',
|
|
651
653
|
tab_websearch: 'Web Search',
|
package/src/renderer/index.html
CHANGED
|
@@ -233,6 +233,7 @@
|
|
|
233
233
|
<button class="tab" data-tab="skills" data-i18n="tab_skills">Skills</button>
|
|
234
234
|
<button class="tab" data-tab="agents" data-i18n="tab_agents">Paralel Ajanlar</button>
|
|
235
235
|
<button class="tab" data-tab="tts" data-i18n="tab_tts">Sesli Yanıt</button>
|
|
236
|
+
<button class="tab" data-tab="install" data-i18n="tab_install">Kurulum</button>
|
|
236
237
|
<button class="tab" data-tab="email" data-i18n="tab_email">E-posta</button>
|
|
237
238
|
<button class="tab" data-tab="integrations" data-i18n="tab_integrations">Entegrasyonlar</button>
|
|
238
239
|
<button class="tab" data-tab="websearch" data-i18n="tab_websearch">Web Arama</button>
|
|
@@ -257,6 +258,7 @@
|
|
|
257
258
|
<div id="tab-skills" class="pane" hidden></div>
|
|
258
259
|
<div id="tab-agents" class="pane" hidden></div>
|
|
259
260
|
<div id="tab-tts" class="pane" hidden></div>
|
|
261
|
+
<div id="tab-install" class="pane" hidden></div>
|
|
260
262
|
<div id="tab-email" class="pane" hidden></div>
|
|
261
263
|
<div id="tab-integrations" class="pane" hidden></div>
|
|
262
264
|
<div id="tab-websearch" class="pane" hidden></div>
|
package/src/renderer/renderer.js
CHANGED
|
@@ -1060,6 +1060,7 @@ async function renderActiveSettingsTab() {
|
|
|
1060
1060
|
case 'fallout': await refreshFalloutPane(); break;
|
|
1061
1061
|
case 'skills': await renderSkillsPane(); break;
|
|
1062
1062
|
case 'tts': await renderTtsPane(); break;
|
|
1063
|
+
case 'install': await renderInstallPane(); break;
|
|
1063
1064
|
case 'email': await renderEmailPane(); break;
|
|
1064
1065
|
case 'integrations': await renderIntegrationsPane(); break;
|
|
1065
1066
|
case 'websearch': await renderWebSearchPane(); break;
|
|
@@ -1150,13 +1151,14 @@ function switchTab(name) {
|
|
|
1150
1151
|
document.querySelectorAll('#setTabs .tab').forEach((b) =>
|
|
1151
1152
|
b.classList.toggle('active', b.dataset.tab === name)
|
|
1152
1153
|
);
|
|
1153
|
-
for (const p of ['lang', 'provider', 'fallout', 'skills', 'agents', 'tts', 'email', 'integrations', 'websearch', 'mcp', 'events', 'cron', 'usage', 'logs', 'dash', 'sec', 'update']) {
|
|
1154
|
+
for (const p of ['lang', 'provider', 'fallout', 'skills', 'agents', 'tts', 'install', 'email', 'integrations', 'websearch', 'mcp', 'events', 'cron', 'usage', 'logs', 'dash', 'sec', 'update']) {
|
|
1154
1155
|
const el = $('#tab-' + p);
|
|
1155
1156
|
if (el) el.hidden = p !== name; // guard: eksik pane tüm sekmeleri kilitlemesin
|
|
1156
1157
|
}
|
|
1157
1158
|
if (name === 'lang') renderLangPane();
|
|
1158
1159
|
if (name === 'cron') openCron();
|
|
1159
1160
|
if (name === 'usage') renderUsagePane();
|
|
1161
|
+
if (name === 'install') renderInstallPane();
|
|
1160
1162
|
if (name === 'events') renderEventsPane();
|
|
1161
1163
|
if (name === 'logs') renderLogPane();
|
|
1162
1164
|
if (name === 'dash') renderDashboardPane();
|
|
@@ -2097,8 +2099,76 @@ function ttsFlushTail() {
|
|
|
2097
2099
|
if (rest) ttsEnqueueSentence(rest);
|
|
2098
2100
|
else ttsKick();
|
|
2099
2101
|
}
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
+
/* ---------------- KURULUM SEKMESİ: bileşenler OTOMATİK kurulur ----------------
|
|
2103
|
+
Eksik/kısmen inmiş bileşen sekme açılınca kendiliğinden indirilir; kullanıcı
|
|
2104
|
+
hiçbir düğmeye basmaz. Durum canlı güncellenir (4 sn'de bir). */
|
|
2105
|
+
async function renderInstallPane() {
|
|
2106
|
+
const pane = $('#tab-install');
|
|
2107
|
+
if (!pane) return;
|
|
2108
|
+
pane.innerHTML =
|
|
2109
|
+
'<h2>Kurulum</h2><div class="sub">Gerekli bileşenler otomatik indirilir ve kurulur — eksik varsa aşağıda İNİYOR olarak görürsün.</div>' +
|
|
2110
|
+
'<div id="instRows" style="margin-top:10px">Taranıyor…</div>';
|
|
2111
|
+
|
|
2112
|
+
const autoStarted = new Set(); // bu pane oturumunda otomatik başlatılanlar
|
|
2113
|
+
let refreshTimer = null;
|
|
2114
|
+
|
|
2115
|
+
const badge = (st) => {
|
|
2116
|
+
const map = {
|
|
2117
|
+
ok: ['KURULU', 'var(--ok)'],
|
|
2118
|
+
downloaded: ['İNDİRİLDİ', 'var(--ok)'],
|
|
2119
|
+
loading: ['İNİYOR…', '#d9a441'],
|
|
2120
|
+
partial: ['İNİYOR… (devam)', '#d9a441'],
|
|
2121
|
+
missing: ['İNDİRİLİYOR…', '#d9a441'],
|
|
2122
|
+
cloud: ['BULUT', 'var(--muted)'],
|
|
2123
|
+
optional: ['OPSİYONEL', 'var(--muted)'],
|
|
2124
|
+
};
|
|
2125
|
+
const [txt, color] = map[st] || [st, 'var(--muted)'];
|
|
2126
|
+
return '<span style="color:' + color + ';font-weight:700;font-size:11px;flex:none">' + txt + '</span>';
|
|
2127
|
+
};
|
|
2128
|
+
|
|
2129
|
+
/* eksik bileşenleri OTOMATİK başlat (bileşen başına bir kez) */
|
|
2130
|
+
const autoStart = (rows) => {
|
|
2131
|
+
for (const r of rows) {
|
|
2132
|
+
if (autoStarted.has(r.id)) continue;
|
|
2133
|
+
if (r.id === 'stt' && ['missing', 'partial', 'loading'].includes(r.state)) {
|
|
2134
|
+
autoStarted.add('stt');
|
|
2135
|
+
beast.sttPrefetchNow().catch(() => {});
|
|
2136
|
+
}
|
|
2137
|
+
if (r.id === 'emb' && ['missing', 'partial'].includes(r.state)) {
|
|
2138
|
+
autoStarted.add('emb');
|
|
2139
|
+
beast.embedPrefetch().catch(() => {});
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
};
|
|
2143
|
+
|
|
2144
|
+
const render = (rows) => {
|
|
2145
|
+
const el = $('#instRows');
|
|
2146
|
+
if (!el) return;
|
|
2147
|
+
if (!rows || !rows.length) { el.innerHTML = '<div class="sub">Durum alınamadı</div>'; return; }
|
|
2148
|
+
autoStart(rows);
|
|
2149
|
+
el.innerHTML = rows.map((r) => (
|
|
2150
|
+
'<div style="display:flex;align-items:center;gap:10px;padding:9px 0;border-bottom:1px solid var(--border)">' +
|
|
2151
|
+
'<div style="flex:1;min-width:0">' +
|
|
2152
|
+
'<div style="font-size:13px">' + escapeHtml(r.name) + '</div>' +
|
|
2153
|
+
'<div class="sub" style="font-size:11px">' + escapeHtml(r.detail || '') + (r.mb ? ' · ' + r.mb + ' MB' : '') + '</div>' +
|
|
2154
|
+
'</div>' +
|
|
2155
|
+
badge(r.state) +
|
|
2156
|
+
'</div>'
|
|
2157
|
+
)).join('');
|
|
2158
|
+
};
|
|
2159
|
+
|
|
2160
|
+
const refresh = async () => {
|
|
2161
|
+
if (pane.hidden) return;
|
|
2162
|
+
const rows = await beast.installStatus().catch(() => []);
|
|
2163
|
+
render(rows);
|
|
2164
|
+
};
|
|
2165
|
+
|
|
2166
|
+
if (refreshTimer) clearInterval(refreshTimer);
|
|
2167
|
+
await refresh();
|
|
2168
|
+
refreshTimer = setInterval(refresh, 4000);
|
|
2169
|
+
}
|
|
2170
|
+
|
|
2171
|
+
async function renderTtsPane() { const pane = $('#tab-tts');
|
|
2102
2172
|
if (!pane) return;
|
|
2103
2173
|
/* STT DURUMU: model indirildi mi / iniyor mu / hangi motor */
|
|
2104
2174
|
let stt = null;
|