beast-agent 0.30.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 (46) hide show
  1. package/package.json +6 -3
  2. package/src/agent/engine.js +463 -21
  3. package/src/agent/llm.js +52 -3
  4. package/src/agent/obscura.js +26 -10
  5. package/src/agent/skills.js +2 -2
  6. package/src/agent/tools.js +519 -7
  7. package/src/main.js +28 -13
  8. package/src/renderer/i18n.js +7 -7
  9. package/src/renderer/index.html +5 -2
  10. package/src/renderer/renderer.js +154 -5
  11. package/src/renderer/style.css +45 -4
  12. package/.env.example +0 -8
  13. package/config.example.yaml +0 -39
  14. package/eng.traineddata +0 -0
  15. package/scripts/fix-electron.js +0 -126
  16. package/scripts/release.js +0 -121
  17. package/scripts/swap-electron.js +0 -40
  18. package/store/skills.json +0 -5
  19. package/tests/approval.test.js +0 -56
  20. package/tests/bg-jobs.test.js +0 -424
  21. package/tests/bots-name.test.js +0 -42
  22. package/tests/bus.test.js +0 -46
  23. package/tests/computeruse-context.test.js +0 -69
  24. package/tests/cron.test.js +0 -95
  25. package/tests/engine.test.js +0 -203
  26. package/tests/eval.test.js +0 -91
  27. package/tests/fallout.test.js +0 -188
  28. package/tests/llm.test.js +0 -205
  29. package/tests/memory.test.js +0 -33
  30. package/tests/memoryloop.test.js +0 -26
  31. package/tests/notegen.test.js +0 -63
  32. package/tests/obscura.test.js +0 -124
  33. package/tests/owner.test.js +0 -32
  34. package/tests/python.test.js +0 -76
  35. package/tests/research.test.js +0 -116
  36. package/tests/scenarios.json +0 -81
  37. package/tests/sessioncode.test.js +0 -50
  38. package/tests/setup.js +0 -9
  39. package/tests/tokens.test.js +0 -42
  40. package/tests/tools.test.js +0 -84
  41. package/tests/usage.test.js +0 -44
  42. package/tests/v11.test.js +0 -76
  43. package/tests/watchers.test.js +0 -206
  44. package/tests/watext.test.js +0 -53
  45. package/tests/whatsapp.test.js +0 -103
  46. package/tests/wherewasi.test.js +0 -40
@@ -1,4 +1,4 @@
1
- 'use strict';
1
+ 'use strict';
2
2
 
3
3
  /* Hafif i18n (TR/EN):
4
4
  - data-i18n → textContent
@@ -267,9 +267,9 @@
267
267
  ws_h2: 'Web Arama',
268
268
  ws_sub: 'Arama zinciri: 1) dahili tarayıcı (direk Google) 2) Obscura (stealth headless → DuckDuckGo) 3) TinyFish (anahtar varsa) 4) python çoklu-motor (ddgs / DDG+Bing+Mojeek) — otomatik. Sıra ve aç/kapa aşağıdan değiştirilir.',
269
269
  oc_h2: 'Obscura (Stealth Tarayıcı)',
270
- oc_sub: 'Rust tabanlı gizli headless tarayıcı (anti-detect + V8, Chromium\u2019suz). Kurulu değilse ilk açılışta otomatik indirilir (%APPDATA%\\beast\\obscura); DuckDuckGo aramasını bot korumasını aşarak yapar.',
270
+ oc_sub: 'Rust tabanlı gizli headless tarayıcı (anti-detect + V8, Chromium\u2019suz). Paket içinde hazır gelir; ilk açılışta %APPDATA%\\beast\\obscura\'ya açılır; DuckDuckGo aramasını bot korumasını aşarak yapar.',
271
271
  oc_status_ok: 'Obscura kurulu ve hazır.',
272
- oc_status_missing: 'Obscura kurulu değil — ilk açılışta otomatik indirilir (≈74 MB).',
272
+ oc_status_missing: 'Obscura paket içinde hazır — ilk açılışta otomatik kurulur.',
273
273
  oc_install: 'Kur / Güncelle',
274
274
  oc_install_running: 'Kuruluyor…',
275
275
  oc_installing: 'İndiriliyor… (≈74 MB, bağlantıya göre birkaç dakika)',
@@ -325,7 +325,7 @@
325
325
  us_where_off_toast: 'Açılış özeti kapandı',
326
326
  ws_h2: 'Web Arama',
327
327
  oc_status_ok: 'Obscura kurulu ve hazır.',
328
- oc_status_missing: 'Obscura kurulu değil — ilk açılışta otomatik indirilir.',
328
+ oc_status_missing: 'Obscura paket içinde hazır — ilk açılışta otomatik kurulur.',
329
329
  ws_save: 'Kaydet',
330
330
  ws_clear: 'Anahtarı Sil',
331
331
  ws_key_note: 'Anahtar maskeli tutulur; yenisini yazıp kaydettiğinde eskisinin yerine geçer. Boş kaydet: mevcut anahtar korunur.',
@@ -822,9 +822,9 @@
822
822
  ws_h2: 'Web Search',
823
823
  ws_sub: 'Search chain: 1) built-in browser (direct Google) 2) Obscura (stealth headless → DuckDuckGo) 3) TinyFish (if a key is set) 4) python multi-engine (ddgs / DDG+Bing+Mojeek) — automatic. Order and on/off are editable below.',
824
824
  oc_h2: 'Obscura (Stealth Browser)',
825
- oc_sub: 'Rust-based stealth headless browser (anti-detect + V8, no Chromium). If not installed it is auto-downloaded at first launch (%APPDATA%\\beast\\obscura); it searches DuckDuckGo past bot protection.',
825
+ oc_sub: 'Rust-based stealth headless browser (anti-detect + V8, no Chromium). It ships inside the package and is extracted to %APPDATA%\\beast\\obscura at first launch; it searches DuckDuckGo past bot protection.',
826
826
  oc_status_ok: 'Obscura is installed and ready.',
827
- oc_status_missing: 'Obscura is not installed — it is auto-downloaded at first launch (≈74 MB).',
827
+ oc_status_missing: 'Obscura ships inside the package — it is extracted automatically at first launch.',
828
828
  oc_install: 'Install / Update',
829
829
  oc_install_running: 'Installing…',
830
830
  oc_installing: 'Downloading… (≈74 MB, may take a few minutes)',
@@ -942,7 +942,7 @@
942
942
  us_where_off_toast: 'Startup summary off',
943
943
  ws_h2: 'Web Search',
944
944
  oc_status_ok: 'Obscura is installed and ready.',
945
- oc_status_missing: 'Obscura is not installed — it is auto-downloaded at first launch.',
945
+ oc_status_missing: 'Obscura ships inside the package — it is extracted automatically at first launch.',
946
946
  ws_save: 'Save',
947
947
  ws_clear: 'Delete Key',
948
948
  ws_key_note: 'Key is kept masked; saving a new one replaces the old. Save empty: existing key kept.',
@@ -41,6 +41,7 @@
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
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>
43
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>
44
+ <span id="netDot" class="net-on" title="İnternet: bağlı" data-i18n-title="tipNet"><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 8.82a15 15 0 0 1 20 0"/><path d="M5 12.85a10 10 0 0 1 14 0"/><path d="M8.53 16.11a6 6 0 0 1 6.95 0"/><line x1="12" y1="20" x2="12.01" y2="20"/><line class="net-slash" x1="4" y1="4" x2="20" y2="20"/></svg></span>
44
45
  </div>
45
46
  </aside>
46
47
 
@@ -77,7 +78,6 @@
77
78
  <button id="termCBtn" class="dd-btn dd-icon-btn" title="CMD terminali" data-i18n-title="tipTermC">&#x276F;&#xFE0E;</button>
78
79
  <button id="browserBtn" class="dd-btn dd-icon-btn" title="Dahili tarayıcı" data-i18n-title="tipBrowser">&#x29C9;</button>
79
80
  <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>
80
- <span id="netDot" class="dd-btn dd-icon-btn net-on" title="İnternet: bağlı" data-i18n-title="tipNet"><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="M5 12.55a11 11 0 0 1 14.08 0"/><path d="M8.53 16.11a6 6 0 0 1 6.95 0"/><line x1="12" y1="20" x2="12.01" y2="20"/><line class="net-slash" x1="4" y1="4" x2="20" y2="20"/></svg></span>
81
81
  <div class="drag-spacer"></div>
82
82
  </header>
83
83
 
@@ -112,7 +112,10 @@
112
112
  <code id="codePath" title="">—</code>
113
113
  <button id="codeSave" title="Kaydet (Ctrl+S)">Kaydet</button>
114
114
  </div>
115
- <textarea id="codeTa" spellcheck="false"></textarea>
115
+ <div id="codeBody">
116
+ <div id="codeGutter" aria-hidden="true"></div>
117
+ <textarea id="codeTa" spellcheck="false" wrap="off"></textarea>
118
+ </div>
116
119
  </section>
117
120
 
118
121
  <div id="ideSplit" title="Sürükleyerek boyutlandır"></div>
@@ -78,6 +78,7 @@ const els = {
78
78
  bcTodoWrap: $('#bcTodoWrap'),
79
79
  codeTabs: $('#codeTabs'),
80
80
  codeTa: $('#codeTa'),
81
+ codeGutter: $('#codeGutter'),
81
82
  codePath: $('#codePath'),
82
83
  codeSave: $('#codeSave'),
83
84
  ideRow: $('#ideRow'),
@@ -890,7 +891,7 @@ async function renderWebSearchPane() {
890
891
  '<h2>' + _t('oc_h2') + '</h2>' +
891
892
  '<div class="sub">' + _t('oc_sub') + '</div>' +
892
893
  '<div id="ocStatus" class="sub" style="text-align:left;margin-top:8px"></div>' +
893
- '<label class="mem-label" style="display:flex;align-items:center;gap:8px;cursor:pointer">' +
894
+ '<label class="mem-label" style="display:flex;align-items:center;justify-content:center;gap:8px;cursor:pointer">' +
894
895
  '<input id="ocEnabled" type="checkbox" style="width:auto" /> <span>' + _t('oc_enabled') + '</span></label>' +
895
896
  '<div id="ocProg" class="oc-prog" hidden>' +
896
897
  '<div class="oc-prog-bar"><div class="oc-prog-fill" style="width:0%"></div></div>' +
@@ -3905,11 +3906,18 @@ function onEvent(ev) {
3905
3906
  addToolCard(ev.callId, ev.name, ev.args);
3906
3907
  setStatus(ev.name + '…');
3907
3908
  termAgentEvent(ev);
3909
+ /* ajan dosya yazarsa açık IDE sekmesini izlemeye al */
3910
+ if (ev.name === 'write_file' && ev.args && ev.args.path) codeWriteWatch.set(ev.callId, ev.args.path);
3908
3911
  break;
3909
3912
  case 'tool-end':
3910
3913
  finishToolCard(ev.callId, ev.ok, ev.result);
3911
3914
  setStatus('düşünüyor…');
3912
3915
  termAgentEvent(ev);
3916
+ if (codeWriteWatch.has(ev.callId)) {
3917
+ const wp = codeWriteWatch.get(ev.callId);
3918
+ codeWriteWatch.delete(ev.callId);
3919
+ codeReloadIfOpen(wp);
3920
+ }
3913
3921
  break;
3914
3922
  case 'todos':
3915
3923
  renderTodos(ev.todos);
@@ -5692,6 +5700,7 @@ async function setIdeMode(on) {
5692
5700
  ideSplitRestore();
5693
5701
  await loadIdeTree();
5694
5702
  bcBanner();
5703
+ codeGutterRender(); /* dosya açık olmasa bile rakamlar görünür */
5695
5704
  }
5696
5705
  }
5697
5706
 
@@ -5823,9 +5832,103 @@ async function renderFileTree() {
5823
5832
  Dosya tıklaması MODAL değil, codePane içinde SEKME açar.
5824
5833
  Yanında Beast Code chat'i, onun sağındaki preview tarayıcı durur. */
5825
5834
 
5826
- const codeTabs = []; /* { rel, content, dirty } */
5835
+ const codeTabs = []; /* { rel, content, dirty, base } — base: temiz (disk) içerik, diff bununla */
5827
5836
  let codeActive = -1;
5828
5837
 
5838
+ /* ---------- editör gutter: satır numaraları + değişiklik işaretleri ---------- */
5839
+ /* base ↔ mevcut içerik diff'i: eklenen/değişen satırlar YEŞİL, silinenler
5840
+ kısmen/kırmızı çizgiyle (VS Code gutter stili). LCS; satır adedi aşılırsa
5841
+ bölge-bütününü değişmiş sayar (büyük dosyalarda takılmaz). */
5842
+ function codeDiffLines(baseText, curText) {
5843
+ const added = new Set();
5844
+ const dels = new Map();
5845
+ if (typeof baseText !== 'string') return { added, dels };
5846
+ const a = baseText.split('\n');
5847
+ const b = String(curText || '').split('\n');
5848
+ let p = 0;
5849
+ while (p < a.length && p < b.length && a[p] === b[p]) p++;
5850
+ let ea = a.length - 1;
5851
+ let eb = b.length - 1;
5852
+ while (ea >= p && eb >= p && a[ea] === b[eb]) { ea--; eb--; }
5853
+ const midA = a.slice(p, ea + 1);
5854
+ const midB = b.slice(p, eb + 1);
5855
+ const n = midA.length;
5856
+ const m = midB.length;
5857
+ if (!n && !m) return { added, dels };
5858
+ const pushDel = (at, count) => {
5859
+ if (!count) return;
5860
+ const line = Math.min(Math.max(1, at), b.length || 1);
5861
+ dels.set(line, (dels.get(line) || 0) + count);
5862
+ };
5863
+ if (n * m > 400000 || n > 1500 || m > 1500) {
5864
+ for (let k = 0; k < m; k++) added.add(p + k + 1);
5865
+ pushDel(p + m + 1, n);
5866
+ return { added, dels };
5867
+ }
5868
+ const w = m + 1;
5869
+ const dp = new Int32Array((n + 1) * w);
5870
+ for (let i = n - 1; i >= 0; i--) {
5871
+ for (let j = m - 1; j >= 0; j--) {
5872
+ dp[i * w + j] =
5873
+ midA[i] === midB[j]
5874
+ ? dp[(i + 1) * w + j + 1] + 1
5875
+ : Math.max(dp[(i + 1) * w + j], dp[i * w + j + 1]);
5876
+ }
5877
+ }
5878
+ let i = 0;
5879
+ let j = 0;
5880
+ let pendingDel = 0;
5881
+ while (i < n && j < m) {
5882
+ if (midA[i] === midB[j]) {
5883
+ pushDel(p + j + 1, pendingDel);
5884
+ pendingDel = 0;
5885
+ i++; j++;
5886
+ } else if (dp[(i + 1) * w + j] >= dp[i * w + j + 1]) {
5887
+ pendingDel++; i++;
5888
+ } else {
5889
+ pushDel(p + j + 1, pendingDel);
5890
+ pendingDel = 0;
5891
+ added.add(p + j + 1);
5892
+ j++;
5893
+ }
5894
+ }
5895
+ while (i < n) { pendingDel++; i++; }
5896
+ while (j < m) {
5897
+ pushDel(p + j + 1, pendingDel);
5898
+ pendingDel = 0;
5899
+ added.add(p + j + 1);
5900
+ j++;
5901
+ }
5902
+ pushDel(p + m + 1, pendingDel);
5903
+ return { added, dels };
5904
+ }
5905
+
5906
+ function codeGutterRender() {
5907
+ const g = els.codeGutter;
5908
+ const ta = els.codeTa;
5909
+ if (!g || !ta) return;
5910
+ const hasFile = codeActive >= 0 && codeTabs[codeActive];
5911
+ const t = hasFile ? codeTabs[codeActive] : null;
5912
+ const diff = hasFile ? codeDiffLines(t.base, ta.value) : null;
5913
+ /* dosya açık olmasa bile rakamlar HEP görünür (boş editörde 50 satır iskeleti) */
5914
+ const count = hasFile
5915
+ ? ta.value.split('\n').length
5916
+ : 50;
5917
+ let html = '';
5918
+ for (let i = 1; i <= count; i++) {
5919
+ const isAdd = diff && diff.added.has(i);
5920
+ const delN = diff && diff.dels.get(i);
5921
+ html +=
5922
+ `<div class="cl${isAdd ? ' add' : ''}${delN ? ' del' : ''}${hasFile ? '' : ' idle'}"` +
5923
+ (delN ? ` title="${delN} satır silindi"` : '') +
5924
+ `>${i}</div>`;
5925
+ }
5926
+ g.innerHTML = html;
5927
+ g.scrollTop = ta.scrollTop;
5928
+ }
5929
+
5930
+ let codeGutterTimer = null;
5931
+
5829
5932
  function codeRenderTabs() {
5830
5933
  const bar = els.codeTabs;
5831
5934
  if (!bar) return;
@@ -5860,6 +5963,7 @@ function codeActivate(i) {
5860
5963
  els.codeTa.value = '';
5861
5964
  els.codePath.textContent = '\u2014';
5862
5965
  codeRenderTabs();
5966
+ codeGutterRender();
5863
5967
  return;
5864
5968
  }
5865
5969
  codeActive = i;
@@ -5868,6 +5972,7 @@ function codeActivate(i) {
5868
5972
  els.codePath.textContent = t.rel;
5869
5973
  els.codePath.title = (ideState.path || '') + '\\' + t.rel.replace(/\//g, '\\');
5870
5974
  codeRenderTabs();
5975
+ codeGutterRender();
5871
5976
  }
5872
5977
 
5873
5978
  async function codeOpen(rel) {
@@ -5881,7 +5986,7 @@ async function codeOpen(rel) {
5881
5986
  toast((r && r.error) || 'okunamad\u0131');
5882
5987
  return;
5883
5988
  }
5884
- codeTabs.push({ rel, content: r.content || '', dirty: false });
5989
+ codeTabs.push({ rel, content: r.content || '', dirty: false, base: r.content || '' });
5885
5990
  codeActivate(codeTabs.length - 1);
5886
5991
  els.codeTa.focus();
5887
5992
  }
@@ -5913,13 +6018,44 @@ async function codeSave() {
5913
6018
  const r = await beast.ideWrite(t.rel, t.content).catch(() => null);
5914
6019
  if (r && r.ok) {
5915
6020
  t.dirty = false;
6021
+ t.base = t.content; /* kaydedildi → diff sıfırlanır (VS Code davranışı) */
5916
6022
  codeRenderTabs();
6023
+ codeGutterRender();
5917
6024
  toast(_t('ide_saved'));
5918
6025
  } else {
5919
6026
  toast((r && r.error) || 'kaydedilemedi');
5920
6027
  }
5921
6028
  }
5922
6029
 
6030
+ /* ajan dosyayı YAZINCA açık sekmeyi tazele: eski içerik base olur →
6031
+ ajanın değiştirdiği satırlar gutter'da yeşil/kırmızı görünür */
6032
+ const codeWriteWatch = new Map(); /* callId → path */
6033
+ async function codeReloadIfOpen(p) {
6034
+ const abs = String(p || '').replace(/\//g, '\\');
6035
+ const root = String(ideState.path || '').replace(/\//g, '\\').replace(/\\+$/, '');
6036
+ let rel = null;
6037
+ if (root && abs.toLowerCase().startsWith(root.toLowerCase() + '\\')) {
6038
+ rel = abs.slice(root.length + 1).replace(/\\/g, '/');
6039
+ } else {
6040
+ const cand = abs.toLowerCase();
6041
+ const hit = codeTabs.find((t) => cand.endsWith('\\' + t.rel.replace(/\//g, '\\').toLowerCase()) || cand === t.rel.replace(/\//g, '\\').toLowerCase());
6042
+ if (!hit) return;
6043
+ rel = hit.rel;
6044
+ }
6045
+ const i = codeTabs.findIndex((t) => t.rel === rel);
6046
+ if (i < 0) return;
6047
+ const t = codeTabs[i];
6048
+ if (t.dirty) return; /* kullanıcının kaydedilmemiş düzenlemesini EZME */
6049
+ const r = await beast.ideRead(t.rel).catch(() => null);
6050
+ if (!r || !r.ok) return;
6051
+ t.base = t.content; /* eski disk içeriği = diff tabanı */
6052
+ t.content = r.content || ''; /* ajanın yazdığı yeni içerik */
6053
+ if (i === codeActive) {
6054
+ els.codeTa.value = t.content;
6055
+ }
6056
+ codeGutterRender();
6057
+ }
6058
+
5923
6059
  $('#ideBtn').addEventListener('click', () => setIdeMode(!ideModeOn()));
5924
6060
  $('#filePick').addEventListener('click', async () => {
5925
6061
  const r = await beast.ideSetRoot().catch(() => null);
@@ -5946,6 +6082,12 @@ if (els.codeTa) {
5946
6082
  codeTabs[codeActive].dirty = true;
5947
6083
  const el = els.codeTabs.children[codeActive];
5948
6084
  if (el) el.classList.add('dirty');
6085
+ /* gutter diff'i hafif gecikmeli — her tuşta LCS koşmasın */
6086
+ clearTimeout(codeGutterTimer);
6087
+ codeGutterTimer = setTimeout(codeGutterRender, 120);
6088
+ });
6089
+ els.codeTa.addEventListener('scroll', () => {
6090
+ if (els.codeGutter) els.codeGutter.scrollTop = els.codeTa.scrollTop;
5949
6091
  });
5950
6092
  els.codeTa.addEventListener('keydown', (e) => {
5951
6093
  if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 's') {
@@ -6304,9 +6446,16 @@ function bcIngest(ev) {
6304
6446
  break;
6305
6447
  case 'tool-start':
6306
6448
  bcToolBoxStart(ev.callId, ev.name, ev.args);
6449
+ /* ajan dosya yazarsa açık IDE sekmesini izlemeye al */
6450
+ if (ev.name === 'write_file' && ev.args && ev.args.path) codeWriteWatch.set(ev.callId, ev.args.path);
6307
6451
  break;
6308
6452
  case 'tool-end':
6309
6453
  bcToolBoxEnd(ev.callId, ev.ok, ev.result);
6454
+ if (codeWriteWatch.has(ev.callId)) {
6455
+ const wp = codeWriteWatch.get(ev.callId);
6456
+ codeWriteWatch.delete(ev.callId);
6457
+ codeReloadIfOpen(wp);
6458
+ }
6310
6459
  break;
6311
6460
  case 'bc-mode':
6312
6461
  /* OpenCode disiplini çalışma modu: başlıkta rozet + panelde bilgi satırı */
@@ -6334,13 +6483,13 @@ function bcIngest(ev) {
6334
6483
  break;
6335
6484
  case 'status':
6336
6485
  /* 'idle' = engine oturumu GERÇEKTEN bıraktı (finally bloğu, her yolda gelir) —
6337
- done kaçsa bile panel kilitli kalmaz, otomatik kalkar, ring durur */
6486
+ done kaçsa bile panel kilitli kalmaz, otomatik kalkar, ring durur */
6338
6487
  if (ev.status === 'idle') {
6339
6488
  bcCloseToolGroup();
6340
6489
  bcSetBusy(false);
6341
6490
  bcRefreshPreview();
6342
6491
  }
6343
- break;
6492
+ break;
6344
6493
  }
6345
6494
  }
6346
6495
 
@@ -291,11 +291,15 @@ body.browser-open #topbar { width: auto; }
291
291
  /* göz ikonu: gizli modda çapraz çizgi + soluk, görünür modda normal */
292
292
  #eyeBtn .eye-slash { display: none; }
293
293
  #eyeBtn:not(.on) .eye-slash { display: block; }
294
- #eyeBtn:not(.on) { opacity: 0.55; }
295
294
  #eyeBtn.on { background: var(--accent-dim); color: var(--accent); }
296
295
 
297
- /* internet göstergesi (topbar sağ ): bağlı = YEŞİL wifi, kopuk = KIRMIZI */
298
- #netDot { cursor: default; }
296
+ /* internet göstergesi (sol alt sideFoot satırında, ortalanmış): bağlı = YEŞİL wifi, kopuk = KIRMIZI */
297
+ #netDot {
298
+ display: inline-flex;
299
+ align-items: center;
300
+ padding: 3px 7px;
301
+ cursor: default;
302
+ }
299
303
  #netDot.net-on { color: #22c55e; }
300
304
  #netDot.net-off { color: #ef4444; }
301
305
  #netDot.net-off .net-slash { display: block; }
@@ -2439,6 +2443,41 @@ body.ide-mode #codePane { display: flex; }
2439
2443
  line-height: 1.4;
2440
2444
  }
2441
2445
  #codeSave:hover { color: var(--accent); border-color: var(--accent); background: var(--panel2); }
2446
+ #codeBody { flex: 1; display: flex; min-height: 0; }
2447
+ #codeGutter {
2448
+ flex: none;
2449
+ width: 56px;
2450
+ overflow: hidden;
2451
+ user-select: none;
2452
+ font-family: Consolas, "Cascadia Mono", monospace;
2453
+ font-size: 12.5px;
2454
+ line-height: 20px;
2455
+ padding: 12px 0;
2456
+ background: var(--panel);
2457
+ border-right: 1px solid var(--border);
2458
+ text-align: right;
2459
+ color: var(--muted);
2460
+ }
2461
+ #codeGutter .cl { height: 20px; padding-right: 8px; position: relative; }
2462
+ /* VS Code tarzı değişiklik işaretleri: değişen satır YEŞİL, silinen kırmızı çizgi */
2463
+ #codeGutter .cl.add {
2464
+ background: rgba(34, 197, 94, 0.16);
2465
+ box-shadow: inset 2px 0 0 #22c55e;
2466
+ color: #16a34a;
2467
+ font-weight: 700;
2468
+ }
2469
+ #codeGutter .cl.del { box-shadow: inset 2px 0 0 #ef4444; }
2470
+ #codeGutter .cl.del::after {
2471
+ content: '';
2472
+ position: absolute;
2473
+ left: 0;
2474
+ right: 0;
2475
+ bottom: 0;
2476
+ height: 2px;
2477
+ background: #ef4444;
2478
+ }
2479
+ /* dosya açık değilken boş editör iskelet rakamları daha sönük */
2480
+ #codeGutter .cl.idle { opacity: 0.45; }
2442
2481
  #codeTa {
2443
2482
  flex: 1;
2444
2483
  resize: none;
@@ -2449,7 +2488,9 @@ body.ide-mode #codePane { display: flex; }
2449
2488
  padding: 12px 14px;
2450
2489
  font-family: Consolas, "Cascadia Mono", monospace;
2451
2490
  font-size: 12.5px;
2452
- line-height: 1.55;
2491
+ line-height: 20px;
2492
+ white-space: pre;
2493
+ overflow: auto;
2453
2494
  }
2454
2495
  /* dikey scrollbar hep görünür, tutulabilir ve imleç değişsin */
2455
2496
  #codeTa::-webkit-scrollbar {
package/.env.example DELETED
@@ -1,8 +0,0 @@
1
- # Beast Agent API anahtarları örneği.
2
- # Kullanım: bu dosyayı %APPDATA%\beast\.env olarak kopyala ve anahtarlarını gir.
3
- # Bu dosya config.yaml'daki key_env alanlarıyla eşleşir;
4
- # key_env yoksa <PROVIDER_ID>_API_KEY denenir (örn. zhipu -> ZHIPU_API_KEY).
5
-
6
- OPENCODE_API_KEY=
7
- ZHIPU_API_KEY=
8
- OPENAI_API_KEY=
@@ -1,39 +0,0 @@
1
- # Beast Agent sağlayıcı yapılandırması örneği.
2
- # Kullanım: bu dosyayı %APPDATA%\beast\config.yaml olarak kopyala ve düzenle.
3
- # (Taşınabilir kullanım için BEAST_DATA ortam değişkeni ile başka klasöre alabilirsin.)
4
-
5
- # ÖNERİLEN: OpenCode Zen — ücretsiz modeller, kredi kartı gerekmez (opencode.ai/auth)
6
- providers:
7
- opencode:
8
- name: OpenCode Zen
9
- base_url: https://opencode.ai/zen/v1
10
- key_env: OPENCODE_API_KEY
11
- models:
12
- glm-5.2: {}
13
- kimi-k2.7-code: {}
14
- deepseek-v4-flash-free: {}
15
- big-pickle: {}
16
- minimax-m3: {}
17
- # OpenCode Go aboneliğin varsa base_url: https://opencode.ai/zen/go/v1 kullan.
18
-
19
- zhipu:
20
- name: Zhipu AI
21
- base_url: https://api.z.ai/api/paas/v4
22
- key_env: ZHIPU_API_KEY
23
- models:
24
- glm-4.6: {}
25
- glm-4.5-air: {}
26
-
27
- openai:
28
- name: OpenAI
29
- base_url: https://api.openai.com/v1
30
- key_env: OPENAI_API_KEY
31
- models:
32
- gpt-4o-mini: {}
33
- gpt-4o: {}
34
-
35
- model:
36
- provider: opencode # varsayılan provider id (yoksa ilk provider kullanılır)
37
- default: glm-5.2 # varsayılan model
38
- # base_url: ... # istersen aktif provider'ın URL'ini override et
39
- # key_env: ... # istersen anahtarı farklı env'den oku
package/eng.traineddata DELETED
Binary file
@@ -1,126 +0,0 @@
1
- 'use strict';
2
-
3
- /* BEAST — electron binary onarıcı.
4
- SORUN: `electron` npm paketi binary'yi (dist/electron.exe) postinstall'da
5
- GitHub'dan indirir. Taze makinalarda bu indirme SESSİZCE başarısız olabilir
6
- (proxy/GitHub engeli, npm ignore-scripts=true, ağ kesintisi) — paket kurulmuş
7
- görünür ama `require('electron')` "Electron failed to install correctly" fırlatır.
8
- ÇÖZÜM: install.js'i elle çalıştır; olmazsa yedek aynadan (npmmirror) dene.
9
- Kullanım yerleri:
10
- - package.json postinstall → kurulumda otomatik (npm i -g beast-agent)
11
- - bin/beast-agent.js → her başlatmada bozuksa otomatik onar */
12
-
13
- const fs = require('fs');
14
- const path = require('path');
15
- const { spawnSync } = require('child_process');
16
-
17
- /* electron paket dizini (index.js'in yeri); paket hiç yoksa null */
18
- function electronDir() {
19
- try {
20
- return path.dirname(require.resolve('electron'));
21
- } catch {
22
- return null;
23
- }
24
- }
25
-
26
- /* binary sağlam mı? electron/index.js'in beklentisiyle aynı kontrol:
27
- path.txt + dist/<exe> varlığı */
28
- function status() {
29
- const dir = electronDir();
30
- if (!dir) return { ok: false, missing: true };
31
- const exe = process.platform === 'win32' ? 'electron.exe' : 'electron';
32
- const distOk = fs.existsSync(path.join(dir, 'dist', exe));
33
- const txtOk = fs.existsSync(path.join(dir, 'path.txt'));
34
- return distOk && txtOk ? { ok: true, dir } : { ok: false, dir };
35
- }
36
-
37
- /* platforma göre dist içindeki çalıştırılabilirin göreli yolu (electron/index.js ile aynı) */
38
- function platformPath() {
39
- switch (process.platform) {
40
- case 'win32':
41
- return 'electron.exe';
42
- case 'darwin':
43
- case 'mas':
44
- return 'Electron.app/Contents/MacOS/Electron';
45
- default:
46
- return 'electron';
47
- }
48
- }
49
-
50
- /* onarım — 3 katman:
51
- 0) binary sağlam, yalnız path.txt eksik/bozuk → indirimsiz anında yazar
52
- (install.js bu durumu "zaten kurulu" sanıp atlayabiliyor)
53
- 1) dist bozuk/eksik → dist'i sil + install.js (GitHub) ile taze indir
54
- 2) GitHub engelli → ELECTRON_MIRROR=npmmirror ile tekrar */
55
- function repair({ quiet } = {}) {
56
- let st = status();
57
- if (st.ok) return { ok: true, dir: st.dir, skipped: true };
58
- if (st.missing) return { ok: false, error: 'electron paketi hi\u00e7 yok — npm install -g beast-agent' };
59
- const dir = st.dir;
60
- const exeRel = platformPath();
61
- const exeAbs = path.join(dir, 'dist', ...exeRel.split('/'));
62
- const verFile = path.join(dir, 'dist', 'version');
63
- let wantVer = null;
64
- try { wantVer = String(require(path.join(dir, 'package.json')).version || ''); } catch {}
65
- const distIntact =
66
- fs.existsSync(exeAbs) &&
67
- (!wantVer ||
68
- (fs.existsSync(verFile) &&
69
- fs.readFileSync(verFile, 'utf8').replace(/^v/, '').trim() === wantVer));
70
-
71
- if (distIntact) {
72
- /* KATMAN 0: hızlı onarım — path.txt'yi kendimiz yazıyoruz (indirim yok) */
73
- try { fs.writeFileSync(path.join(dir, 'path.txt'), exeRel, 'utf8'); } catch {}
74
- if (status().ok) return { ok: true, dir, fast: true };
75
- }
76
-
77
- /* KATMAN 1-2: tam indirim */
78
- try { fs.rmSync(path.join(dir, 'dist'), { recursive: true, force: true }); } catch {}
79
- try { fs.unlinkSync(path.join(dir, 'path.txt')); } catch {}
80
- const installJs = path.join(dir, 'install.js');
81
- if (!fs.existsSync(installJs)) {
82
- return { ok: false, error: 'install.js yok — yeniden kur: npm install -g beast-agent' };
83
- }
84
-
85
- const sources = [null, 'https://npmmirror.com/mirrors/electron/'];
86
- for (let i = 0; i < sources.length; i++) {
87
- const env = { ...process.env };
88
- if (sources[i]) {
89
- env.ELECTRON_MIRROR = sources[i];
90
- if (!quiet) console.log(' \u2022 varsay\u0131lan kaynak ba\u015Far\u0131s\u0131z \u2014 yedek ayna deneniyor (npmmirror)\u2026');
91
- } else if (!quiet) {
92
- console.log(' \u2022 electron binary indiriliyor (ilk sefer ~110 MB, 1-2 dk)\u2026');
93
- }
94
- const r = spawnSync(process.execPath, [installJs], {
95
- cwd: dir,
96
- env,
97
- stdio: quiet ? 'ignore' : 'inherit',
98
- timeout: 600000,
99
- });
100
- if (!r.error && r.status === 0 && status().ok) {
101
- return { ok: true, dir, mirror: sources[i] || 'github' };
102
- }
103
- if (!quiet && r.error) {
104
- console.log(' ! deneme ba\u015far\u0131s\u0131z: ' + String(r.error.message || r.error).slice(0, 160));
105
- }
106
- }
107
- return { ok: false, error: 'electron binary indirilemedi (a\u011f/proxy engeli olabilir)' };
108
- }
109
-
110
- module.exports = { electronDir, status, repair };
111
-
112
- /* CLI: package.json postinstall → `node scripts/fix-electron.js --soft`
113
- (her durumda exit 0 — npm install bozulmasın, başlatma anında tekrar denenir)
114
- elle çağrı → hata durumunda exit 1 */
115
- if (require.main === module) {
116
- const soft = process.argv.includes('--soft');
117
- const r = repair({ quiet: false });
118
- if (r.ok) {
119
- console.log(r.skipped ? '\u2713 electron binary tamam' : '\u2713 electron binary onar\u0131ld\u0131');
120
- process.exit(0);
121
- }
122
- console.error('\u2717 electron onar\u0131lamad\u0131: ' + (r.error || '?'));
123
- console.error(' elle \u00e7\u00f6z\u00fcm: npm config set ignore-scripts false');
124
- console.error(' npm install -g beast-agent');
125
- process.exit(soft ? 0 : 1);
126
- }