beast-agent 2.44.0 → 2.44.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/README.md CHANGED
@@ -24,8 +24,8 @@ Beast Agent is a personal AI agent that runs on your machine and connects to **a
24
24
  - **Slash commands** — `/new`, `/open`, `/change`, `/think`, `/rule`, `/allow`, `/block`, `/backup`, `/approve` and more
25
25
  - **Event center** — IMAP IDLE email watching, file-change watching, price feed (Binance), webhook inputs
26
26
  - **Cron + watchers** — scheduled tasks, file/web/battery watchers
27
- - **MCP desteği** — Model Context Protocol server bağla (filesystem, git, fetch, memory + binlerce topluluk server'ı); araçlar `mcp__server__tool` adıyla modele açılır, Ayarlar → MCP'den yönetilir
28
- - **Skills** — `%APPDATA%\beast\skills\<ad>\SKILL.md` ile ajanına yetenek öğret; Superpowers metodoloji paketi (planlama, TDD, paralel ajan disiplini, doğrulama) builtin gelir
27
+ - **MCP support** — connect Model Context Protocol servers (filesystem, git, fetch, memory + thousands of community servers); tools are exposed to the model as `mcp__server__tool` and managed from Settings → MCP
28
+ - **Skills** — teach your agent new abilities with `%APPDATA%\beast\skills\<name>\SKILL.md`; the Superpowers methodology pack (planning, TDD, parallel-agent discipline, verification) ships built-in
29
29
  - **Web search chain** — TinyFish (free, used first if a key is set) → built-in browser (direct Google) → python multi-engine (DDG/Bing/Mojeek) → Exa
30
30
  - **Approval gate** — optional confirmation for risky actions (commands / file deletion-modification): default OFF (everything free), when ON the agent asks (`/approve`, `/approve always`, `/deny`)
31
31
  - **Provider-based limits** — per-provider max input token limit with context compression
@@ -1,137 +1,137 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
-
4
- /* Beast Agent global npm başlatıcısı (`beast` kısa adı da aynı scripte bağlı):
5
- `beast` / `beast-agent` → uygulamayı detached başlatır, terminali hemen serbest bırakır
6
- `beast update` → npm'den en son sürümü yükler (uygulama kapalıyken çalıştır) */
7
-
8
- const { spawn, spawnSync } = require('child_process');
9
- const path = require('path');
10
- const fs = require('fs');
11
- const os = require('os');
12
-
13
- /* kaldırma modu: uygulamayı kaldırır ama KİŞİSEL VERİLERİ korur
14
- (%APPDATA%\beast: config.yaml, .env, oturumlar, hafıza, WhatsApp eşlemesi, yedekler) */
15
- if (process.argv[2] === 'uninstall') {
16
- const isWin = process.platform === 'win32';
17
- console.log('Beast Agent kald\u0131r\u0131l\u0131yor\u2026');
18
- if (isWin) {
19
- /* çalışan örnekleri kapat */
20
- try {
21
- spawnSync('powershell.exe', ['-NoProfile', '-Command',
22
- "Get-Process electron -ErrorAction SilentlyContinue | Where-Object { $_.Path -like '*node_modules*beast-agent*' } | Stop-Process -Force"],
23
- { stdio: 'ignore' });
24
- console.log('\u2022 \u00E7al\u0131\u015Fan Beast kapat\u0131ld\u0131 (varsa)');
25
- } catch {}
26
- /* startup kaydını sil — yalnız verisi beast-agent'a işaret ediyorsa */
27
- try {
28
- spawnSync('powershell.exe', ['-NoProfile', '-Command',
29
- "$k='HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run';" +
30
- "foreach($n in (Get-Item $k -ErrorAction SilentlyContinue).GetValueNames()){" +
31
- "$v=(Get-ItemProperty $k).$n; if($v -like '*node_modules*beast-agent*'){ Remove-ItemProperty -Path $k -Name $n; Write-Host '• startup kayd\u0131 silindi' } }"],
32
- { stdio: 'inherit' });
33
- } catch {}
34
- /* masaüstü kısayolunu sil (gerçek Masaüstü yolu: OneDrive olabilir) */
35
- try {
36
- spawnSync('powershell.exe', ['-NoProfile', '-Command',
37
- "$d=[Environment]::GetFolderPath('Desktop'); if(Test-Path \"$d\\Beast Agent.lnk\"){ Remove-Item \"$d\\Beast Agent.lnk\" -Force; Write-Host '\u2022 masa\u00FCst\u00FC k\u0131sayolu silindi' }"],
38
- { stdio: 'inherit' });
39
- } catch {}
40
- } else {
41
- try { spawnSync('pkill', ['-f', 'node_modules/beast-agent'], { stdio: 'ignore' }); } catch {}
42
- }
43
- console.log('\u2022 npm paketi kald\u0131r\u0131l\u0131yor\u2026');
44
- const ur = spawnSync('npm', ['uninstall', '-g', 'beast-agent'], { stdio: 'inherit', shell: isWin });
45
- console.log('\n\u2713 Beast Agent kald\u0131r\u0131ld\u0131.');
46
- console.log('\u2139 Ki\u015Fisel verilerin korundu \u2014 %APPDATA%\\beast');
47
- console.log(' (config.yaml, .env, oturumlar, haf\u0131za, WhatsApp e\u015Flemesi, \u015Fifreli yedekler)');
48
- console.log(' Tekrar kurmak i\u00E7in: npm install -g beast-agent');
49
- process.exit(ur.status || 0);
50
- }
51
-
52
- /* güncelleme modu: çalışan Beast'i kapat (dosya kilidi EBUSY vermesin) → npm güncelle (görünür ilerleme) → yeniden başlat.
53
- Bu komut güncelleme butonu tarafından GÖRÜNÜR bir cmd penceresi içinde çalıştırılır;
54
- doğrudan terminalden de çalışır — npm install çıktısı ekranda akar. */
55
- if (process.argv[2] === 'update') {
56
- const isWin = process.platform === 'win32';
57
- console.log('\u27F3 beast-agent g\u00FCncelleniyor\u2026');
58
- if (isWin) {
59
- try {
60
- spawnSync('powershell.exe', ['-NoProfile', '-Command',
61
- "Get-Process electron -ErrorAction SilentlyContinue | Where-Object { $_.Path -like '*node_modules*beast-agent*' } | Stop-Process -Force"],
62
- { stdio: 'ignore' });
63
- console.log('\u2022 \u00E7al\u0131\u015Fan Beast kapat\u0131ld\u0131 (varsa)');
64
- } catch {}
65
- } else {
66
- try { spawnSync('pkill', ['-f', 'node_modules/beast-agent'], { stdio: 'ignore' }); } catch {}
67
- }
68
- /* dosya kilidi (EBUSY) bazen ilk denemede patlar — 5 deneme hakkı */
69
- let ok = false;
70
- for (let i = 1; i <= 5 && !ok; i++) {
71
- const r = spawnSync('npm', ['install', '-g', 'beast-agent@latest'], { stdio: 'inherit', shell: isWin });
72
- ok = r.status === 0;
73
- if (!ok && i < 5) {
74
- console.log(` \u2022 deneme ${i}/5 ba\u015Far\u0131s\u0131z (dosya kilidi olabilir) \u2014 3 sn sonra tekrar\u2026`);
75
- if (isWin) spawnSync('powershell.exe', ['-NoProfile', '-Command', 'Start-Sleep -Seconds 3'], { stdio: 'ignore' });
76
- else spawnSync('sleep', ['3']);
77
- }
78
- }
79
- if (!ok) {
80
- console.log('\n\u2717 g\u00FCncelleme ba\u015Far\u0131s\u0131z \u2014 elle: npm install -g beast-agent@latest');
81
- if (isWin) spawnSync('cmd.exe', ['/c', 'pause'], { stdio: 'inherit', shell: false });
82
- process.exit(1);
83
- }
84
- console.log('\n\u2713 beast-agent g\u00FCncellendi \u2014 uygulama ba\u015Flat\u0131l\u0131yor\u2026');
85
- launchDetached([]);
86
- if (isWin) spawnSync('cmd.exe', ['/c', 'timeout /t 3'], { stdio: 'ignore' });
87
- process.exit(0);
88
- }
89
-
90
- /* SearXNG: yerel arama motoru — kur + arka planda başlat (127.0.0.1:8888)
91
- beast searxng → gerekirse kur, başlat
92
- beast searxng status → durum
93
- beast searxng stop → kulla */
94
- if (process.argv[2] === 'searxng') {
95
- require('../src/agent/searxng').cli(process.argv.slice(3)).catch((e) => {
96
- console.error('\u2717 ' + String((e && e.message) || e));
97
- process.exit(1);
98
- });
99
- return;
100
- }
101
-
102
- /* detached başlatıcı + kendini onaran electron:
103
- taze makinalarda npm postinstall sırasında electron binary indirmesi
104
- sessizce başarısız olmuş olabilir → burada otomatik tamir edilir. */
105
- function launchDetached(extraArgs) {
106
- let electron = null;
107
- try { electron = require('electron'); } catch {}
108
- if (typeof electron !== 'string') {
109
- let fix = null;
110
- try { fix = require('../scripts/fix-electron'); } catch {}
111
- if (fix) {
112
- console.log('\u27F3 electron \u00e7al\u0131\u015Fma dosyalar\u0131 eksik bulundu \u2014 otomatik onar\u0131l\u0131yor\u2026');
113
- const r = fix.repair({ quiet: false });
114
- if (r.ok && !r.skipped) console.log('\u2713 electron onar\u0131ld\u0131');
115
- if (r.ok) {
116
- try { electron = require('electron'); } catch {}
117
- }
118
- }
119
- }
120
- if (typeof electron !== 'string') {
121
- console.log('\n\u2717 Electron \u00e7al\u0131\u015Fma dosyas\u0131 kurulamad\u0131.');
122
- console.log(' Elle \u00e7\u00f6z\u00fcm \u2014 \u015fu 2 komutu \u00e7al\u0131\u015Ft\u0131r:');
123
- console.log(' npm config set ignore-scripts false');
124
- console.log(' npm install -g beast-agent');
125
- return false;
126
- }
127
- const child = spawn(electron, [path.resolve(__dirname, '..'), ...extraArgs], {
128
- stdio: 'ignore',
129
- detached: true,
130
- /* windowsHide KULLANMA: Chromium ilk pencereyi gizli başlatıyor (tray-only bug) */
131
- });
132
- child.unref();
133
- return true;
134
- }
135
-
136
- if (!launchDetached(process.argv.slice(2))) process.exit(1);
137
- process.exit(0);
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /* Beast Agent global npm launcher (`beast` short alias points to the same script):
5
+ `beast` / `beast-agent` → launches the app detached, frees the terminal immediately
6
+ `beast update` → installs the latest version from npm (run while the app is closed) */
7
+
8
+ const { spawn, spawnSync } = require('child_process');
9
+ const path = require('path');
10
+ const fs = require('fs');
11
+ const os = require('os');
12
+
13
+ /* uninstall mode: removes the app but KEEPS YOUR PERSONAL DATA
14
+ (%APPDATA%\beast: config.yaml, .env, sessions, memory, WhatsApp pairing, backups) */
15
+ if (process.argv[2] === 'uninstall') {
16
+ const isWin = process.platform === 'win32';
17
+ console.log('Uninstalling Beast Agent\u2026');
18
+ if (isWin) {
19
+ /* stop running instances */
20
+ try {
21
+ spawnSync('powershell.exe', ['-NoProfile', '-Command',
22
+ "Get-Process electron -ErrorAction SilentlyContinue | Where-Object { $_.Path -like '*node_modules*beast-agent*' } | Stop-Process -Force"],
23
+ { stdio: 'ignore' });
24
+ console.log('\u2022 stopped running Beast instances (if any)');
25
+ } catch {}
26
+ /* remove the startup entry — only if it points to beast-agent */
27
+ try {
28
+ spawnSync('powershell.exe', ['-NoProfile', '-Command',
29
+ "$k='HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run';" +
30
+ "foreach($n in (Get-Item $k -ErrorAction SilentlyContinue).GetValueNames()){" +
31
+ "$v=(Get-ItemProperty $k).$n; if($v -like '*node_modules*beast-agent*'){ Remove-ItemProperty -Path $k -Name $n; Write-Host '\u2022 startup entry removed' } }"],
32
+ { stdio: 'inherit' });
33
+ } catch {}
34
+ /* remove the desktop shortcut (real Desktop path: may be under OneDrive) */
35
+ try {
36
+ spawnSync('powershell.exe', ['-NoProfile', '-Command',
37
+ "$d=[Environment]::GetFolderPath('Desktop'); if(Test-Path \"$d\\Beast Agent.lnk\"){ Remove-Item \"$d\\Beast Agent.lnk\" -Force; Write-Host '\u2022 desktop shortcut removed' }"],
38
+ { stdio: 'inherit' });
39
+ } catch {}
40
+ } else {
41
+ try { spawnSync('pkill', ['-f', 'node_modules/beast-agent'], { stdio: 'ignore' }); } catch {}
42
+ }
43
+ console.log('\u2022 removing the npm package\u2026');
44
+ const ur = spawnSync('npm', ['uninstall', '-g', 'beast-agent'], { stdio: 'inherit', shell: isWin });
45
+ console.log('\n\u2713 Beast Agent uninstalled.');
46
+ console.log('\u2139 Your personal data is preserved \u2014 %APPDATA%\\beast');
47
+ console.log(' (config.yaml, .env, sessions, memory, WhatsApp pairing, encrypted backups)');
48
+ console.log(' To reinstall: npm install -g beast-agent');
49
+ process.exit(ur.status || 0);
50
+ }
51
+
52
+ /* update mode: stop the running Beast (avoid file-lock EBUSY) → update npm (visible progress) → relaunch.
53
+ This command is run by the update button inside a VISIBLE cmd window;
54
+ it also works from a terminal — npm install output streams on screen. */
55
+ if (process.argv[2] === 'update') {
56
+ const isWin = process.platform === 'win32';
57
+ console.log('\u27F3 Updating beast-agent\u2026');
58
+ if (isWin) {
59
+ try {
60
+ spawnSync('powershell.exe', ['-NoProfile', '-Command',
61
+ "Get-Process electron -ErrorAction SilentlyContinue | Where-Object { $_.Path -like '*node_modules*beast-agent*' } | Stop-Process -Force"],
62
+ { stdio: 'ignore' });
63
+ console.log('\u2022 stopped running Beast instances (if any)');
64
+ } catch {}
65
+ } else {
66
+ try { spawnSync('pkill', ['-f', 'node_modules/beast-agent'], { stdio: 'ignore' }); } catch {}
67
+ }
68
+ /* file locks (EBUSY) sometimes fail on the first attempt — 5 tries */
69
+ let ok = false;
70
+ for (let i = 1; i <= 5 && !ok; i++) {
71
+ const r = spawnSync('npm', ['install', '-g', 'beast-agent@latest'], { stdio: 'inherit', shell: isWin });
72
+ ok = r.status === 0;
73
+ if (!ok && i < 5) {
74
+ console.log(` \u2022 attempt ${i}/5 failed (possible file lock) \u2014 retrying in 3s\u2026`);
75
+ if (isWin) spawnSync('powershell.exe', ['-NoProfile', '-Command', 'Start-Sleep -Seconds 3'], { stdio: 'ignore' });
76
+ else spawnSync('sleep', ['3']);
77
+ }
78
+ }
79
+ if (!ok) {
80
+ console.log('\n\u2717 update failed \u2014 manually: npm install -g beast-agent@latest');
81
+ if (isWin) spawnSync('cmd.exe', ['/c', 'pause'], { stdio: 'inherit', shell: false });
82
+ process.exit(1);
83
+ }
84
+ console.log('\n\u2713 beast-agent updated \u2014 launching the app\u2026');
85
+ launchDetached([]);
86
+ if (isWin) spawnSync('cmd.exe', ['/c', 'timeout /t 3'], { stdio: 'ignore' });
87
+ process.exit(0);
88
+ }
89
+
90
+ /* SearXNG: local search engine — install + start in the background (127.0.0.1:8888)
91
+ beast searxng → install if needed, then start
92
+ beast searxng status → status
93
+ beast searxng stop → stop */
94
+ if (process.argv[2] === 'searxng') {
95
+ require('../src/agent/searxng').cli(process.argv.slice(3)).catch((e) => {
96
+ console.error('\u2717 ' + String((e && e.message) || e));
97
+ process.exit(1);
98
+ });
99
+ return;
100
+ }
101
+
102
+ /* detached launcher + self-healing electron:
103
+ on fresh machines the electron binary download during npm postinstall
104
+ may have silently failed → it is repaired automatically here. */
105
+ function launchDetached(extraArgs) {
106
+ let electron = null;
107
+ try { electron = require('electron'); } catch {}
108
+ if (typeof electron !== 'string') {
109
+ let fix = null;
110
+ try { fix = require('../scripts/fix-electron'); } catch {}
111
+ if (fix) {
112
+ console.log('\u27F3 electron runtime files are missing \u2014 repairing automatically\u2026');
113
+ const r = fix.repair({ quiet: false });
114
+ if (r.ok && !r.skipped) console.log('\u2713 electron repaired');
115
+ if (r.ok) {
116
+ try { electron = require('electron'); } catch {}
117
+ }
118
+ }
119
+ }
120
+ if (typeof electron !== 'string') {
121
+ console.log('\n\u2717 Electron runtime could not be installed.');
122
+ console.log(' Manual fix \u2014 run these 2 commands:');
123
+ console.log(' npm config set ignore-scripts false');
124
+ console.log(' npm install -g beast-agent');
125
+ return false;
126
+ }
127
+ const child = spawn(electron, [path.resolve(__dirname, '..'), ...extraArgs], {
128
+ stdio: 'ignore',
129
+ detached: true,
130
+ /* do NOT use windowsHide: Chromium starts the first window hidden (tray-only bug) */
131
+ });
132
+ child.unref();
133
+ return true;
134
+ }
135
+
136
+ if (!launchDetached(process.argv.slice(2))) process.exit(1);
137
+ process.exit(0);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "beast-agent",
3
3
  "productName": "Beast Agent",
4
- "version": "2.44.0",
4
+ "version": "2.44.1",
5
5
  "description": "Ultra-fast local agent shell for Windows.",
6
6
  "author": "algokodcom (AlgoKod)",
7
7
  "license": "MIT",
@@ -1,137 +1,137 @@
1
- 'use strict';
2
-
3
- /* Beast Agent — Dağıtım / Senkron Sistemi
4
- Tek komutla tam sürüm akışı (EXE/INSTALLER YOK — npm + kaynak dağıtımı):
5
- npm run release → otomatik patch bump (0.20.0 → 0.20.1)
6
- npm run release -- minor → 0.21.0
7
- npm run release -- 0.22.0 → belirli sürüm
8
-
9
- Adımlar:
10
- 1) package.json sürümü yükselt
11
- 2) commit + tag + push (main + tag)
12
- 3) GitHub Release (yalnız kaynak — exe/asset yüklenmez)
13
- 4) npm publish (NPM_TOKEN env var ise; yoksa atlar ve uyarır)
14
- 5) OneDrive yedek klasörüne kaynak kopyası (beast-v< sürüm >)
15
- */
16
-
17
- const fs = require('fs');
18
- const path = require('path');
19
- const { execSync } = require('child_process');
20
-
21
- const ROOT = path.join(__dirname, '..');
22
- const ONE_DRIVE_DIR = process.env.BEAST_BACKUP_DIR
23
- || 'C:\\Users\\batuh\\OneDrive\\Masaüstü\\Beast Agent';
24
-
25
- const step = (msg) => console.log('\n\x1b[1m▶ ' + msg + '\x1b[0m');
26
- const ok = (msg) => console.log(' \x1b[32m✓\x1b[0m ' + msg);
27
- const warn = (msg) => console.log(' \x1b[33m!\x1b[0m ' + msg);
28
- const fail = (msg) => { console.error(' \x1b[31m✗ ' + msg + '\x1b[0m'); process.exit(1); };
29
-
30
- function run(cmd, opts = {}) {
31
- /* stdio:'inherit' iken execSync null döner — trim patlamasın */
32
- return String(execSync(cmd, { cwd: ROOT, stdio: opts.inherit ? 'inherit' : 'pipe', encoding: 'utf8', ...opts }) ?? '').trim();
33
- }
34
-
35
- function bump(version, kind) {
36
- const [ma, mi, pa] = version.split('.').map(Number);
37
- if (kind === 'major') return `${ma + 1}.0.0`;
38
- if (kind === 'minor') return `${ma}.${mi + 1}.0`;
39
- return `${ma}.${mi}.${pa + 1}`;
40
- }
41
-
42
- /* ---------- argümanlar ---------- */
43
- const arg = process.argv[2] || 'patch';
44
- const pkgPath = path.join(ROOT, 'package.json');
45
- const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
46
- const current = pkg.version;
47
- const next = ['major', 'minor', 'patch'].includes(arg) ? bump(current, arg) : arg.replace(/^v/, '');
48
- if (!/^\d+\.\d+\.\d+$/.test(next)) fail('geçersiz sürüm: ' + next);
49
- const tag = 'v' + next;
50
-
51
- console.log(`\x1b[1mBeast Agent release: ${current} → ${next}\x1b[0m`);
52
-
53
- /* ---------- 1) sürüm bump ---------- */
54
- step('1/5 sürüm yükselt: ' + current + ' → ' + next);
55
- pkg.version = next;
56
- fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 4) + '\n');
57
- ok('package.json → ' + next);
58
-
59
- /* ---------- 2) commit + push ---------- */
60
- step('2/5 git: commit + tag + push');
61
- try {
62
- run('git add -A');
63
- run(`git commit -m "v${next}"`);
64
- } catch { warn('commit edilecek değişiklik yoktu'); }
65
- try { run(`git tag ${tag} -f`); } catch {}
66
- run('git push origin main');
67
- run(`git push origin ${tag}`);
68
- ok('pushed: main + ' + tag);
69
-
70
- /* ---------- 3) GitHub Release (kaynak — exe yok) ---------- */
71
- step('3/5 GitHub Release ' + tag);
72
- const gh = process.env.GH || 'gh';
73
- let ghOk = false;
74
- try {
75
- const notes = [
76
- `## Beast Agent ${tag}`,
77
- '',
78
- '- \`npm i -g beast-agent@\`' + next,
79
- '',
80
- 'Dağıtım npm üzerinden yapılır — exe/installer sürümü kaldırıldı.',
81
- 'Tam değişiklik listesi: commit geçmişi.',
82
- ].join('\n');
83
- const notesFile = path.join(ROOT, 'dist', 'release-notes.md');
84
- fs.mkdirSync(path.dirname(notesFile), { recursive: true });
85
- fs.writeFileSync(notesFile, notes);
86
- try { run(`${gh} release delete ${tag} --yes --cleanup-tag`); } catch {}
87
- run(`${gh} release create ${tag} --title "Beast Agent ${tag}" --notes-file "${notesFile}"`, { inherit: true });
88
- ok('release yayında: https://github.com/algokodcom/beast-agent/releases/tag/' + tag);
89
- ghOk = true;
90
- } catch (e) {
91
- /* gh kurulu değil / oturum yok → yayın atlanır, akış npm ile sürer */
92
- warn('GitHub release atlandı (gh yok veya hata): ' + String(e).slice(0, 160));
93
- }
94
- if (!ghOk) {
95
- warn('GitHub Release elle açılabilir: https://github.com/algokodcom/beast-agent/releases/new?tag=' + tag);
96
- }
97
-
98
- /* ---------- 4) npm publish ---------- */
99
- step('4/5 npm publish');
100
- if (process.env.NPM_TOKEN) {
101
- try {
102
- run(`npm publish --//registry.npmjs.org/:_authToken=${process.env.NPM_TOKEN}`, { inherit: true });
103
- ok('npm: beast-agent@' + next);
104
- } catch (e) {
105
- warn('npm publish başarısız (sürüm zaten var olabilir): ' + String(e).slice(0, 200));
106
- }
107
- } else {
108
- warn('NPM_TOKEN env yok — npm adımı atlandı.');
109
- warn('Elle: set NPM_TOKEN=<token> && npm publish');
110
- }
111
-
112
- /* ---------- 5) OneDrive kaynak yedeği ---------- */
113
- step('5/5 OneDrive yedek (beast-v' + next + ')');
114
- try {
115
- const dest = path.join(ONE_DRIVE_DIR, 'beast-v' + next);
116
- fs.mkdirSync(dest, { recursive: true });
117
- /* robocopy 0-7 arası TÜM çıkış kodları başarıdır (1 = dosya kopyalandı);
118
- execSync 0 dışını hata sanır — kodu burada yut, gerçek hatada (>7) dur */
119
- try {
120
- execSync(
121
- `robocopy "${ROOT}" "${dest}" /E /XD node_modules dist "beast agent web" .git /NFL /NDL /NJH`,
122
- { cwd: ROOT, stdio: 'pipe' }
123
- );
124
- } catch (e) {
125
- const code = e && e.status;
126
- if (!(typeof code === 'number' && code < 8)) throw e;
127
- }
128
- const info = path.join(dest, `YEDEK-BILGI-v${next}.txt`);
129
- fs.writeFileSync(info, `BEAST AGENT v${next} — ${new Date().toLocaleString('tr-TR')}\nKaynak: ${ROOT}\nGitHub: https://github.com/algokodcom/beast-agent/releases/tag/${tag}\nnpm: https://www.npmjs.com/package/beast-agent\n`);
130
- ok(dest);
131
- } catch (e) {
132
- warn('OneDrive yedeği atlandı: ' + String(e).slice(0, 160));
133
- }
134
-
135
- console.log(`\n\x1b[1m\x1b[32m✓ v${next} dağıtımı tamam.\x1b[0m`);
136
- console.log(' GitHub : https://github.com/algokodcom/beast-agent/releases/tag/' + tag);
137
- console.log(' npm : https://www.npmjs.com/package/beast-agent');
1
+ 'use strict';
2
+
3
+ /* Beast Agent — Release / Sync System
4
+ Full release flow with a single command (NO EXE/INSTALLER — npm + source distribution):
5
+ npm run release → automatic patch bump (0.20.0 → 0.20.1)
6
+ npm run release -- minor → 0.21.0
7
+ npm run release -- 0.22.0 → specific version
8
+
9
+ Steps:
10
+ 1) bump the package.json version
11
+ 2) commit + tag + push (main + tag)
12
+ 3) GitHub Release (source only — no exe/asset upload)
13
+ 4) npm publish (only if NPM_TOKEN env var is set; otherwise skipped with a warning)
14
+ 5) source copy into the OneDrive backup folder (beast-v< version >)
15
+ */
16
+
17
+ const fs = require('fs');
18
+ const path = require('path');
19
+ const { execSync } = require('child_process');
20
+
21
+ const ROOT = path.join(__dirname, '..');
22
+ const ONE_DRIVE_DIR = process.env.BEAST_BACKUP_DIR
23
+ || 'C:\\Users\\batuh\\OneDrive\\Masaüstü\\Beast Agent';
24
+
25
+ const step = (msg) => console.log('\n\x1b[1m▶ ' + msg + '\x1b[0m');
26
+ const ok = (msg) => console.log(' \x1b[32m✓\x1b[0m ' + msg);
27
+ const warn = (msg) => console.log(' \x1b[33m!\x1b[0m ' + msg);
28
+ const fail = (msg) => { console.error(' \x1b[31m✗ ' + msg + '\x1b[0m'); process.exit(1); };
29
+
30
+ function run(cmd, opts = {}) {
31
+ /* with stdio:'inherit' execSync returns null — avoid crashing on trim */
32
+ return String(execSync(cmd, { cwd: ROOT, stdio: opts.inherit ? 'inherit' : 'pipe', encoding: 'utf8', ...opts }) ?? '').trim();
33
+ }
34
+
35
+ function bump(version, kind) {
36
+ const [ma, mi, pa] = version.split('.').map(Number);
37
+ if (kind === 'major') return `${ma + 1}.0.0`;
38
+ if (kind === 'minor') return `${ma}.${mi + 1}.0`;
39
+ return `${ma}.${mi}.${pa + 1}`;
40
+ }
41
+
42
+ /* ---------- arguments ---------- */
43
+ const arg = process.argv[2] || 'patch';
44
+ const pkgPath = path.join(ROOT, 'package.json');
45
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
46
+ const current = pkg.version;
47
+ const next = ['major', 'minor', 'patch'].includes(arg) ? bump(current, arg) : arg.replace(/^v/, '');
48
+ if (!/^\d+\.\d+\.\d+$/.test(next)) fail('invalid version: ' + next);
49
+ const tag = 'v' + next;
50
+
51
+ console.log(`\x1b[1mBeast Agent release: ${current} → ${next}\x1b[0m`);
52
+
53
+ /* ---------- 1) version bump ---------- */
54
+ step('1/5 bump version: ' + current + ' → ' + next);
55
+ pkg.version = next;
56
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 4) + '\n');
57
+ ok('package.json → ' + next);
58
+
59
+ /* ---------- 2) commit + push ---------- */
60
+ step('2/5 git: commit + tag + push');
61
+ try {
62
+ run('git add -A');
63
+ run(`git commit -m "v${next}"`);
64
+ } catch { warn('there were no changes to commit'); }
65
+ try { run(`git tag ${tag} -f`); } catch {}
66
+ run('git push origin main');
67
+ run(`git push origin ${tag}`);
68
+ ok('pushed: main + ' + tag);
69
+
70
+ /* ---------- 3) GitHub Release (source — no exe) ---------- */
71
+ step('3/5 GitHub Release ' + tag);
72
+ const gh = process.env.GH || 'gh';
73
+ let ghOk = false;
74
+ try {
75
+ const notes = [
76
+ `## Beast Agent ${tag}`,
77
+ '',
78
+ '- `npm i -g beast-agent@' + next + '`',
79
+ '',
80
+ 'Distribution is done via npm — the exe/installer release has been removed.',
81
+ 'Full changelog: commit history.',
82
+ ].join('\n');
83
+ const notesFile = path.join(ROOT, 'dist', 'release-notes.md');
84
+ fs.mkdirSync(path.dirname(notesFile), { recursive: true });
85
+ fs.writeFileSync(notesFile, notes);
86
+ try { run(`${gh} release delete ${tag} --yes --cleanup-tag`); } catch {}
87
+ run(`${gh} release create ${tag} --title "Beast Agent ${tag}" --notes-file "${notesFile}"`, { inherit: true });
88
+ ok('release published: https://github.com/algokodcom/beast-agent/releases/tag/' + tag);
89
+ ghOk = true;
90
+ } catch (e) {
91
+ /* gh missing / not logged in → skip the release, continue with npm */
92
+ warn('GitHub release skipped (gh missing or error): ' + String(e).slice(0, 160));
93
+ }
94
+ if (!ghOk) {
95
+ warn('GitHub Release can be created manually: https://github.com/algokodcom/beast-agent/releases/new?tag=' + tag);
96
+ }
97
+
98
+ /* ---------- 4) npm publish ---------- */
99
+ step('4/5 npm publish');
100
+ if (process.env.NPM_TOKEN) {
101
+ try {
102
+ run(`npm publish --//registry.npmjs.org/:_authToken=${process.env.NPM_TOKEN}`, { inherit: true });
103
+ ok('npm: beast-agent@' + next);
104
+ } catch (e) {
105
+ warn('npm publish failed (the version may already exist): ' + String(e).slice(0, 200));
106
+ }
107
+ } else {
108
+ warn('NPM_TOKEN env is missing — npm step skipped.');
109
+ warn('Manually: set NPM_TOKEN=<token> && npm publish');
110
+ }
111
+
112
+ /* ---------- 5) OneDrive source backup ---------- */
113
+ step('5/5 OneDrive backup (beast-v' + next + ')');
114
+ try {
115
+ const dest = path.join(ONE_DRIVE_DIR, 'beast-v' + next);
116
+ fs.mkdirSync(dest, { recursive: true });
117
+ /* every robocopy exit code 0-7 is a success (1 = files copied);
118
+ execSync treats anything other than 0 as an error — swallow the code here, stop only on real failure (>7) */
119
+ try {
120
+ execSync(
121
+ `robocopy "${ROOT}" "${dest}" /E /XD node_modules dist "beast agent web" .git /NFL /NDL /NJH`,
122
+ { cwd: ROOT, stdio: 'pipe' }
123
+ );
124
+ } catch (e) {
125
+ const code = e && e.status;
126
+ if (!(typeof code === 'number' && code < 8)) throw e;
127
+ }
128
+ const info = path.join(dest, `BACKUP-INFO-v${next}.txt`);
129
+ fs.writeFileSync(info, `BEAST AGENT v${next} — ${new Date().toLocaleString('en-US')}\nSource: ${ROOT}\nGitHub: https://github.com/algokodcom/beast-agent/releases/tag/${tag}\nnpm: https://www.npmjs.com/package/beast-agent\n`);
130
+ ok(dest);
131
+ } catch (e) {
132
+ warn('OneDrive backup skipped: ' + String(e).slice(0, 160));
133
+ }
134
+
135
+ console.log(`\n\x1b[1m\x1b[32m✓ v${next} release complete.\x1b[0m`);
136
+ console.log(' GitHub : https://github.com/algokodcom/beast-agent/releases/tag/' + tag);
137
+ console.log(' npm : https://www.npmjs.com/package/beast-agent');
@@ -1473,7 +1473,7 @@ class Engine {
1473
1473
  delete s.notes;
1474
1474
  delete s.notesAt;
1475
1475
  delete s.summary; // özet de sıfırlanır — taze başlangıç
1476
- this.todos.set(sid, []);
1476
+ this.todos.set(sid, s.todos || []);
1477
1477
  this.emit({ type: 'sessions' });
1478
1478
  return true;
1479
1479
  }
@@ -4140,7 +4140,7 @@ class Engine {
4140
4140
  /* GÖREV LİSTESİ DİSİPLİNİ: ajan işi bitti sanıyor ama listede hâlâ
4141
4141
  bekleyen/aktif madde varsa BİR KEZ hatırlat ve tura devam et —
4142
4142
  liste ya tamamlanmalı ya kalan maddeler listeden düşürülmeli. */
4143
- const todos = session.todos || this.todos.get(sid) || [];
4143
+ const todos = this.todos.has(sid) ? this.todos.get(sid) || [] : session.todos || [];
4144
4144
  const pending = todos.filter((t) => t && t.status !== 'done');
4145
4145
  if (pending.length && !nudged) {
4146
4146
  nudged = true;
@@ -5370,6 +5370,8 @@ const skills = require('./skills');
5370
5370
  const items = sanitizeTodoItems(args.items);
5371
5371
  this._tagTodoIds(sessionId, items); /* her madde kalıcı ID taşır — geri alma buna bağlanır */
5372
5372
  this.todos.set(sessionId, items);
5373
+ const tSession = this.cache.get(String(sessionId));
5374
+ if (tSession) tSession.todos = items;
5373
5375
  try {
5374
5376
  fs.appendFileSync(
5375
5377
  this._file(sessionId),
@@ -6550,6 +6552,8 @@ Engine.prototype.undoTodo = function (sid, todoId) {
6550
6552
  if (t && t.id === id && t.status === 'done') t.status = 'pending';
6551
6553
  }
6552
6554
  this.todos.set(key, todos);
6555
+ const uSession = this.cache.get(key);
6556
+ if (uSession) uSession.todos = todos;
6553
6557
  try {
6554
6558
  fs.appendFileSync(this._file(key), JSON.stringify({ t: 'todo', items: todos }) + '\n');
6555
6559
  } catch {}
@@ -6584,6 +6588,8 @@ Engine.prototype.clearTodos = function (sid) {
6584
6588
  }
6585
6589
  const prev = this.todos.get(key) || [];
6586
6590
  this.todos.set(key, []);
6591
+ const cSession = this.cache.get(key);
6592
+ if (cSession) cSession.todos = [];
6587
6593
  try {
6588
6594
  fs.appendFileSync(this._file(key), JSON.stringify({ t: 'todo', items: [] }) + '\n');
6589
6595
  } catch {}
@@ -1,14 +1,14 @@
1
1
  'use strict';
2
2
 
3
- /* SearXNG — yerel metasearch entegrasyonu (github.com/searxng/searxng)
4
- SearXNG resmi olarak Linux/Docker hedefler; Windows'ta `import pwd`
5
- yüzünden patlar. Bu modül Beast'ın GÖMÜLÜ Python'ına gerçek searxng'yi
6
- (GitHub master) kurar + pwd shim'i yazar + 127.0.0.1:8888'de arka planda
7
- çalıştırır. Arama zinciri 'searxng' motorunu yalnız AYAKTAYSA kullanır.
3
+ /* SearXNG — local metasearch integration (github.com/searxng/searxng)
4
+ SearXNG officially targets Linux/Docker; on Windows it crashes because of
5
+ `import pwd`. This module installs the real searxng (GitHub master) into
6
+ Beast's EMBEDDED Python + writes a pwd shim + runs it in the background on
7
+ 127.0.0.1:8888. The search chain only uses the 'searxng' engine while it is UP.
8
8
 
9
- CLI: beast searxng → gerekirse kur + başlat
10
- beast searxng status → durum
11
- beast searxng stop → kulla */
9
+ CLI: beast searxng → install if needed + start
10
+ beast searxng status → status
11
+ beast searxng stop → stop */
12
12
 
13
13
  const fs = require('fs');
14
14
  const path = require('path');
@@ -20,7 +20,7 @@ const PKG_URL = 'https://github.com/searxng/searxng/archive/refs/heads/master.zi
20
20
  const GETPIP_URL = 'https://bootstrap.pypa.io/get-pip.py';
21
21
  const DEFAULT_URL = 'http://127.0.0.1:8888';
22
22
 
23
- /* ---------- yollar ---------- */
23
+ /* ---------- paths ---------- */
24
24
 
25
25
  function beastAppDir() {
26
26
  if (process.env.BEAST_DATA) return process.env.BEAST_DATA;
@@ -40,7 +40,7 @@ function runPyPath() { return path.join(dir(), 'run.py'); }
40
40
  function pidPath() { return path.join(dir(), 'server.pid'); }
41
41
  function pyExe() { return path.join(beastAppDir(), 'py', 'python.exe'); }
42
42
 
43
- /* ---------- durum yoklama (cache'li) ---------- */
43
+ /* ---------- status probe (cached) ---------- */
44
44
 
45
45
  let _probe = { at: 0, up: false, url: '' };
46
46
  const PROBE_UP_TTL = 5 * 60 * 1000;
@@ -64,11 +64,11 @@ async function isUp(baseUrl = DEFAULT_URL, { force = false } = {}) {
64
64
  return up;
65
65
  }
66
66
 
67
- /* ---------- arama (zincir motoru) ---------- */
67
+ /* ---------- search (chain engine) ---------- */
68
68
 
69
69
  async function search(query, { maxResults = 8, signal, baseUrl } = {}) {
70
70
  const base = String(baseUrl || process.env.BEAST_SEARXNG_URL || DEFAULT_URL).replace(/\/+$/, '');
71
- if (!(await isUp(base))) return null; // ayakta değil → zincir sıradaki motora geçer
71
+ if (!(await isUp(base))) return null; // not up → the chain moves to the next engine
72
72
  try {
73
73
  const sig =
74
74
  signal && typeof AbortSignal !== 'undefined' && AbortSignal.any
@@ -100,7 +100,7 @@ async function search(query, { maxResults = 8, signal, baseUrl } = {}) {
100
100
  }
101
101
  }
102
102
 
103
- /* ---------- kurulum ---------- */
103
+ /* ---------- installation ---------- */
104
104
 
105
105
  function sh(exe, args, timeoutMs = 600000) {
106
106
  return new Promise((resolve, reject) => {
@@ -116,7 +116,7 @@ function sh(exe, args, timeoutMs = 600000) {
116
116
 
117
117
  async function downloadTo(url, dest) {
118
118
  const r = await fetch(url, { signal: AbortSignal.timeout(120000) });
119
- if (!r.ok) throw new Error(`indirme başarısız: HTTP ${r.status}`);
119
+ if (!r.ok) throw new Error(`download failed: HTTP ${r.status}`);
120
120
  fs.writeFileSync(dest, Buffer.from(await r.arrayBuffer()));
121
121
  }
122
122
 
@@ -124,7 +124,7 @@ function sitePackagesDir(py) {
124
124
  return sh(py, ['-c', 'import sysconfig;print(sysconfig.get_paths()["purelib"])']).then((s) => s.trim());
125
125
  }
126
126
 
127
- /* gömülü python'un ._pth dosyasında `import site` açık değilse pip/paketler görünmez */
127
+ /* if `import site` is not enabled in the embedded python's ._pth file, pip/packages are invisible */
128
128
  function fixEmbeddedPth(py) {
129
129
  try {
130
130
  const dirPy = path.dirname(py);
@@ -145,14 +145,14 @@ async function ensurePip(py, onLog) {
145
145
  await sh(py, ['-m', 'pip', '--version'], 60000);
146
146
  return;
147
147
  } catch {}
148
- onLog('pip kuruluyor…');
148
+ onLog('installing pip…');
149
149
  const gp = path.join(os.tmpdir(), 'beast-get-pip.py');
150
150
  await downloadTo(GETPIP_URL, gp);
151
151
  await sh(py, [gp, '--no-warn-script-location'], 300000);
152
152
  fixEmbeddedPth(py);
153
153
  }
154
154
 
155
- /** Tam kurulum — `beast searxng` komutunun yaptığı iş. */
155
+ /** Full installation — what the `beast searxng` command does. */
156
156
  async function install({ onLog } = {}) {
157
157
  const log = (m) => { try { (onLog || ((s) => console.log(' • ' + s)))(m); } catch {} };
158
158
  const tools = require('./tools');
@@ -161,22 +161,22 @@ async function install({ onLog } = {}) {
161
161
  log('python: ' + py);
162
162
 
163
163
  await ensurePip(py, log);
164
- log('setuptools/wheel/tzdata kuruluyor…');
164
+ log('installing setuptools/wheel/tzdata…');
165
165
  await sh(py, ['-m', 'pip', 'install', '--no-warn-script-location', 'setuptools', 'wheel', 'tzdata'], 600000);
166
166
 
167
- log('searxng bağımlılıkları indiriliyor (~40 MB)…');
167
+ log('downloading searxng dependencies (~40 MB)…');
168
168
  const reqs = path.join(os.tmpdir(), 'beast-searxng-requirements.txt');
169
169
  await downloadTo(REQS_URL, reqs);
170
170
  await sh(py, ['-m', 'pip', 'install', '--no-warn-script-location', '-r', reqs], 900000);
171
171
 
172
- log('searxng motoru kuruluyor…');
172
+ log('installing the searxng engine…');
173
173
  await sh(py, ['-m', 'pip', 'install', '--no-warn-script-location', '--no-build-isolation', PKG_URL], 900000);
174
174
 
175
- /* pwd shim — searxng/valkeydb.py unix socket sahipliği için pwd import eder */
175
+ /* pwd shim — searxng/valkeydb.py imports pwd for unix socket ownership */
176
176
  const sp = (await sitePackagesDir(py)) || path.join(path.dirname(py), 'Lib', 'site-packages');
177
177
  const shim = [
178
- '"""Windows shim: SearXNG valkeydb.py yalnizca unix-socket sahipligi icin pwd',
179
- 'kullanir; Windows\'ta valkey devre disi oldugundan donuk yanit yeterlidir."""',
178
+ '"""Windows shim: SearXNG valkeydb.py only uses pwd for unix-socket ownership;',
179
+ 'valkey is disabled on Windows, so a stub response is sufficient."""',
180
180
  'import os',
181
181
  '',
182
182
  'class _Pw:',
@@ -203,7 +203,7 @@ async function install({ onLog } = {}) {
203
203
  ].join('\n');
204
204
  fs.writeFileSync(path.join(sp, 'pwd.py'), shim, 'utf8');
205
205
 
206
- /* ayarlar + çalıştırıcı */
206
+ /* settings + runner */
207
207
  const secret = 'beast-' + Math.random().toString(36).slice(2, 14);
208
208
  fs.writeFileSync(
209
209
  settingsPath(),
@@ -225,11 +225,11 @@ async function install({ onLog } = {}) {
225
225
  );
226
226
  fs.writeFileSync(runPyPath(), 'from searx.webapp import run; run()', 'utf8');
227
227
  resetProbeCache();
228
- log('kurulum tamam');
228
+ log('installation complete');
229
229
  return { ok: true };
230
230
  }
231
231
 
232
- /* ---------- başlat / durdur / durum ---------- */
232
+ /* ---------- start / stop / status ---------- */
233
233
 
234
234
  function readPid() {
235
235
  try {
@@ -243,7 +243,7 @@ function readPid() {
243
243
  async function start({ installIfMissing = true, onLog } = {}) {
244
244
  if (await isUp(DEFAULT_URL, { force: true })) return { ok: true, already: true, url: DEFAULT_URL };
245
245
  if (!fs.existsSync(settingsPath()) || !fs.existsSync(runPyPath())) {
246
- if (!installIfMissing) return { ok: false, error: 'kurulu değil — önce: beast searxng' };
246
+ if (!installIfMissing) return { ok: false, error: 'not installed — first run: beast searxng' };
247
247
  await install({ onLog });
248
248
  }
249
249
  const tools = require('./tools');
@@ -256,17 +256,17 @@ async function start({ installIfMissing = true, onLog } = {}) {
256
256
  });
257
257
  try { fs.writeFileSync(pidPath(), String(child.pid)); } catch {}
258
258
  child.unref();
259
- /* ayağa kalkmasını bekle (ilk açılış motor listesini derler — birkaç sn) */
259
+ /* wait for it to come up (the first boot compiles the engine list — a few seconds) */
260
260
  for (let i = 0; i < 20; i++) {
261
261
  await new Promise((r) => setTimeout(r, 1000));
262
262
  if (await isUp(DEFAULT_URL, { force: true })) return { ok: true, url: DEFAULT_URL, pid: child.pid };
263
263
  }
264
- return { ok: false, error: 'searxng başlatılamadı (20 sn içinde yanıt yok)' };
264
+ return { ok: false, error: 'searxng failed to start (no response within 20s)' };
265
265
  }
266
266
 
267
267
  function stop() {
268
268
  const pid = readPid();
269
- if (!pid) return { ok: true, note: 'çalışmıyor' };
269
+ if (!pid) return { ok: true, note: 'not running' };
270
270
  try {
271
271
  execSync(`taskkill /PID ${pid} /T /F`, { stdio: 'ignore' });
272
272
  } catch {}
@@ -288,26 +288,26 @@ async function status() {
288
288
 
289
289
  async function cli(argv) {
290
290
  const sub = String(argv[0] || 'start').toLowerCase();
291
- console.log('\u27F3 SearXNG (yerel arama motoru)');
291
+ console.log('\u27F3 SearXNG (local search engine)');
292
292
  if (sub === 'stop') {
293
293
  const r = stop();
294
- console.log(r.ok ? '\u2713 durduruldu' : '\u2717 durdurulamadı');
294
+ console.log(r.ok ? '\u2713 stopped' : '\u2717 could not stop');
295
295
  process.exit(r.ok ? 0 : 1);
296
296
  }
297
297
  if (sub === 'status') {
298
298
  const s = await status();
299
- console.log(` kurulu : ${s.installed ? 'evet' : 'hayır'}`);
300
- console.log(` çalışıyor: ${s.up ? 'evet (' + s.url + ')' : 'hayır'}`);
299
+ console.log(` installed: ${s.installed ? 'yes' : 'no'}`);
300
+ console.log(` running : ${s.up ? 'yes (' + s.url + ')' : 'no'}`);
301
301
  process.exit(0);
302
302
  }
303
303
  /* start */
304
304
  const r = await start({ installIfMissing: true, onLog: (m) => console.log(' \u2022 ' + m) });
305
305
  if (r.ok) {
306
- console.log(r.already ? '\u2713 SearXNG zaten çalışıyor — ' + r.url : '\u2713 SearXNG başlatıldı — ' + r.url);
307
- console.log('\u2139 arama zincirinde kullanılmaya hazır (Ayarlar → Web Arama sırası)');
306
+ console.log(r.already ? '\u2713 SearXNG is already running — ' + r.url : '\u2713 SearXNG started — ' + r.url);
307
+ console.log('\u2139 ready to use in the search chain (Settings → Web Search order)');
308
308
  process.exit(0);
309
309
  }
310
- console.error('\u2717 ' + (r.error || 'başlatılamadı'));
310
+ console.error('\u2717 ' + (r.error || 'failed to start'));
311
311
  process.exit(1);
312
312
  }
313
313
 
package/src/main.js CHANGED
@@ -5104,7 +5104,12 @@ function resyncBrowserUi() {
5104
5104
  setTimeout(() => { try { layoutBrowser(); resyncBrowserUi(); } catch {} }, 80);
5105
5105
  setTimeout(() => { try { layoutBrowser(); resyncBrowserUi(); } catch {} }, 300);
5106
5106
  });
5107
- win.on('show', layoutBrowser);
5107
+ win.on('show', () => { layoutBrowser(); resyncBrowserUi(); });
5108
+ /* renderer her yeni yüklemede (açılış, reload, kurtarma) tarayıcı durumunu
5109
+ TAZE alır — açılışta kaçan 'browser' olayı dock'un ayrılmamasına yol açıyordu */
5110
+ win.webContents.on('did-finish-load', () => {
5111
+ try { resyncBrowserUi(); } catch {}
5112
+ });
5108
5113
  // X'e basınca gizle — tepside yaşamaya devam, WhatsApp bağlantısı sürer
5109
5114
  win.on('close', (e) => {
5110
5115
  if (!app.isQuitting) {
@@ -7594,6 +7599,23 @@ ipcMain.handle('browser:toggle', () => {
7594
7599
  /* göz ikonu: ajan tarayıcısını görünür/gizli yap — yalnızca gizleme özelliği
7595
7600
  (Ayarlar → Web Arama) açıkken etkilidir; özellik kapalıysa hep görünür */
7596
7601
  ipcMain.handle('browser:shown:get', () => ({ shown: !browserHeadlessPref(), enabled: browserHideEnabled() }));
7602
+ /* RENDERER AÇILIŞ SENKRONU: tarayıcı, renderer olayları dinlemeye başlamadan
7603
+ açılmış olabilir (açılışta oturum kurtarma/arka plan işi) — durum buradan
7604
+ PULL edilir; yoksa native view dock alanı ayrılmadan chat'in üzerinde kalır */
7605
+ ipcMain.handle('browser:state:get', () => {
7606
+ let url = '';
7607
+ try { url = browser.view && browser.open && !browser.view.webContents.isDestroyed() ? browser.view.webContents.getURL() : ''; } catch {}
7608
+ return {
7609
+ open: browser.open,
7610
+ visible: browser.visible,
7611
+ width: browserShownWidth(browserW()),
7612
+ phone: browser.phone,
7613
+ mobile: browser.mobile,
7614
+ phoneRect: browser.mobileRect,
7615
+ device: browser.deviceKey,
7616
+ url,
7617
+ };
7618
+ });
7597
7619
  ipcMain.handle('browser:shown:set', (_e, v) => {
7598
7620
  if (!browserHideEnabled()) return { shown: true, enabled: false };
7599
7621
  settings.browserHeadless = !v;
package/src/preload.js CHANGED
@@ -84,6 +84,7 @@ contextBridge.exposeInMainWorld('beast', {
84
84
  browserShownGet: () => ipcRenderer.invoke('browser:shown:get'),
85
85
  browserShownSet: (v) => ipcRenderer.invoke('browser:shown:set', v),
86
86
  browserHideSet: (v) => ipcRenderer.invoke('browser:hide:set', v),
87
+ browserStateGet: () => ipcRenderer.invoke('browser:state:get'),
87
88
  terminalToggle: () => ipcRenderer.invoke('terminal:toggle'),
88
89
  terminalRun: (cmd, shell) => ipcRenderer.invoke('terminal:run', { cmd, shell }),
89
90
  terminalStop: () => ipcRenderer.invoke('terminal:stop'),
@@ -5741,6 +5741,43 @@ function renderAgentsPane() {
5741
5741
 
5742
5742
  /* ---------------- events from engine ---------------- */
5743
5743
 
5744
+ /* Tarayıcı panel durumu: canlı 'browser' olayı + açılış senkronu (browserStateGet)
5745
+ AYNI yolu kullanır — native view ile dock alanı (--bw) asla ayrışmasın */
5746
+ function applyBrowserState(ev) {
5747
+ /* visible=false → ajan tarayıcıyı GİZLİ kullanıyor: UI yer açmaz */
5748
+ const shown = !!ev.open && ev.visible !== false;
5749
+ const wasShown = document.body.classList.contains('browser-open');
5750
+ document.body.classList.toggle('browser-open', shown);
5751
+ if (shown && ev.width) document.body.style.setProperty('--bw', ev.width + 'px');
5752
+ document.body.classList.toggle('phone-mode', !!ev.phone);
5753
+ if (els.bbPhone) els.bbPhone.classList.toggle('on', !!ev.phone);
5754
+ els.browserBar.hidden = !shown;
5755
+ els.bbResize.hidden = !shown;
5756
+ /* terminal artık ALT dock — tarayıcıyla birlikte yaşar, kapatılmaz */
5757
+ /* #19 tarayıcı açılınca paralel ajan konsolu (sağ panel) yerini bırakır;
5758
+ kapanınca önceki durumuna döner — istenirse railBtn ile elle açılır.
5759
+ GİZLİ ajan gezinmeleri (shown=false, wasShown=false) rail'e DOKUNMAZ —
5760
+ aksi halde paralel ajan konsolu kendi kendine kapanırdı */
5761
+ if (shown) {
5762
+ railPrefBeforeBrowser = !document.body.classList.contains('rail-hidden');
5763
+ toggleRail(true);
5764
+ } else if (wasShown) {
5765
+ toggleRail(!railPrefBeforeBrowser);
5766
+ }
5767
+ /* IDE modunda tarayıcı açılır/kapanır/genişlik değişirse row yeniden bölünür —
5768
+ editör + Beast Code ORTAK kırpılıp ORTAK açılır (kullanıcı payı korunur) */
5769
+ if (ideModeOn()) ideSplitApplyFrac();
5770
+ if (sbModeOn()) sbSplitApplyFrac();
5771
+ if (shown) {
5772
+ els.browserBtn.classList.add('on');
5773
+ if (ev.url && document.activeElement !== els.bbUrl) {
5774
+ els.bbUrl.value = ev.url.startsWith('https://duckduckgo.com/?q=') ? decodeURIComponent(ev.url.split('q=')[1] || '') : ev.url;
5775
+ }
5776
+ } else {
5777
+ els.browserBtn.classList.remove('on');
5778
+ }
5779
+ }
5780
+
5744
5781
  function onEvent(ev) {
5745
5782
  if (ev.type === 'notify-click') {
5746
5783
  /* toast tıklandı: ilgili panele atla */
@@ -5991,41 +6028,9 @@ function onEvent(ev) {
5991
6028
  soldaki klasör paneli ELLE yenilemeden canlı tazelenir */
5992
6029
  ideRefreshTree();
5993
6030
  break;
5994
- case 'browser': {
5995
- /* visible=false → ajan tarayıcıyı GİZLİ kullanıyor: UI yer açmaz */
5996
- const shown = !!ev.open && ev.visible !== false;
5997
- const wasShown = document.body.classList.contains('browser-open');
5998
- document.body.classList.toggle('browser-open', shown);
5999
- if (shown && ev.width) document.body.style.setProperty('--bw', ev.width + 'px');
6000
- document.body.classList.toggle('phone-mode', !!ev.phone);
6001
- if (els.bbPhone) els.bbPhone.classList.toggle('on', !!ev.phone);
6002
- els.browserBar.hidden = !shown;
6003
- els.bbResize.hidden = !shown;
6004
- /* terminal artık ALT dock — tarayıcıyla birlikte yaşar, kapatılmaz */
6005
- /* #19 tarayıcı açılınca paralel ajan konsolu (sağ panel) yerini bırakır;
6006
- kapanınca önceki durumuna döner — istenirse railBtn ile elle açılır.
6007
- GİZLİ ajan gezinmeleri (shown=false, wasShown=false) rail'e DOKUNMAZ —
6008
- aksi halde paralel ajan konsolu kendi kendine kapanırdı */
6009
- if (shown) {
6010
- railPrefBeforeBrowser = !document.body.classList.contains('rail-hidden');
6011
- toggleRail(true);
6012
- } else if (wasShown) {
6013
- toggleRail(!railPrefBeforeBrowser);
6014
- }
6015
- /* IDE modunda tarayıcı açılır/kapanır/genişlik değişirse row yeniden bölünür —
6016
- editör + Beast Code ORTAK kırpılıp ORTAK açılır (kullanıcı payı korunur) */
6017
- if (ideModeOn()) ideSplitApplyFrac();
6018
- if (sbModeOn()) sbSplitApplyFrac();
6019
- if (shown) {
6020
- els.browserBtn.classList.add('on');
6021
- if (ev.url && document.activeElement !== els.bbUrl) {
6022
- els.bbUrl.value = ev.url.startsWith('https://duckduckgo.com/?q=') ? decodeURIComponent(ev.url.split('q=')[1] || '') : ev.url;
6023
- }
6024
- } else {
6025
- els.browserBtn.classList.remove('on');
6026
- }
6031
+ case 'browser':
6032
+ applyBrowserState(ev);
6027
6033
  break;
6028
- }
6029
6034
  case 'status':
6030
6035
  /* kuyruktan tetiklenen yeni iş: kilitle kendiliğinden açılmışsa geri kapat */
6031
6036
  if (ev.status !== 'idle' && !busy) setBusy(true);
@@ -7046,6 +7051,14 @@ async function init() {
7046
7051
  beast.onEvent(onEvent);
7047
7052
  toggleRail(true); /* Paralel Ajanlar paneli varsayılan KAPALI — railBtn ile açılır */
7048
7053
 
7054
+ /* AÇILIŞ SENKRONU: tarayıcı renderer hazır olmadan açılmışsa (oturum kurtarma/
7055
+ arka plan işi) 'browser' olayı kaybolurdu — durum PULL edilir ki dock alanı
7056
+ (--bw) ayrılsın ve native view chat'in üzerine binmesin */
7057
+ try {
7058
+ const bst = await beast.browserStateGet();
7059
+ if (bst) applyBrowserState(bst);
7060
+ } catch {}
7061
+
7049
7062
  state = await beast.getState();
7050
7063
  try {
7051
7064
  const s = await beast.getSettings();