beast-agent 1.1.0 → 1.2.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 +1 -1
- package/src/agent/agentdefs.js +122 -0
- package/src/agent/engine.js +176 -22
- package/src/agent/skills.js +1 -0
- package/src/agent/tools.js +527 -35
- package/src/main.js +41 -0
- package/src/preload.js +1 -0
- package/src/renderer/index.html +7 -1
- package/src/renderer/renderer.js +291 -13
- package/src/renderer/style.css +369 -254
package/src/main.js
CHANGED
|
@@ -662,6 +662,7 @@ function waSlashHelp() {
|
|
|
662
662
|
'• */notes* – bu oturumun notlarını göster',
|
|
663
663
|
'• */notify* on|off – hata mail bildirimini aç/kapa',
|
|
664
664
|
'• */think* <0-5> – düşünme seviyesi (0 kapalı · 1 low · 2 medium · 3 high · 4 xhigh · 5 max)',
|
|
665
|
+
'• */agent* [isim] – özel ajan bağla/listele (%APPDATA%\beast\agents)',
|
|
665
666
|
'• */clear* – bu oturumun geçmişini temizle',
|
|
666
667
|
'• */screenshot* – masaüstü ekran görüntüsünü gönder',
|
|
667
668
|
'• */rule* <metin> – kalıcı kural ekle (*/rules*: liste)',
|
|
@@ -3925,6 +3926,32 @@ ipcMain.handle('agent:send', (_e, { sessionId, text }) => {
|
|
|
3925
3926
|
desktopEcho(sessionId, t, r && r.error ? r.error : r ? r.text : thinkStatusText());
|
|
3926
3927
|
return true;
|
|
3927
3928
|
}
|
|
3929
|
+
if (t === '/agent' || t.startsWith('/agent ')) {
|
|
3930
|
+
/* opencode agent port: özel ajan tanımları (%APPDATA%\beast\agents\*.md) */
|
|
3931
|
+
const arg = t.slice(6).trim();
|
|
3932
|
+
if (!arg) {
|
|
3933
|
+
const list = engine.listAgents();
|
|
3934
|
+
desktopEcho(
|
|
3935
|
+
sessionId,
|
|
3936
|
+
t,
|
|
3937
|
+
list.length
|
|
3938
|
+
? '**Özel ajanlar:**\n' + list.map((d) => `- **${d.name}**${d.model ? ' · ' + d.model : ''}${d.steps ? ' · ' + d.steps + ' tur' : ''}${d.tools ? ' · ' + d.tools.length + ' araç' : ''}`).join('\n') + '\n\nBağlamak için: **/agent <isim>** · ayırmak için: **/agent off**'
|
|
3939
|
+
: 'Özel ajan yok — `%APPDATA%\\beast\\agents\\` klasörüne `<isim>.md` tanımı koy (örnek dosya orada).'
|
|
3940
|
+
);
|
|
3941
|
+
return true;
|
|
3942
|
+
}
|
|
3943
|
+
const r = engine.setSessionAgent(sessionId, arg);
|
|
3944
|
+
desktopEcho(
|
|
3945
|
+
sessionId,
|
|
3946
|
+
t,
|
|
3947
|
+
r.ok
|
|
3948
|
+
? r.agent
|
|
3949
|
+
? `**Ajan bağlandı: ${r.agent}**${r.model ? ' · model: ' + r.model : ''}${r.steps ? ' · ' + r.steps + ' tur' : ''}${r.tools ? ' · araçlar: ' + r.tools.join(', ') : ''}`
|
|
3950
|
+
: '**Ajan bağlantısı kaldırıldı** — oturum normal akışa döndü.'
|
|
3951
|
+
: r.error
|
|
3952
|
+
);
|
|
3953
|
+
return true;
|
|
3954
|
+
}
|
|
3928
3955
|
if (t === '/clear') {
|
|
3929
3956
|
/* #25 artık GERÇEK silme: oturum dosyasındaki mesajlar + notlar silinir,
|
|
3930
3957
|
kod/meta/todolar korunur. Ekran da temizlenir ('clear' olayı). */
|
|
@@ -4008,6 +4035,7 @@ function desktopSlashHelp() {
|
|
|
4008
4035
|
'**/change [n]** – modelleri listele · n. modele geç',
|
|
4009
4036
|
'**/model [isim]** – aktif modeli göster / değiştir',
|
|
4010
4037
|
'**/think 0-5** – düşünme seviyesi (0 kapalı · 5 max)',
|
|
4038
|
+
'**/agent [isim]** – özel ajan bağla / listele (%APPDATA%\\beast\\agents\\*.md)',
|
|
4011
4039
|
'**/clear** – oturum geçmişini gerçekten sil (kod korunur)',
|
|
4012
4040
|
'**/notes** – bu oturumun notlarını göster',
|
|
4013
4041
|
'**/rule <metin>** – kalıcı kural ekle · **/rules** – listele',
|
|
@@ -4458,9 +4486,22 @@ ipcMain.handle('model:set', (_e, sel) => {
|
|
|
4458
4486
|
saveSettings();
|
|
4459
4487
|
engine.setModelOverride(sel);
|
|
4460
4488
|
}
|
|
4489
|
+
/* IDE/Beast Code dahil tüm paneller anlık haberdar olsun — picker +
|
|
4490
|
+
durum etiketleri kapatıp açmadan güncellenir */
|
|
4491
|
+
try { win && !win.isDestroyed() && win.webContents.send('agent:event', { type: 'modelChanged' }); } catch {}
|
|
4461
4492
|
return engine.publicState();
|
|
4462
4493
|
});
|
|
4463
4494
|
|
|
4495
|
+
/* Paralel ajan geçmişini TOPLUCA sil (rail başlığındaki çöp ikonu) */
|
|
4496
|
+
ipcMain.handle('agents:clearAll', () => {
|
|
4497
|
+
try {
|
|
4498
|
+
const removed = engine.clearAllBgJobs();
|
|
4499
|
+
return { ok: true, removed };
|
|
4500
|
+
} catch (e) {
|
|
4501
|
+
return { ok: false, error: String((e && e.message) || e) };
|
|
4502
|
+
}
|
|
4503
|
+
});
|
|
4504
|
+
|
|
4464
4505
|
ipcMain.handle('model:role', (_e, map) => {
|
|
4465
4506
|
const roleModels = {};
|
|
4466
4507
|
const allowed = {};
|
package/src/preload.js
CHANGED
|
@@ -180,6 +180,7 @@ contextBridge.exposeInMainWorld('beast', {
|
|
|
180
180
|
idePreview: () => ipcRenderer.invoke('ide:preview'),
|
|
181
181
|
idePreviewFile: (rel) => ipcRenderer.invoke('ide:previewFile', rel),
|
|
182
182
|
idePreviewUrl: (url) => ipcRenderer.invoke('ide:previewUrl', url),
|
|
183
|
+
agentsClearAll: () => ipcRenderer.invoke('agents:clearAll'),
|
|
183
184
|
ideDelete: (rel) => ipcRenderer.invoke('ide:delete', rel),
|
|
184
185
|
onWaEvent: (cb) => ipcRenderer.on('wa:event', (_e, ev) => cb(ev)),
|
|
185
186
|
onEvent: (cb) => ipcRenderer.on('agent:event', (_e, ev) => cb(ev)),
|
package/src/renderer/index.html
CHANGED
|
@@ -130,6 +130,7 @@
|
|
|
130
130
|
</div>
|
|
131
131
|
<div id="bcOut"></div>
|
|
132
132
|
<div id="bcTodoWrap" hidden></div>
|
|
133
|
+
<div id="bcStatus" hidden></div>
|
|
133
134
|
<div id="bcInputRow">
|
|
134
135
|
<span id="bcPrompt">code></span>
|
|
135
136
|
<input id="bcInput" spellcheck="false" autocomplete="off" placeholder="Beast Code mesajı yaz — Enter ile gönder…" data-i18n-ph="bc_ph" />
|
|
@@ -140,7 +141,12 @@
|
|
|
140
141
|
</main>
|
|
141
142
|
|
|
142
143
|
<aside id="rail">
|
|
143
|
-
<div id="railHead"
|
|
144
|
+
<div id="railHead">
|
|
145
|
+
<span id="railTitle" data-i18n="labelParallel">Paralel Ajanlar</span>
|
|
146
|
+
<button id="railClear" title="Tüm paralel ajan geçmişini sil" aria-label="Tüm paralel ajan geçmişini sil">
|
|
147
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#111" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18"/><path d="M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6"/><path d="M14 11v6"/></svg>
|
|
148
|
+
</button>
|
|
149
|
+
</div>
|
|
144
150
|
<div id="railList"></div>
|
|
145
151
|
<div id="sideFoot2">
|
|
146
152
|
<span class="foot-label2" data-i18n="labelParallel">Paralel Ajanlar</span>
|
package/src/renderer/renderer.js
CHANGED
|
@@ -42,6 +42,7 @@ const els = {
|
|
|
42
42
|
eyeBtn: $('#eyeBtn'),
|
|
43
43
|
netDot: $('#netDot'),
|
|
44
44
|
railBtn: $('#railBtn'),
|
|
45
|
+
railClear: $('#railClear'),
|
|
45
46
|
watchBtn: $('#watchBtn'),
|
|
46
47
|
cronBtn: $('#cronBtn'),
|
|
47
48
|
watchOverlay: $('#watchOverlay'),
|
|
@@ -76,6 +77,7 @@ const els = {
|
|
|
76
77
|
bcClear: $('#bcClear'),
|
|
77
78
|
bcNew: $('#bcNew'),
|
|
78
79
|
bcTodoWrap: $('#bcTodoWrap'),
|
|
80
|
+
bcStatus: $('#bcStatus'),
|
|
79
81
|
codeTabs: $('#codeTabs'),
|
|
80
82
|
codeTa: $('#codeTa'),
|
|
81
83
|
codeGutter: $('#codeGutter'),
|
|
@@ -411,6 +413,176 @@ function addStopNote(reason) {
|
|
|
411
413
|
scrollDown(true);
|
|
412
414
|
}
|
|
413
415
|
|
|
416
|
+
/* ---------------- opencode diff görünümü (BİREBİR port) ----------------
|
|
417
|
+
edit_file/write_file sonuçları chat'te ve Beast Code panelinde opencode'un
|
|
418
|
+
permission/diff ekranı gibi gösterilir: SOLDa kırmızı (eski/silinen),
|
|
419
|
+
SAĞDA yeşil (yeni/eklenen) — dar alanda birleşik (unified) görünüme düşer.
|
|
420
|
+
Motor: LCS tabanlı satır diff'i (opencode npm "diff" paketinin diffLines
|
|
421
|
+
karşılığı) + del/add blok eşleştirmesi (split görünüm hizalaması). */
|
|
422
|
+
function diffOps(aText, bText) {
|
|
423
|
+
const a = aText ? String(aText).split('\n') : [];
|
|
424
|
+
const b = bText ? String(bText).split('\n') : [];
|
|
425
|
+
let p = 0;
|
|
426
|
+
while (p < a.length && p < b.length && a[p] === b[p]) p++;
|
|
427
|
+
let ea = a.length - 1;
|
|
428
|
+
let eb = b.length - 1;
|
|
429
|
+
while (ea >= p && eb >= p && a[ea] === b[eb]) { ea--; eb--; }
|
|
430
|
+
const ops = [];
|
|
431
|
+
for (let i = 0; i < p; i++) ops.push({ t: 'ctx', a: a[i], b: b[i] });
|
|
432
|
+
const midA = a.slice(p, ea + 1);
|
|
433
|
+
const midB = b.slice(p, eb + 1);
|
|
434
|
+
const n = midA.length;
|
|
435
|
+
const m = midB.length;
|
|
436
|
+
if (n * m > 400000 || n > 1500 || m > 1500) {
|
|
437
|
+
for (const x of midA) ops.push({ t: 'del', a: x });
|
|
438
|
+
for (const y of midB) ops.push({ t: 'add', b: y });
|
|
439
|
+
} else {
|
|
440
|
+
const w = m + 1;
|
|
441
|
+
const dp = new Int32Array((n + 1) * w);
|
|
442
|
+
for (let i = n - 1; i >= 0; i--) {
|
|
443
|
+
for (let j = m - 1; j >= 0; j--) {
|
|
444
|
+
dp[i * w + j] =
|
|
445
|
+
midA[i] === midB[j]
|
|
446
|
+
? dp[(i + 1) * w + j + 1] + 1
|
|
447
|
+
: Math.max(dp[(i + 1) * w + j], dp[i * w + j + 1]);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
let i = 0;
|
|
451
|
+
let j = 0;
|
|
452
|
+
while (i < n && j < m) {
|
|
453
|
+
if (midA[i] === midB[j]) { ops.push({ t: 'ctx', a: midA[i], b: midB[j] }); i++; j++; }
|
|
454
|
+
else if (dp[(i + 1) * w + j] >= dp[i * w + j + 1]) { ops.push({ t: 'del', a: midA[i] }); i++; }
|
|
455
|
+
else { ops.push({ t: 'add', b: midB[j] }); j++; }
|
|
456
|
+
}
|
|
457
|
+
while (i < n) ops.push({ t: 'del', a: midA[i++] });
|
|
458
|
+
while (j < m) ops.push({ t: 'add', b: midB[j++] });
|
|
459
|
+
}
|
|
460
|
+
for (let k = ea + 1; k < a.length; k++) ops.push({ t: 'ctx', a: a[k], b: b[k] });
|
|
461
|
+
return ops;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/* del/add bloklarını yan yana hizalar: split görünümde sol satır ile sağ satır
|
|
465
|
+
aynı yükseklikte durur; eksik taraf boş "space" satırla doldurulur */
|
|
466
|
+
function diffSplitRows(ops, startLine) {
|
|
467
|
+
const rows = [];
|
|
468
|
+
let oldNo = Math.max(1, startLine || 1);
|
|
469
|
+
let newNo = oldNo;
|
|
470
|
+
let i = 0;
|
|
471
|
+
while (i < ops.length) {
|
|
472
|
+
const op = ops[i];
|
|
473
|
+
if (op.t === 'ctx') {
|
|
474
|
+
rows.push({ l: { no: oldNo++, text: op.a, cls: 'ctx' }, r: { no: newNo++, text: op.b, cls: 'ctx' } });
|
|
475
|
+
i++;
|
|
476
|
+
continue;
|
|
477
|
+
}
|
|
478
|
+
const dels = [];
|
|
479
|
+
const adds = [];
|
|
480
|
+
while (i < ops.length && ops[i].t !== 'ctx') {
|
|
481
|
+
if (ops[i].t === 'del') dels.push(ops[i].a);
|
|
482
|
+
else adds.push(ops[i].b);
|
|
483
|
+
i++;
|
|
484
|
+
}
|
|
485
|
+
const max = Math.max(dels.length, adds.length);
|
|
486
|
+
for (let k = 0; k < max; k++) {
|
|
487
|
+
rows.push({
|
|
488
|
+
l: k < dels.length ? { no: oldNo++, text: dels[k], cls: 'del' } : { no: '', text: '', cls: 'space' },
|
|
489
|
+
r: k < adds.length ? { no: newNo++, text: adds[k], cls: 'add' } : { no: '', text: '', cls: 'space' },
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
return rows;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
const DIFF_RENDER_MAX_ROWS = 400; /* dev değişikliklerde DOM şişmesin */
|
|
497
|
+
|
|
498
|
+
function diffLineEl(no, text, cls, sign) {
|
|
499
|
+
const line = document.createElement('div');
|
|
500
|
+
line.className = 'diff-line ' + cls;
|
|
501
|
+
const num = document.createElement('span');
|
|
502
|
+
num.className = 'diff-num';
|
|
503
|
+
num.textContent = String(no);
|
|
504
|
+
const code = document.createElement('span');
|
|
505
|
+
code.className = 'diff-code';
|
|
506
|
+
code.textContent = (sign || '') + text;
|
|
507
|
+
line.appendChild(num);
|
|
508
|
+
line.appendChild(code);
|
|
509
|
+
return line;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/* opencode <diff view="split|unified"> karşılığı: genişlik >= 620px ise
|
|
513
|
+
yan-yana (solda kırmızı eski / sağda yeşil yeni), dar ise birleşik */
|
|
514
|
+
function buildDiffEl(diff, availWidth) {
|
|
515
|
+
const wrap = document.createElement('div');
|
|
516
|
+
wrap.className = 'diffbox';
|
|
517
|
+
const head = document.createElement('div');
|
|
518
|
+
head.className = 'diff-head';
|
|
519
|
+
const fname = document.createElement('span');
|
|
520
|
+
fname.className = 'diff-file';
|
|
521
|
+
fname.textContent = String(diff.path || '');
|
|
522
|
+
const badge = document.createElement('span');
|
|
523
|
+
badge.className = 'diff-badge';
|
|
524
|
+
const a = document.createElement('span');
|
|
525
|
+
a.className = 'diff-badge-add';
|
|
526
|
+
a.textContent = '+' + (diff.additions || 0);
|
|
527
|
+
const d = document.createElement('span');
|
|
528
|
+
d.className = 'diff-badge-del';
|
|
529
|
+
d.textContent = '−' + (diff.deletions || 0);
|
|
530
|
+
badge.appendChild(a);
|
|
531
|
+
badge.appendChild(d);
|
|
532
|
+
head.appendChild(fname);
|
|
533
|
+
head.appendChild(badge);
|
|
534
|
+
wrap.appendChild(head);
|
|
535
|
+
|
|
536
|
+
const ops = diffOps(diff.before, diff.after);
|
|
537
|
+
const split = (availWidth || 0) >= 620;
|
|
538
|
+
const view = document.createElement('div');
|
|
539
|
+
view.className = 'diff ' + (split ? 'diff-split' : 'diff-uni');
|
|
540
|
+
if (split) {
|
|
541
|
+
const rows = diffSplitRows(ops, diff.startLine);
|
|
542
|
+
const left = document.createElement('div');
|
|
543
|
+
left.className = 'diff-side old';
|
|
544
|
+
const right = document.createElement('div');
|
|
545
|
+
right.className = 'diff-side new';
|
|
546
|
+
const capped = rows.length > DIFF_RENDER_MAX_ROWS;
|
|
547
|
+
for (const row of rows.slice(0, DIFF_RENDER_MAX_ROWS)) {
|
|
548
|
+
left.appendChild(diffLineEl(row.l.no, row.l.text, row.l.cls, ''));
|
|
549
|
+
right.appendChild(diffLineEl(row.r.no, row.r.text, row.r.cls, ''));
|
|
550
|
+
}
|
|
551
|
+
view.appendChild(left);
|
|
552
|
+
view.appendChild(right);
|
|
553
|
+
if (capped) {
|
|
554
|
+
const note = document.createElement('div');
|
|
555
|
+
note.className = 'diff-more';
|
|
556
|
+
note.textContent = `… ${rows.length - DIFF_RENDER_MAX_ROWS} satır daha (dosyada gör)`;
|
|
557
|
+
view.appendChild(note);
|
|
558
|
+
}
|
|
559
|
+
} else {
|
|
560
|
+
let oldNo = Math.max(1, diff.startLine || 1);
|
|
561
|
+
let newNo = oldNo;
|
|
562
|
+
const capped = ops.length > DIFF_RENDER_MAX_ROWS;
|
|
563
|
+
for (const op of ops.slice(0, DIFF_RENDER_MAX_ROWS)) {
|
|
564
|
+
if (op.t === 'ctx') {
|
|
565
|
+
view.appendChild(diffLineEl(newNo, op.b, 'ctx', ' '));
|
|
566
|
+
oldNo++; newNo++;
|
|
567
|
+
} else if (op.t === 'del') {
|
|
568
|
+
view.appendChild(diffLineEl(oldNo, op.a, 'del', '-'));
|
|
569
|
+
oldNo++;
|
|
570
|
+
} else {
|
|
571
|
+
view.appendChild(diffLineEl(newNo, op.b, 'add', '+'));
|
|
572
|
+
newNo++;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
if (capped) {
|
|
576
|
+
const note = document.createElement('div');
|
|
577
|
+
note.className = 'diff-more';
|
|
578
|
+
note.textContent = `… ${ops.length - DIFF_RENDER_MAX_ROWS} satır daha (dosyada gör)`;
|
|
579
|
+
view.appendChild(note);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
wrap.appendChild(view);
|
|
583
|
+
return wrap;
|
|
584
|
+
}
|
|
585
|
+
|
|
414
586
|
/* ---------------- tool cards ---------------- */
|
|
415
587
|
/* Ard arda gelen araç kartları TEK kutuda toplanır (.tool-box): çalışırken
|
|
416
588
|
lacivert outline döner, gövde max 420px scroll'lu. Grup; tool_calls İÇEREN
|
|
@@ -425,7 +597,9 @@ function closeChatToolGroup() {
|
|
|
425
597
|
function argSummary(name, args) {
|
|
426
598
|
try {
|
|
427
599
|
if (name === 'run_command') return String(args.command || '');
|
|
428
|
-
if (name === 'read_file' || name === 'write_file') return String(args.path || '');
|
|
600
|
+
if (name === 'read_file' || name === 'write_file' || name === 'edit_file') return String(args.path || '');
|
|
601
|
+
if (name === 'grep') return String(args.pattern || '');
|
|
602
|
+
if (name === 'glob') return String(args.pattern || '');
|
|
429
603
|
if (name === 'list_dir') return String(args.path || '.');
|
|
430
604
|
if (name === 'memory_write' || name === 'user_write') return String(args.text || '').slice(0, 80);
|
|
431
605
|
return JSON.stringify(args).slice(0, 100);
|
|
@@ -468,7 +642,10 @@ function addToolCard(callId, name, args) {
|
|
|
468
642
|
return card;
|
|
469
643
|
}
|
|
470
644
|
|
|
471
|
-
|
|
645
|
+
/* opencode tool-end portu: edit/write sonucu ham JSON yerine kırmızı/yeşil
|
|
646
|
+
DIFF olarak çizilir (opencode'un permission/diff ekranı); diğer araçlar
|
|
647
|
+
eskisi gibi düz metin gösterir */
|
|
648
|
+
function finishToolCard(callId, ok, result, diff) {
|
|
472
649
|
const sel = callId
|
|
473
650
|
? `.tool-card[data-call-id="${CSS.escape(callId)}"]`
|
|
474
651
|
: null;
|
|
@@ -479,8 +656,29 @@ function finishToolCard(callId, ok, result) {
|
|
|
479
656
|
st.classList.add(ok ? 'ok' : 'err');
|
|
480
657
|
st.textContent = ok ? 'tamam' : 'hata';
|
|
481
658
|
const body = card.querySelector('.tool-body');
|
|
482
|
-
|
|
483
|
-
|
|
659
|
+
if (diff && diff.path) {
|
|
660
|
+
/* başlığa +/- rozetleri (opencode filediff additions/deletions) */
|
|
661
|
+
const head = card.querySelector('.tool-head');
|
|
662
|
+
if (head && !head.querySelector('.diff-badge')) {
|
|
663
|
+
const badge = document.createElement('span');
|
|
664
|
+
badge.className = 'diff-badge';
|
|
665
|
+
const a = document.createElement('span');
|
|
666
|
+
a.className = 'diff-badge-add';
|
|
667
|
+
a.textContent = '+' + (diff.additions || 0);
|
|
668
|
+
const d = document.createElement('span');
|
|
669
|
+
d.className = 'diff-badge-del';
|
|
670
|
+
d.textContent = '−' + (diff.deletions || 0);
|
|
671
|
+
badge.appendChild(a);
|
|
672
|
+
badge.appendChild(d);
|
|
673
|
+
head.insertBefore(badge, st);
|
|
674
|
+
}
|
|
675
|
+
body.textContent = '';
|
|
676
|
+
body.classList.add('open', 'diff-body');
|
|
677
|
+
body.appendChild(buildDiffEl(diff, body.clientWidth || 800));
|
|
678
|
+
} else {
|
|
679
|
+
body.textContent = String(result || '(çıktı yok)').slice(0, 4000);
|
|
680
|
+
if (String(result || '').length <= 300) body.classList.add('open');
|
|
681
|
+
}
|
|
484
682
|
/* ring burada söndürülmez — iş bitene kadar (closeChatToolGroup) döner */
|
|
485
683
|
if (chatToolGroup && chatToolGroup.body.contains(card)) {
|
|
486
684
|
chatToolGroup.body.scrollTop = chatToolGroup.body.scrollHeight;
|
|
@@ -621,7 +819,7 @@ async function openSession(id) {
|
|
|
621
819
|
addToolCard(tc.id, tc.function.name, args);
|
|
622
820
|
const out = s.messages[i + 1];
|
|
623
821
|
if (out && out.role === 'tool' && out.tool_call_id === tc.id) {
|
|
624
|
-
finishToolCard(tc.id, true, out.content);
|
|
822
|
+
finishToolCard(tc.id, true, out.content, out.diffView);
|
|
625
823
|
i++;
|
|
626
824
|
} else {
|
|
627
825
|
finishToolCard(tc.id, false, '(sonuç yok)');
|
|
@@ -3906,11 +4104,11 @@ function onEvent(ev) {
|
|
|
3906
4104
|
addToolCard(ev.callId, ev.name, ev.args);
|
|
3907
4105
|
setStatus(ev.name + '…');
|
|
3908
4106
|
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);
|
|
4107
|
+
/* ajan dosya yazarsa/editlerse açık IDE sekmesini izlemeye al */
|
|
4108
|
+
if ((ev.name === 'write_file' || ev.name === 'edit_file') && ev.args && ev.args.path) codeWriteWatch.set(ev.callId, ev.args.path);
|
|
3911
4109
|
break;
|
|
3912
4110
|
case 'tool-end':
|
|
3913
|
-
finishToolCard(ev.callId, ev.ok, ev.result);
|
|
4111
|
+
finishToolCard(ev.callId, ev.ok, ev.result, ev.diff);
|
|
3914
4112
|
setStatus('düşünüyor…');
|
|
3915
4113
|
termAgentEvent(ev);
|
|
3916
4114
|
if (codeWriteWatch.has(ev.callId)) {
|
|
@@ -4843,9 +5041,29 @@ async function init() {
|
|
|
4843
5041
|
});
|
|
4844
5042
|
}
|
|
4845
5043
|
if (els.railBtn) els.railBtn.addEventListener('click', () => {
|
|
5044
|
+
const willOpen = document.body.classList.contains('rail-hidden');
|
|
5045
|
+
/* IDE modunda rail istenirse açık tarayıcı yerini bırakır — ikisi aynı
|
|
5046
|
+
sağ dock'u paylaşır; tarayıcı kapanma olayı rail'i tekrar KAPATMASIN
|
|
5047
|
+
diye railPrefBeforeBrowser=true ile bırakılır */
|
|
5048
|
+
if (willOpen && ideModeOn() && document.body.classList.contains('browser-open')) {
|
|
5049
|
+
railPrefBeforeBrowser = true;
|
|
5050
|
+
els.bbClose.click();
|
|
5051
|
+
}
|
|
4846
5052
|
toggleRail(!document.body.classList.contains('rail-hidden'));
|
|
4847
5053
|
railPrefBeforeBrowser = !document.body.classList.contains('rail-hidden');
|
|
4848
5054
|
});
|
|
5055
|
+
if (els.railClear) {
|
|
5056
|
+
els.railClear.addEventListener('click', async () => {
|
|
5057
|
+
if (!confirm('TÜM paralel ajan geçmişi silinsin mi?\n(Çalışan ajanlar da iptal edilir — geri alınamaz)')) return;
|
|
5058
|
+
try {
|
|
5059
|
+
const r = await beast.agentsClearAll();
|
|
5060
|
+
if (r && r.ok) toast('Paralel ajan geçmişi silindi' + (r.removed ? ' — ' + r.removed + ' iş' : ''));
|
|
5061
|
+
else toast('Silinemedi: ' + ((r && r.error) || '?'));
|
|
5062
|
+
} catch (e) {
|
|
5063
|
+
toast('Silinemedi: ' + String((e && e.message) || e));
|
|
5064
|
+
}
|
|
5065
|
+
});
|
|
5066
|
+
}
|
|
4849
5067
|
els.bbBack.addEventListener('click', () => beast.browserCtrl('back'));
|
|
4850
5068
|
els.bbFwd.addEventListener('click', () => beast.browserCtrl('forward'));
|
|
4851
5069
|
els.bbReload.addEventListener('click', () => beast.browserCtrl('reload'));
|
|
@@ -5828,6 +6046,21 @@ async function renderFileTree() {
|
|
|
5828
6046
|
await build('', 0, tree);
|
|
5829
6047
|
}
|
|
5830
6048
|
|
|
6049
|
+
/* Ağaç otomatik tazeleme: ajan dosya/klasör ürettikçe soldaki panel KENDİ
|
|
6050
|
+
kendisi yenilenir — elle yenileme yok. Açık klasörler (ideState.open)
|
|
6051
|
+
korunur; debounce paralel araç patlamalarını tek çizime indirir. */
|
|
6052
|
+
let ideTreeTimer = null;
|
|
6053
|
+
function ideRefreshTree() {
|
|
6054
|
+
if (ideTreeTimer) return;
|
|
6055
|
+
ideTreeTimer = setTimeout(() => {
|
|
6056
|
+
ideTreeTimer = null;
|
|
6057
|
+
try {
|
|
6058
|
+
ideState.cache.clear();
|
|
6059
|
+
renderFileTree().catch(() => {});
|
|
6060
|
+
} catch {}
|
|
6061
|
+
}, 600);
|
|
6062
|
+
}
|
|
6063
|
+
|
|
5831
6064
|
/* ---------- sekmeli kod editörü (VS Code düzeni) ----------
|
|
5832
6065
|
Dosya tıklaması MODAL değil, codePane içinde SEKME açar.
|
|
5833
6066
|
Yanında Beast Code chat'i, onun sağındaki preview tarayıcı durur. */
|
|
@@ -6270,6 +6503,20 @@ function bcStreamDelta(delta) {
|
|
|
6270
6503
|
/* İş bitti → preview açık ve IDE modundaysa workspace sayfasını otomatik yenile */
|
|
6271
6504
|
let bcPrevAt = 0;
|
|
6272
6505
|
|
|
6506
|
+
/* Beast Code durum balonu: düşünüyor… / araç adları / durum satırları —
|
|
6507
|
+
chat inputun üstündeki balonun BC panelindeki karşılığı */
|
|
6508
|
+
function bcStatusShow(text) {
|
|
6509
|
+
if (!els.bcStatus) return;
|
|
6510
|
+
const t = String(text || '').trim();
|
|
6511
|
+
if (!t) return;
|
|
6512
|
+
els.bcStatus.textContent = t;
|
|
6513
|
+
els.bcStatus.hidden = false;
|
|
6514
|
+
}
|
|
6515
|
+
|
|
6516
|
+
function bcStatusHide() {
|
|
6517
|
+
if (els.bcStatus) els.bcStatus.hidden = true;
|
|
6518
|
+
}
|
|
6519
|
+
|
|
6273
6520
|
function bcRefreshPreview() {
|
|
6274
6521
|
const now = Date.now();
|
|
6275
6522
|
if (now - bcPrevAt < 1500) return; /* done + idle çift tetiklemesin */
|
|
@@ -6354,7 +6601,7 @@ function bcToolBoxStart(callId, name, args) {
|
|
|
6354
6601
|
bcBodyScroll(body);
|
|
6355
6602
|
}
|
|
6356
6603
|
|
|
6357
|
-
function bcToolBoxEnd(callId, ok, result) {
|
|
6604
|
+
function bcToolBoxEnd(callId, ok, result, diff) {
|
|
6358
6605
|
bcFlushStream();
|
|
6359
6606
|
const t = (callId && bcTools.get(callId)) || null;
|
|
6360
6607
|
if (callId) bcTools.delete(callId);
|
|
@@ -6365,7 +6612,27 @@ function bcToolBoxEnd(callId, ok, result) {
|
|
|
6365
6612
|
sec.classList.add('done');
|
|
6366
6613
|
if (!ok) sec.classList.add('failed');
|
|
6367
6614
|
const pre = sec.querySelector('.bc-toolout');
|
|
6368
|
-
if (
|
|
6615
|
+
if (diff && diff.path) {
|
|
6616
|
+
/* opencode diff görünümü: başlığa +/- rozeti, gövdeye kırmızı/yeşil diff */
|
|
6617
|
+
const headEl = sec.querySelector('.bc-toolhead');
|
|
6618
|
+
if (headEl && !headEl.querySelector('.diff-badge')) {
|
|
6619
|
+
const badge = document.createElement('span');
|
|
6620
|
+
badge.className = 'diff-badge';
|
|
6621
|
+
const a = document.createElement('span');
|
|
6622
|
+
a.className = 'diff-badge-add';
|
|
6623
|
+
a.textContent = '+' + (diff.additions || 0);
|
|
6624
|
+
const d = document.createElement('span');
|
|
6625
|
+
d.className = 'diff-badge-del';
|
|
6626
|
+
d.textContent = '−' + (diff.deletions || 0);
|
|
6627
|
+
badge.appendChild(a);
|
|
6628
|
+
badge.appendChild(d);
|
|
6629
|
+
headEl.appendChild(badge);
|
|
6630
|
+
}
|
|
6631
|
+
pre.hidden = false;
|
|
6632
|
+
pre.textContent = '';
|
|
6633
|
+
pre.classList.add('bc-diffview');
|
|
6634
|
+
pre.appendChild(buildDiffEl(diff, pre.clientWidth || 480));
|
|
6635
|
+
} else if (out) {
|
|
6369
6636
|
pre.hidden = false;
|
|
6370
6637
|
pre.textContent = out.length > 4000 ? out.slice(0, 4000) + '\n… (kesildi)' : out;
|
|
6371
6638
|
} else {
|
|
@@ -6465,16 +6732,20 @@ function bcIngest(ev) {
|
|
|
6465
6732
|
break;
|
|
6466
6733
|
case 'tool-start':
|
|
6467
6734
|
bcToolBoxStart(ev.callId, ev.name, ev.args);
|
|
6468
|
-
/* ajan dosya yazarsa açık IDE sekmesini izlemeye al */
|
|
6469
|
-
if (ev.name === 'write_file' && ev.args && ev.args.path) codeWriteWatch.set(ev.callId, ev.args.path);
|
|
6735
|
+
/* ajan dosya yazarsa/editlerse açık IDE sekmesini izlemeye al */
|
|
6736
|
+
if ((ev.name === 'write_file' || ev.name === 'edit_file') && ev.args && ev.args.path) codeWriteWatch.set(ev.callId, ev.args.path);
|
|
6470
6737
|
break;
|
|
6471
6738
|
case 'tool-end':
|
|
6472
|
-
bcToolBoxEnd(ev.callId, ev.ok, ev.result);
|
|
6739
|
+
bcToolBoxEnd(ev.callId, ev.ok, ev.result, ev.diff);
|
|
6473
6740
|
if (codeWriteWatch.has(ev.callId)) {
|
|
6474
6741
|
const wp = codeWriteWatch.get(ev.callId);
|
|
6475
6742
|
codeWriteWatch.delete(ev.callId);
|
|
6476
6743
|
codeReloadIfOpen(wp);
|
|
6477
6744
|
}
|
|
6745
|
+
/* dosya/klasör üreten araçlardan sonra soldaki ağaç otomatik tazelensin */
|
|
6746
|
+
if (ev.name === 'write_file' || ev.name === 'edit_file' || ev.name === 'run_command' || ev.name === 'python_run') {
|
|
6747
|
+
ideRefreshTree();
|
|
6748
|
+
}
|
|
6478
6749
|
break;
|
|
6479
6750
|
case 'bc-preview':
|
|
6480
6751
|
/* iş bitince üretilen site/app dahili tarayıcıda CANLI açılır */
|
|
@@ -6493,8 +6764,10 @@ function bcIngest(ev) {
|
|
|
6493
6764
|
bcFlushStream();
|
|
6494
6765
|
bcCloseToolGroup();
|
|
6495
6766
|
bcSetBusy(false);
|
|
6767
|
+
bcStatusHide();
|
|
6496
6768
|
/* iptal/durdurma SEBEBİ panelde de görünür */
|
|
6497
6769
|
bcLine(ev.aborted ? 't-err' : 't-dim', ev.aborted ? '[durduruldu — sebep: ' + (ev.reason || 'sebep belirtilmedi') + ']' : '(tamamlandı)');
|
|
6770
|
+
ideRefreshTree(); /* son güvenlik tazelemesi — izlenmeyen yoldan üretilen dosyalar da düşsün */
|
|
6498
6771
|
bcRefreshPreview();
|
|
6499
6772
|
if (ideModeOn() && els.bcInput) els.bcInput.focus();
|
|
6500
6773
|
break;
|
|
@@ -6502,6 +6775,7 @@ function bcIngest(ev) {
|
|
|
6502
6775
|
bcFlushStream();
|
|
6503
6776
|
bcCloseToolGroup();
|
|
6504
6777
|
bcSetBusy(false);
|
|
6778
|
+
bcStatusHide();
|
|
6505
6779
|
bcLine('t-err', '[hata] ' + (ev.error || ''));
|
|
6506
6780
|
break;
|
|
6507
6781
|
case 'status':
|
|
@@ -6510,7 +6784,11 @@ function bcIngest(ev) {
|
|
|
6510
6784
|
if (ev.status === 'idle') {
|
|
6511
6785
|
bcCloseToolGroup();
|
|
6512
6786
|
bcSetBusy(false);
|
|
6787
|
+
bcStatusHide();
|
|
6513
6788
|
bcRefreshPreview();
|
|
6789
|
+
} else {
|
|
6790
|
+
/* düşünüyor… / araç adı / bağlam durumu — input üstünde canlı balon */
|
|
6791
|
+
bcStatusShow(ev.status === 'thinking' ? 'düşünüyor…' : String(ev.status || ''));
|
|
6514
6792
|
}
|
|
6515
6793
|
break;
|
|
6516
6794
|
}
|