beast-agent 1.1.1 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 +276 -12
- package/src/renderer/style.css +381 -256
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)');
|
|
@@ -3647,12 +3845,18 @@ function renderAgentRail() {
|
|
|
3647
3845
|
const when = j.startedAt
|
|
3648
3846
|
? new Date(j.startedAt).toLocaleTimeString('tr-TR', { hour: '2-digit', minute: '2-digit' })
|
|
3649
3847
|
: '';
|
|
3848
|
+
/* iptal sebebi LİSTEDE yazmaz (yatay scroll çıkarır) — tooltip + açınca
|
|
3849
|
+
detaydaki .ag-err satırında görünür */
|
|
3850
|
+
const abortTip =
|
|
3851
|
+
j.status === 'aborted' && j.error
|
|
3852
|
+
? ` title="İptal sebebi: ${escapeHtml(String(j.error).slice(0, 200))}"`
|
|
3853
|
+
: '';
|
|
3650
3854
|
row.innerHTML =
|
|
3651
3855
|
`<div class="rj-head">` +
|
|
3652
3856
|
`<span class="ag-dot"></span>` +
|
|
3653
3857
|
`<span class="sess-title">${escapeHtml(j.title)}</span>` +
|
|
3654
3858
|
(j.code ? `<span class="sess-code" title="Oturum kodu">${escapeHtml(j.code)}</span>` : ``) +
|
|
3655
|
-
`<span class="rj-time">${j.status === 'running' ? when + ' · ' + agentTimerHtml(j.startedAt) + ' · ' + _t('ag_working') : (agStText(j.status) === _t('ag_st_done') ? '\u2713' : (agStText(j.status) || j.status)
|
|
3859
|
+
`<span class="rj-time"${abortTip}>${j.status === 'running' ? when + ' · ' + agentTimerHtml(j.startedAt) + ' · ' + _t('ag_working') : (agStText(j.status) === _t('ag_st_done') ? '\u2713' : (agStText(j.status) || j.status))}</span>` +
|
|
3656
3860
|
(j.status === 'running'
|
|
3657
3861
|
? `<button class="rj-cancel" title="${_t('ag_cancel')}">×</button>`
|
|
3658
3862
|
: `<button class="rj-cancel" title="${_t('ag_delete')}"><svg viewBox="0 0 24 24" width="12" height="12" fill="none" stroke="currentColor" stroke-width="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 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/><path d="M10 11v6M14 11v6"/></svg></button>`) +
|
|
@@ -3906,11 +4110,11 @@ function onEvent(ev) {
|
|
|
3906
4110
|
addToolCard(ev.callId, ev.name, ev.args);
|
|
3907
4111
|
setStatus(ev.name + '…');
|
|
3908
4112
|
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);
|
|
4113
|
+
/* ajan dosya yazarsa/editlerse açık IDE sekmesini izlemeye al */
|
|
4114
|
+
if ((ev.name === 'write_file' || ev.name === 'edit_file') && ev.args && ev.args.path) codeWriteWatch.set(ev.callId, ev.args.path);
|
|
3911
4115
|
break;
|
|
3912
4116
|
case 'tool-end':
|
|
3913
|
-
finishToolCard(ev.callId, ev.ok, ev.result);
|
|
4117
|
+
finishToolCard(ev.callId, ev.ok, ev.result, ev.diff);
|
|
3914
4118
|
setStatus('düşünüyor…');
|
|
3915
4119
|
termAgentEvent(ev);
|
|
3916
4120
|
if (codeWriteWatch.has(ev.callId)) {
|
|
@@ -4843,9 +5047,29 @@ async function init() {
|
|
|
4843
5047
|
});
|
|
4844
5048
|
}
|
|
4845
5049
|
if (els.railBtn) els.railBtn.addEventListener('click', () => {
|
|
5050
|
+
const willOpen = document.body.classList.contains('rail-hidden');
|
|
5051
|
+
/* IDE modunda rail istenirse açık tarayıcı yerini bırakır — ikisi aynı
|
|
5052
|
+
sağ dock'u paylaşır; tarayıcı kapanma olayı rail'i tekrar KAPATMASIN
|
|
5053
|
+
diye railPrefBeforeBrowser=true ile bırakılır */
|
|
5054
|
+
if (willOpen && ideModeOn() && document.body.classList.contains('browser-open')) {
|
|
5055
|
+
railPrefBeforeBrowser = true;
|
|
5056
|
+
els.bbClose.click();
|
|
5057
|
+
}
|
|
4846
5058
|
toggleRail(!document.body.classList.contains('rail-hidden'));
|
|
4847
5059
|
railPrefBeforeBrowser = !document.body.classList.contains('rail-hidden');
|
|
4848
5060
|
});
|
|
5061
|
+
if (els.railClear) {
|
|
5062
|
+
els.railClear.addEventListener('click', async () => {
|
|
5063
|
+
if (!confirm('TÜM paralel ajan geçmişi silinsin mi?\n(Çalışan ajanlar da iptal edilir — geri alınamaz)')) return;
|
|
5064
|
+
try {
|
|
5065
|
+
const r = await beast.agentsClearAll();
|
|
5066
|
+
if (r && r.ok) toast('Paralel ajan geçmişi silindi' + (r.removed ? ' — ' + r.removed + ' iş' : ''));
|
|
5067
|
+
else toast('Silinemedi: ' + ((r && r.error) || '?'));
|
|
5068
|
+
} catch (e) {
|
|
5069
|
+
toast('Silinemedi: ' + String((e && e.message) || e));
|
|
5070
|
+
}
|
|
5071
|
+
});
|
|
5072
|
+
}
|
|
4849
5073
|
els.bbBack.addEventListener('click', () => beast.browserCtrl('back'));
|
|
4850
5074
|
els.bbFwd.addEventListener('click', () => beast.browserCtrl('forward'));
|
|
4851
5075
|
els.bbReload.addEventListener('click', () => beast.browserCtrl('reload'));
|
|
@@ -6285,6 +6509,20 @@ function bcStreamDelta(delta) {
|
|
|
6285
6509
|
/* İş bitti → preview açık ve IDE modundaysa workspace sayfasını otomatik yenile */
|
|
6286
6510
|
let bcPrevAt = 0;
|
|
6287
6511
|
|
|
6512
|
+
/* Beast Code durum balonu: düşünüyor… / araç adları / durum satırları —
|
|
6513
|
+
chat inputun üstündeki balonun BC panelindeki karşılığı */
|
|
6514
|
+
function bcStatusShow(text) {
|
|
6515
|
+
if (!els.bcStatus) return;
|
|
6516
|
+
const t = String(text || '').trim();
|
|
6517
|
+
if (!t) return;
|
|
6518
|
+
els.bcStatus.textContent = t;
|
|
6519
|
+
els.bcStatus.hidden = false;
|
|
6520
|
+
}
|
|
6521
|
+
|
|
6522
|
+
function bcStatusHide() {
|
|
6523
|
+
if (els.bcStatus) els.bcStatus.hidden = true;
|
|
6524
|
+
}
|
|
6525
|
+
|
|
6288
6526
|
function bcRefreshPreview() {
|
|
6289
6527
|
const now = Date.now();
|
|
6290
6528
|
if (now - bcPrevAt < 1500) return; /* done + idle çift tetiklemesin */
|
|
@@ -6369,7 +6607,7 @@ function bcToolBoxStart(callId, name, args) {
|
|
|
6369
6607
|
bcBodyScroll(body);
|
|
6370
6608
|
}
|
|
6371
6609
|
|
|
6372
|
-
function bcToolBoxEnd(callId, ok, result) {
|
|
6610
|
+
function bcToolBoxEnd(callId, ok, result, diff) {
|
|
6373
6611
|
bcFlushStream();
|
|
6374
6612
|
const t = (callId && bcTools.get(callId)) || null;
|
|
6375
6613
|
if (callId) bcTools.delete(callId);
|
|
@@ -6380,7 +6618,27 @@ function bcToolBoxEnd(callId, ok, result) {
|
|
|
6380
6618
|
sec.classList.add('done');
|
|
6381
6619
|
if (!ok) sec.classList.add('failed');
|
|
6382
6620
|
const pre = sec.querySelector('.bc-toolout');
|
|
6383
|
-
if (
|
|
6621
|
+
if (diff && diff.path) {
|
|
6622
|
+
/* opencode diff görünümü: başlığa +/- rozeti, gövdeye kırmızı/yeşil diff */
|
|
6623
|
+
const headEl = sec.querySelector('.bc-toolhead');
|
|
6624
|
+
if (headEl && !headEl.querySelector('.diff-badge')) {
|
|
6625
|
+
const badge = document.createElement('span');
|
|
6626
|
+
badge.className = 'diff-badge';
|
|
6627
|
+
const a = document.createElement('span');
|
|
6628
|
+
a.className = 'diff-badge-add';
|
|
6629
|
+
a.textContent = '+' + (diff.additions || 0);
|
|
6630
|
+
const d = document.createElement('span');
|
|
6631
|
+
d.className = 'diff-badge-del';
|
|
6632
|
+
d.textContent = '−' + (diff.deletions || 0);
|
|
6633
|
+
badge.appendChild(a);
|
|
6634
|
+
badge.appendChild(d);
|
|
6635
|
+
headEl.appendChild(badge);
|
|
6636
|
+
}
|
|
6637
|
+
pre.hidden = false;
|
|
6638
|
+
pre.textContent = '';
|
|
6639
|
+
pre.classList.add('bc-diffview');
|
|
6640
|
+
pre.appendChild(buildDiffEl(diff, pre.clientWidth || 480));
|
|
6641
|
+
} else if (out) {
|
|
6384
6642
|
pre.hidden = false;
|
|
6385
6643
|
pre.textContent = out.length > 4000 ? out.slice(0, 4000) + '\n… (kesildi)' : out;
|
|
6386
6644
|
} else {
|
|
@@ -6484,7 +6742,7 @@ function bcIngest(ev) {
|
|
|
6484
6742
|
if ((ev.name === 'write_file' || ev.name === 'edit_file') && ev.args && ev.args.path) codeWriteWatch.set(ev.callId, ev.args.path);
|
|
6485
6743
|
break;
|
|
6486
6744
|
case 'tool-end':
|
|
6487
|
-
bcToolBoxEnd(ev.callId, ev.ok, ev.result);
|
|
6745
|
+
bcToolBoxEnd(ev.callId, ev.ok, ev.result, ev.diff);
|
|
6488
6746
|
if (codeWriteWatch.has(ev.callId)) {
|
|
6489
6747
|
const wp = codeWriteWatch.get(ev.callId);
|
|
6490
6748
|
codeWriteWatch.delete(ev.callId);
|
|
@@ -6512,6 +6770,7 @@ function bcIngest(ev) {
|
|
|
6512
6770
|
bcFlushStream();
|
|
6513
6771
|
bcCloseToolGroup();
|
|
6514
6772
|
bcSetBusy(false);
|
|
6773
|
+
bcStatusHide();
|
|
6515
6774
|
/* iptal/durdurma SEBEBİ panelde de görünür */
|
|
6516
6775
|
bcLine(ev.aborted ? 't-err' : 't-dim', ev.aborted ? '[durduruldu — sebep: ' + (ev.reason || 'sebep belirtilmedi') + ']' : '(tamamlandı)');
|
|
6517
6776
|
ideRefreshTree(); /* son güvenlik tazelemesi — izlenmeyen yoldan üretilen dosyalar da düşsün */
|
|
@@ -6522,6 +6781,7 @@ function bcIngest(ev) {
|
|
|
6522
6781
|
bcFlushStream();
|
|
6523
6782
|
bcCloseToolGroup();
|
|
6524
6783
|
bcSetBusy(false);
|
|
6784
|
+
bcStatusHide();
|
|
6525
6785
|
bcLine('t-err', '[hata] ' + (ev.error || ''));
|
|
6526
6786
|
break;
|
|
6527
6787
|
case 'status':
|
|
@@ -6530,7 +6790,11 @@ function bcIngest(ev) {
|
|
|
6530
6790
|
if (ev.status === 'idle') {
|
|
6531
6791
|
bcCloseToolGroup();
|
|
6532
6792
|
bcSetBusy(false);
|
|
6793
|
+
bcStatusHide();
|
|
6533
6794
|
bcRefreshPreview();
|
|
6795
|
+
} else {
|
|
6796
|
+
/* düşünüyor… / araç adı / bağlam durumu — input üstünde canlı balon */
|
|
6797
|
+
bcStatusShow(ev.status === 'thinking' ? 'düşünüyor…' : String(ev.status || ''));
|
|
6534
6798
|
}
|
|
6535
6799
|
break;
|
|
6536
6800
|
}
|