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.
- package/package.json +6 -3
- package/src/agent/engine.js +463 -21
- package/src/agent/llm.js +52 -3
- package/src/agent/obscura.js +26 -10
- package/src/agent/skills.js +2 -2
- package/src/agent/tools.js +519 -7
- package/src/main.js +28 -13
- package/src/renderer/i18n.js +7 -7
- package/src/renderer/index.html +5 -2
- package/src/renderer/renderer.js +154 -5
- package/src/renderer/style.css +45 -4
- package/.env.example +0 -8
- package/config.example.yaml +0 -39
- package/eng.traineddata +0 -0
- package/scripts/fix-electron.js +0 -126
- package/scripts/release.js +0 -121
- package/scripts/swap-electron.js +0 -40
- package/store/skills.json +0 -5
- package/tests/approval.test.js +0 -56
- package/tests/bg-jobs.test.js +0 -424
- package/tests/bots-name.test.js +0 -42
- package/tests/bus.test.js +0 -46
- package/tests/computeruse-context.test.js +0 -69
- package/tests/cron.test.js +0 -95
- package/tests/engine.test.js +0 -203
- package/tests/eval.test.js +0 -91
- package/tests/fallout.test.js +0 -188
- package/tests/llm.test.js +0 -205
- package/tests/memory.test.js +0 -33
- package/tests/memoryloop.test.js +0 -26
- package/tests/notegen.test.js +0 -63
- package/tests/obscura.test.js +0 -124
- package/tests/owner.test.js +0 -32
- package/tests/python.test.js +0 -76
- package/tests/research.test.js +0 -116
- package/tests/scenarios.json +0 -81
- package/tests/sessioncode.test.js +0 -50
- package/tests/setup.js +0 -9
- package/tests/tokens.test.js +0 -42
- package/tests/tools.test.js +0 -84
- package/tests/usage.test.js +0 -44
- package/tests/v11.test.js +0 -76
- package/tests/watchers.test.js +0 -206
- package/tests/watext.test.js +0 -53
- package/tests/whatsapp.test.js +0 -103
- package/tests/wherewasi.test.js +0 -40
package/src/renderer/i18n.js
CHANGED
|
@@ -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).
|
|
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
|
|
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
|
|
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).
|
|
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
|
|
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
|
|
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.',
|
package/src/renderer/index.html
CHANGED
|
@@ -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">❯︎</button>
|
|
78
79
|
<button id="browserBtn" class="dd-btn dd-icon-btn" title="Dahili tarayıcı" data-i18n-title="tipBrowser">⧉</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
|
-
<
|
|
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>
|
package/src/renderer/renderer.js
CHANGED
|
@@ -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,
|
|
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
|
|
package/src/renderer/style.css
CHANGED
|
@@ -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 (
|
|
298
|
-
#netDot {
|
|
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:
|
|
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=
|
package/config.example.yaml
DELETED
|
@@ -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
|
package/scripts/fix-electron.js
DELETED
|
@@ -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
|
-
}
|