beast-agent 0.29.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/package.json +6 -3
  2. package/src/agent/engine.js +554 -33
  3. package/src/agent/llm.js +52 -3
  4. package/src/agent/obscura.js +26 -10
  5. package/src/agent/skills.js +87 -29
  6. package/src/agent/tools.js +519 -7
  7. package/src/main.js +48 -7
  8. package/src/preload.js +2 -0
  9. package/src/renderer/i18n.js +11 -7
  10. package/src/renderer/index.html +5 -2
  11. package/src/renderer/renderer.js +246 -8
  12. package/src/renderer/style.css +60 -4
  13. package/.env.example +0 -8
  14. package/config.example.yaml +0 -39
  15. package/eng.traineddata +0 -0
  16. package/scripts/fix-electron.js +0 -126
  17. package/scripts/release.js +0 -121
  18. package/scripts/swap-electron.js +0 -40
  19. package/store/skills.json +0 -5
  20. package/tests/approval.test.js +0 -56
  21. package/tests/bg-jobs.test.js +0 -379
  22. package/tests/bots-name.test.js +0 -42
  23. package/tests/bus.test.js +0 -46
  24. package/tests/computeruse-context.test.js +0 -69
  25. package/tests/cron.test.js +0 -95
  26. package/tests/engine.test.js +0 -203
  27. package/tests/eval.test.js +0 -91
  28. package/tests/fallout.test.js +0 -188
  29. package/tests/llm.test.js +0 -205
  30. package/tests/memory.test.js +0 -33
  31. package/tests/memoryloop.test.js +0 -26
  32. package/tests/notegen.test.js +0 -63
  33. package/tests/obscura.test.js +0 -124
  34. package/tests/owner.test.js +0 -32
  35. package/tests/python.test.js +0 -76
  36. package/tests/research.test.js +0 -116
  37. package/tests/scenarios.json +0 -81
  38. package/tests/sessioncode.test.js +0 -50
  39. package/tests/setup.js +0 -9
  40. package/tests/tokens.test.js +0 -42
  41. package/tests/tools.test.js +0 -84
  42. package/tests/usage.test.js +0 -44
  43. package/tests/v11.test.js +0 -76
  44. package/tests/watchers.test.js +0 -206
  45. package/tests/watext.test.js +0 -53
  46. package/tests/whatsapp.test.js +0 -103
  47. package/tests/wherewasi.test.js +0 -40
package/src/agent/llm.js CHANGED
@@ -70,6 +70,38 @@ function friendlyError(status, statusText, detail) {
70
70
  return msg;
71
71
  }
72
72
 
73
+ /* opencode cache disiplini (provider/transform.ts:1262-1276 port): destekleyen
74
+ sağlayıcılara oturum-sabit önbellek anahtarı gönderilir — aynı önek tekrar
75
+ kullanıldığında girdi tokenleri cache'ten okunur (~%90 ucuz + hızlı TTFT) */
76
+ const CACHE_KEY_PROVIDER_RE = /openai|azure|xai|deepseek|cerebras|deepinfra|mistral|venice/i;
77
+ const CACHE_KEY_MODEL_RE = /openai|gpt-|^o[134]|xai|grok|deepseek|cerebras|deepinfra|mistral|venice/i;
78
+ function wantsCacheKey(sel) {
79
+ if (!sel) return false;
80
+ return (
81
+ CACHE_KEY_PROVIDER_RE.test(String(sel.providerId || '')) ||
82
+ CACHE_KEY_MODEL_RE.test(String(sel.model || ''))
83
+ );
84
+ }
85
+
86
+ /* Retry-After başlığı: saniye ("2"), milisaniye ("120ms" / retry-after-ms)
87
+ ya da HTTP-tarih olabilir (opencode session/retry.ts port) */
88
+ function parseRetryAfter(v) {
89
+ if (v == null) return null;
90
+ const s = String(v).trim();
91
+ if (!s) return null;
92
+ const ms = /^(\d+)\s*ms$/i.exec(s);
93
+ if (ms) return Number(ms[1]);
94
+ if (/^\d+(\.\d+)?$/.test(s)) return Number(s) * 1000;
95
+ const d = Date.parse(s);
96
+ if (!Number.isNaN(d)) return Math.max(0, d - Date.now());
97
+ return null;
98
+ }
99
+
100
+ const RETRY_AFTER_CAP_MS = 30000; /* opencode retry.ts:39 — headersız bekleme tavanı */
101
+ function clampMs(v) {
102
+ return Math.min(RETRY_AFTER_CAP_MS, Math.max(0, Number(v) || 0));
103
+ }
104
+
73
105
  function sleep(ms, signal) {
74
106
  return new Promise((resolve, reject) => {
75
107
  const t = setTimeout(resolve, ms);
@@ -112,9 +144,14 @@ async function withRetries(fn, { signal, onRetry } = {}) {
112
144
  try {
113
145
  onRetry && onRetry(attempt, status);
114
146
  } catch {}
115
- const wait = netErr
116
- ? NET_BACKOFF[Math.min(attempt - 1, NET_BACKOFF.length - 1)]
117
- : 800 * Math.pow(2, attempt - 1);
147
+ /* sağlayıcı retry-after dediye: backoff yerine ona uy (30 sn tavan);
148
+ opencode session/retry.ts:26-31 ile aynı politika */
149
+ let wait;
150
+ if (e.retryAfterMs) wait = clampMs(e.retryAfterMs);
151
+ else
152
+ wait = netErr
153
+ ? NET_BACKOFF[Math.min(attempt - 1, NET_BACKOFF.length - 1)]
154
+ : 800 * Math.pow(2, attempt - 1);
118
155
  await sleep(wait, signal);
119
156
  }
120
157
  }
@@ -133,6 +170,10 @@ async function openChat(sel, body, { stream, signal, omitReasoning } = {}) {
133
170
  if (body.reasoningEffort && !omitReasoning) {
134
171
  payload.reasoning_effort = String(body.reasoningEffort);
135
172
  }
173
+ /* prompt cache anahtarı: oturum başına sabit → sağlayıcı önek önbelleği tutar */
174
+ if (body.cacheKey && wantsCacheKey(sel)) {
175
+ payload.prompt_cache_key = String(body.cacheKey);
176
+ }
136
177
  return fetch(sel.url, {
137
178
  method: 'POST',
138
179
  signal,
@@ -180,6 +221,9 @@ async function streamOnce(sel, body, { signal, onDelta, onRetry } = {}, omitReas
180
221
  } catch {}
181
222
  const err = new Error(friendlyError(r.status, r.statusText, detail));
182
223
  err.status = r.status;
224
+ err.retryAfterMs = parseRetryAfter(
225
+ r.headers && (r.headers.get('retry-after-ms') || r.headers.get('retry-after'))
226
+ );
183
227
  throw err;
184
228
  }
185
229
  return r;
@@ -317,6 +361,9 @@ async function chatOnce(sel, body, { signal, onRetry } = {}) {
317
361
  } catch {}
318
362
  const err = new Error(friendlyError(r.status, r.statusText, detail));
319
363
  err.status = r.status;
364
+ err.retryAfterMs = parseRetryAfter(
365
+ r.headers && (r.headers.get('retry-after-ms') || r.headers.get('retry-after'))
366
+ );
320
367
  throw err;
321
368
  }
322
369
  return r;
@@ -343,4 +390,6 @@ module.exports = {
343
390
  sumUsage,
344
391
  setNetProbe,
345
392
  isNetworkError,
393
+ wantsCacheKey,
394
+ parseRetryAfter,
346
395
  };
@@ -23,6 +23,12 @@ const FETCH_TIMEOUT_MS = 25000;
23
23
  /* content-length gelmezse yüzde tahmini için yaklaşık boyut (stealth zip ≈74 MB) */
24
24
  const EST_ZIP_BYTES = 74 * 1024 * 1024;
25
25
 
26
+ /* Beast Agent PAKETİNE gömülü zip (vendor/) — varsa HİÇ indirme yapılmaz */
27
+ function bundledZip() {
28
+ const p = path.join(__dirname, '..', '..', 'vendor', 'obscura.zip');
29
+ try { return fs.existsSync(p) ? p : null; } catch { return null; }
30
+ }
31
+
26
32
  function obscuraDir() {
27
33
  const base = process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming');
28
34
  return path.join(base, 'beast', 'obscura');
@@ -130,8 +136,8 @@ function psExpand(zipPath, destDir) {
130
136
  });
131
137
  }
132
138
 
133
- /* Obscura'yı kur / güncelle (yeniden indirip üzerine yazar).
134
- onProgress({pct, phase}) — 1-88 indirme, 89-96 açma, 97-99 doğrulama. */
139
+ /* Obscura'yı kur / güncelle. SIRA: pakete gömülü vendor zip'i (network YOK,
140
+ anında) → yoksa GitHub'dan indir. onProgress({pct, phase}). */
135
141
  async function installObscura(signal, onProgress) {
136
142
  const tick = (pct, phase) => {
137
143
  if (typeof onProgress === 'function') {
@@ -142,14 +148,23 @@ async function installObscura(signal, onProgress) {
142
148
  tick(0, 'hazırlanıyor');
143
149
  const dest = obscuraDir();
144
150
  fs.mkdirSync(dest, { recursive: true });
145
- const zipPath = path.join(os.tmpdir(), 'beast-obscura.zip');
146
- const buf = await httpsDownload(RELEASE_BASE + WINDOWS_ZIP, 5, signal, onProgress);
147
- tick(89, 'kuruluyor');
148
- fs.writeFileSync(zipPath, buf);
149
- tick(90, 'kuruluyor');
150
- const ok = await psExpand(zipPath, dest);
151
- try { fs.unlinkSync(zipPath); } catch {}
152
- tick(97, 'doğrulanıyor');
151
+ const bundled = bundledZip();
152
+ let ok = false;
153
+ if (bundled) {
154
+ /* PAKET İÇİ kurulum — indirme yok, saniyeler sürer */
155
+ tick(30, 'kuruluyor');
156
+ ok = await psExpand(bundled, dest);
157
+ tick(97, 'doğrulanıyor');
158
+ } else {
159
+ const zipPath = path.join(os.tmpdir(), 'beast-obscura.zip');
160
+ const buf = await httpsDownload(RELEASE_BASE + WINDOWS_ZIP, 5, signal, onProgress);
161
+ tick(89, 'kuruluyor');
162
+ fs.writeFileSync(zipPath, buf);
163
+ tick(90, 'kuruluyor');
164
+ ok = await psExpand(zipPath, dest);
165
+ try { fs.unlinkSync(zipPath); } catch {}
166
+ tick(97, 'doğrulanıyor');
167
+ }
153
168
  if (!ok || !obscuraInstalled()) {
154
169
  return { ok: false, error: 'obscura kurulumu başarısız (zip açılamadı)' };
155
170
  }
@@ -265,6 +280,7 @@ module.exports = {
265
280
  ENGINE: 'obscura',
266
281
  RELEASE_BASE,
267
282
  WINDOWS_ZIP,
283
+ bundledZip,
268
284
  obscuraDir,
269
285
  obscuraExe,
270
286
  obscuraInstalled,
@@ -1,4 +1,4 @@
1
- 'use strict';
1
+ 'use strict';
2
2
 
3
3
  /* Beast skills: %APPDATA%\beast\skills\**\SKILL.md
4
4
  Only name+description go into the system prompt (few tokens).
@@ -61,43 +61,101 @@ function scan() {
61
61
  const SEEDS = [
62
62
  {
63
63
  folder: 'help',
64
+ force: true,
64
65
  body: `---
65
66
  name: help
66
- description: Beast Agent genel yardım — tüm veri yolları (%APPDATA%\\beast), ayar/config dosyaları, memory, cron, watcher, WhatsApp, TTS, araç özeti.
67
- version: 1.0.0
67
+ description: Beast Agent'ın İÇ HARİTASI"kaç bot var", "oturumlar nerede", "x nasıl çalışır" gibi SİSTEM sorularını saniyeler içinde çözer: tüm veri yolları, hazır PowerShell/json one-liner'lar, kod haritası, slash komutları, ayar sekmeleri. Kod tabanını saatlerce taramadan bu haritadan oku.
68
+ version: 2.0.0
68
69
  ---
69
70
 
70
- # Beast Agent Yardım
71
+ # Beast Agent İç Haritası (self-help)
72
+
73
+ ## ALTIN KURAL
74
+ Sistem sorusu geldiğinde KOD TABANINI TARAMA. Aşağıdaki hazır yolu/one-liner'ı kullan — cevap 1-2 saniyede çıkar.
75
+
76
+ ## HIZLI CEVAPLAR (hazır komutlar)
77
+
78
+ **"Kaç bot var / botları listele"**
79
+ \`\`\`powershell
80
+ $b = Get-Content "$env:APPDATA\\beast\\bots.json" | ConvertFrom-Json; $b.bots | Select-Object id,name,admin,code
81
+ "Toplam bot: " + $b.bots.Count + " (admin: Beast)"
82
+ \`\`\`
83
+ (python_run ile: \`import json;d=json.load(open(r'%APPDATA%\\beast\\bots.json',encoding='utf-8'));print(len(d['bots']),[b['name'] for b in d['bots']])\`)
84
+
85
+ **"Kaç oturum var / sohbet geçmişi"**
86
+ \`\`\`powershell
87
+ (Get-ChildItem "$env:APPDATA\\beast\\sessions\\*.jsonl").Count
88
+ \`\`\`
89
+ Kod ↔ dosya eşleşmesi: jsonl'nin ilk satırı \`{"t":"meta","code":"ABC12"}\` taşır.
90
+
91
+ **"Paralel ajanlar ne durumda"** → \`tasks_list\` aracını ÇAĞIR (kod okumaya gerek yok) ya da:
92
+ \`\`\`powershell
93
+ Get-Content "$env:APPDATA\\beast\\sessions\\bg-jobs.json" | ConvertFrom-Json | % jobs | Select title,status,startedAt,error
94
+ \`\`\`
95
+
96
+ **"Maliyet/usage"** → \`/usage\` komutu ya da Ayarlar → Maliyet; kayıt dosyası \`usage.json\`.
71
97
 
72
- Tüm veri tek kökte: \`%APPDATA%\\beast\\\` (test/taşınabilir için \`BEAST_DATA\` env override).
98
+ **"Cron/izleyici var mı"** \`cron.json\`, \`watchers.json\`.
73
99
 
74
- ## Dosya Haritası
100
+ ## DOSYA HARİTASI (%APPDATA%\\beast\\)
75
101
 
76
102
  | Yol | Ne İşe Yarar |
77
103
  |---|---|
78
- | \`config.yaml\` + \`.env\` | Model sağlayıcıları + API anahtarları. Provider tanımı: \`providers.<id>.base_url/key_env/models\`; aktif seçim: \`model.provider/default\`. \`.env\`'de \`<PROVIDER>_API_KEY\` veya \`key_env\` ile eşleşen anahtar |
79
- | \`settings.json\` | App ayarları: theme, workspace, modelOverride, customProviders, roleModels, deletedModels, fallout, waTts (TTS), email (mail credential), waAllow, waLockdown |
80
- | \`sessions\\\` | Sohbet oturumları (mesaj JSON'ları) |
81
- | \`memories\\\` | SOUL.md (kişilik), MEMORY.md (uzun hafıza kayıtları), USER.md (kullanıcı bilgisi) |
82
- | \`skills\\\` | \`**\\\\SKILL.md\` isim+açıklama system prompt'a gider, gövde okunur |
83
- | \`cron.json\` | Zamanlanmış görevler (5 alanlı cron) |
84
- | \`watchers.json\` | Web/batarya izleyicileri |
85
- | \`wa-auth\\\` | WhatsApp Baileys eşleme auth'u SİLME |
86
- | \`wa-chats.json\`, \`wa.log\` | WA sohbet eşlemesi ve log |
87
- | \`bots.json\`, \`bots/<id>/\`, \`whitelist.json\` | Bot sistemi: bot kaydı (max 5, \`beast\` admin silinemez), her botun izole klasörü (config.json, memory.md, yetkiler.json, logs/), numara→bot eşlemesi. Bağlı olmayan numara beast'e düşer |
88
- | \`logs\\\`, \`scripts\\\` | Çalışma logları / kullanıcı scriptleri |
89
-
90
- ## Sağlık Kontrolleri
91
-
92
- - "Model yapılandırılmadı" hatası → \`config.yaml\`/\`.env\` dolu mu bak; yoksa kullanıcıdan Ayarlar → Provider'dan model seçmesini ya da dosyaları doldurmasını iste (\`config.example.yaml\` repo kökünde örnek var).
93
- - Mail sorunları → \`email\` skill'ini oku.
94
- - fallout zinciri → Ayarlar → Fallout; 401'de sıradaki slota otomatik düşer.
95
-
96
- ## Davranış Kuralları
97
-
104
+ | \`config.yaml\` + \`.env\` | Model sağlayıcıları + API anahtarları (\`providers.<id>.base_url/key_env/models\`, aktif: \`model.provider/default\`) |
105
+ | \`settings.json\` | App ayarları: theme, workspace, modelOverride, customProviders, roleModels, deletedModels, fallout, waTts, email, waAllow, **searchChain (web arama sırası)**, **obscuraEnabled**, activeBotId |
106
+ | \`sessions\\*.jsonl\` | Sohbet oturumları (satır JSON: t:meta kod, t:meta2 paralel-ajan işareti, t:msg mesaj, t:todo, t:notes) |
107
+ | \`sessions\\bg-jobs.json\` | Paralel ajan iş kayıtları: id, title, status(queued/running/done/error/aborted), error=İPTAL SEBEBİ, groupId |
108
+ | \`memories\\\` | SOUL.md (kişilik), MEMORY.md (uzun hafıza), USER.md (kullanıcı) |
109
+ | \`skills\\<ad>\\SKILL.md\` | Skill'ler (isim+açıklama prompt'a girer, gövde okunur) |
110
+ | \`bots.json\` | Bot kayıt defteri — max 5 bot, ilk kayıt admin 'Beast' (silinemez). Bot adı HARFLE başlamak ZORUNDA |
111
+ | \`bots/<id>/\` | Botun izole klasörü: config.json, memory.md, yetkiler.json, logs/ |
112
+ | \`whitelist.json\`, \`wa-auth\\\`, \`wa-chats.json\`, \`wa.log\` | WhatsApp izin listesi, Baileys auth (SİLME), sohbet eşlemesi, log |
113
+ | \`cron.json\`, \`watchers.json\`, \`bus.json\` | Zamanlanmış görevler, web/batarya izleyicileri, olay abonelikleri |
114
+ | \`scripts\\\` | Python scriptleri (websearch.py, news.py) |
115
+ | \`obscura\\obscura.exe\` | Obscura stealth tarayıcı (web arama zincirinin 2. motoru; açılışta otomatik kurulur) |
116
+ | \`py\\python.exe\` | Gömülü Python runtime (makinede Python olmasa bile python_run çalışır) |
117
+ | \`usage.json\`, \`logs\\\` | Kullanım sayaçları, çalışma logları |
118
+ | Masaüstü\\Beast-Backups | Şifreli yedekler (.beastbak) /backup ile alınır |
119
+
120
+ ## KOD HARİTASI (src/)
121
+
122
+ | Dosya | Sorumluluk |
123
+ |---|---|
124
+ | \`main.js\` | Electron ana süreç: tüm IPC, WhatsApp/Telegram/Discord entegrasyonları, onay kapısı (/approve), /stop /restart, splash, gizli araştırma tarayıcısı, obscura kurulumu |
125
+ | \`agent/engine.js\` | OTURUM MOTORU: send/_run tur döngüsü, paralel ajanlar (run_background, run_background_many, tasks_list, task_status, task_cancel — task_cancel reason ZORUNLU), superyorizon (takılan işi zorla kapatır), iptal sebep disiplini, flushPendingReports |
126
+ | \`agent/tools.js\` | Araçlar + web_search SIRALI ZİNCİRİ (searchChain: 1 dahili tarayıcı(Google) → 2 Obscura(stealth→DuckDuckGo) → 3 TinyFish(anahtarsa) → 4 python çoklu-motor; sıra Ayarlar→Web Arama'dan değişir), run_command, read/write_file, python_run, http_fetch, deep_search |
127
+ | \`agent/llm.js\` | Sağlayıcı çağrısı + retry: ağ kopmasında 6 deneme + internet dönene kadar bekler; akış ortası kopmada kaldığı yerden devam |
128
+ | \`agent/obscura.js\` | Obscura: otomatik kurulum (GitHub releases, stealth zip) + DuckDuckGo html/lite arama ayrıştırıcı |
129
+ | \`agent/bots.js\` | Bot CRUD, 5 haneli bot kodu, izolasyon; ad-ilk-harf doğrulaması |
130
+ | \`agent/skills.js\` | Builtin tohumlar (help, email, python-web-search, pdf, gold-trading) + SKILL.md taraması + taslaklar |
131
+ | \`agent/memory.js\`, \`agent/kb.js\` | Kalıcı hafıza + bilgi bankası |
132
+ | \`cron.js\` (src kökü), \`agent/watchers.js\`, \`agent/bus.js\` | Cron, izleyici, olay merkezi — /stop bunlara DOKUNMAZ |
133
+ | \`agent/usage.js\` | Token/maliyet sayaçları |
134
+ | \`renderer/\` | Arayüz: renderer.js (tüm paneller), i18n.js (TR/EN), index.html, style.css |
135
+ | \`bin/beast-agent.js\` | CLI: \`beast\` (başlat), \`beast update\`, \`beast uninstall\` |
136
+
137
+ ## SLASH KOMUTLARI
138
+ /help · /version · /new · /open <kod> · /sessions · /stop · /start · /restart · /change [n] · /model <isim> · /think 0-5 · /clear · /notes · /rule <metin> · /rules · /notify on|off · /screenshot · /approve [always] · /deny · /update [now] · /usage · /backup · /status · /skills
139
+
140
+ ## AYAR SEKMELERİ
141
+ Provider · Fallout · Skills · Paralel Ajanlar · TTS · E-posta · Entegrasyonlar · Web Arama (Obscura kurulum + arama sırası) · Olaylar · Cron · Maliyet · Loglar · Panel · Limitler · Güvenlik · Güncelleme
142
+
143
+ ## PARALEL AJAN HIZLI BİLGİ
144
+ - CEO modu: konuşan ajan iş YAPMAZ, run_background/run_background_many ile devreder; görev tanımı kendine yeterli olmalı (ajan CEO bağlamını GÖREMEZ).
145
+ - İş bitince birleşik/bireysel rapor OTOMATİK üst sohbete düşer — takılı iş superyorizon tarafından SEBEPİYLE zorla kapatılır.
146
+ - Canlı izleme: tasks_list/task_status; iptal: task_cancel (reason zorunlu, kullanıcıya sebep yazılır).
147
+
148
+ ## SAĞLIK KONTROLLERİ
149
+ - "Model yapılandırılmadı" → config.yaml/.env dolu mu; Ayarlar → Provider'dan seçim.
150
+ - Mail hatası → \`email\` skill'ini oku.
151
+ - 401 → Fallout zinciri sıradaki slota otomatik düşer.
152
+ - DDG boş/engelli → normaldir; zincir Obscura/Bing/Mojeek'e otomatik geçer.
153
+
154
+ ## DAVRANIŞ KURALLARI
98
155
  - Şifre/API anahtarlarını asla düz metin loglama/tekrarlama.
99
- - settings.json'a el ile yazarken app kapalı olsun (kapanışta ezme riski).
100
- - Yeni yetenek gerekiyorsa \`%APPDATA%\\beast\\skills\\<ad>\\\\SKILL.md\` oluşturmayı önerebilirsin.`,
156
+ - settings.json'a el ile yazarken app kapalı olsun.
157
+ - Yeni yetenek gerekiyorsa \`%APPDATA%\\beast\\skills\\<ad>\\SKILL.md\` oluşturmayı öner.
158
+ - Bu haritadaki yolları ÖNCE dene; kod taraması yalnız haritada olmayan derin sorularda.`,
101
159
  },
102
160
  {
103
161
  folder: 'email',
@@ -178,7 +236,7 @@ Gerçek Chromium olduğu için Google'a bot koruması uygulamaz. Arama aep=1 ile
178
236
 
179
237
  ## 2. Obscura (stealth headless — DuckDuckGo)
180
238
 
181
- Rust tabanlı gizli tarayıcı: anti-detect parmak izi + V8 JS. Kurulu değilse uygulama açılışında OTOMATİK indirilir (%APPDATA%\\beast\\obscura). Varsayılan AKTİF — tarayıcı engellenirse bot korumasını aşarak DuckDuckGo'dan sonuç getirir.
239
+ Rust tabanlı gizli tarayıcı: anti-detect parmak izi + V8 JS. Beast Agent PAKETİNDE hazır gelir ilk açılışta %APPDATA%\\beast\\obscura'ya açılır (indirme yok). Varsayılan AKTİF — tarayıcı engellenirse bot korumasını aşarak DuckDuckGo'dan sonuç getirir.
182
240
 
183
241
  ## 3. TinyFish API (anahtar varsa)
184
242