beast-agent 1.6.0 → 1.7.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.
@@ -138,6 +138,8 @@ let renderQueued = false;
138
138
 
139
139
  /* #19 sağ panel tercih durumu (tarayıcı açılmadan önceki) — panel varsayılan KAPALI */
140
140
  let railPrefBeforeBrowser = false;
141
+ /* kullanıcı rail'i ELLE mi açtı? — otomatik kapatma yalnız bizim açtıklarımıza dokunur */
142
+ let railManualOpen = false;
141
143
 
142
144
  function toggleRail(hide) {
143
145
  document.body.classList.toggle('rail-hidden', !!hide);
@@ -691,6 +693,10 @@ function finishToolCard(callId, ok, result, diff) {
691
693
  st.classList.remove('run');
692
694
  st.classList.add(ok ? 'ok' : 'err');
693
695
  st.textContent = ok ? 'tamam' : 'hata';
696
+ /* outline: çalışan kart kalmadıysa HEMEN söner — grup kapanmasını beklemez
697
+ (sonraki tool-start yeniden yakar; terminal işi bitince mavi ring dönmez) */
698
+ const box = card.closest('.tool-box');
699
+ if (box && !box.querySelector('.tool-state.run')) box.classList.remove('running');
694
700
  const body = card.querySelector('.tool-body');
695
701
  if (diff && diff.path) {
696
702
  /* başlığa +/- rozetleri (opencode filediff additions/deletions) */
@@ -778,6 +784,7 @@ async function renderSessions(list) {
778
784
  if ((s.botId || 'beast') !== activeBotId) continue;
779
785
  const row = document.createElement('div');
780
786
  row.className = 'sess' + (s.id === activeId ? ' active' : '');
787
+ row.dataset.sid = s.id; /* en üstteki sohbeti otomatik aktif etmek için */
781
788
  row.title = _t('sess_drag');
782
789
  row.draggable = true;
783
790
  row.innerHTML =
@@ -3949,16 +3956,25 @@ async function refreshAgentsPane() {
3949
3956
  renderAgentRail();
3950
3957
  }
3951
3958
 
3952
- /* ajanlar çalışmaya başladığında sağdaki Paralel Ajan konsolu otomatik açılır
3953
- (yalnız boştan-çalışıyor geçişinde; kullanıcı çalışırken elle kapatırsa ezilmez,
3954
- dahili tarayıcı açıkken de karışılmaz) */
3959
+ /* Paralel Ajan konsolu: DEFAULT KAPALI.
3960
+ - Ajanlar çalışmaya başladığında otomatik AÇILIR (boştan-çalışıyor geçişinde;
3961
+ kullanıcı çalışırken elle kapatırsa ezilmez; dahili tarayıcı ve IDE modu
3962
+ açıkken karışılmaz — orada railBtn ile elle açılır)
3963
+ - Tüm işler bitince otomatik KAPANIR (yalnız açılışı biz yaptıysak;
3964
+ kullanıcı elle açtıysa açık kalır) */
3955
3965
  function maybeAutoOpenRail() {
3956
3966
  const hasRunning = agentState.jobs.some((j) => j.status === 'running');
3957
- if (hasRunning && !agentState.autoOpened && document.body.classList.contains('rail-hidden') &&
3958
- !document.body.classList.contains('browser-open')) {
3967
+ const hidden = document.body.classList.contains('rail-hidden');
3968
+ if (hasRunning && !agentState.autoOpened && hidden &&
3969
+ !document.body.classList.contains('browser-open') && !ideModeOn()) {
3959
3970
  toggleRail(false);
3960
3971
  railPrefBeforeBrowser = true;
3961
3972
  }
3973
+ if (!hasRunning && agentState.autoOpened && !hidden &&
3974
+ !railManualOpen && !document.body.classList.contains('browser-open')) {
3975
+ toggleRail(true);
3976
+ railManualOpen = false;
3977
+ }
3962
3978
  agentState.autoOpened = hasRunning;
3963
3979
  }
3964
3980
 
@@ -4328,6 +4344,12 @@ function onEvent(ev) {
4328
4344
  case 'todos':
4329
4345
  renderTodos(ev.todos);
4330
4346
  break;
4347
+ case 'win-max': {
4348
+ /* custom pencere butonu: büyüt/küçült ikonunu pencere durumuyla senkron tut */
4349
+ const wm = $('#winMax');
4350
+ if (wm) wm.innerHTML = ev.maximized ? '❐︎' : '□︎';
4351
+ break;
4352
+ }
4331
4353
  case 'cron':
4332
4354
  if (setTab === 'cron') renderCronList(ev.jobs || []);
4333
4355
  if (els.cronOverlay && !els.cronOverlay.hidden) renderCronModal();
@@ -5057,11 +5079,15 @@ async function init() {
5057
5079
  } catch {}
5058
5080
  applyState();
5059
5081
 
5060
- /* açılışta: oturum varsa SON oturumu otomatik yükle/göster; yoksa yeni oturum AÇMA (kullanıcı "Yeni Sohbet"e bassın) */
5082
+ /* açılışta: oturum varsa SIDEBAR'IN EN ÜSTTEKİ sohbeti direkt aktif açılır
5083
+ (elle sürükleme sırası + aktif bot filtresi gözetilir); yoksa yeni oturum
5084
+ AÇMA (kullanıcı "Yeni Sohbet"e bassın) */
5061
5085
  const sessions = await beast.listSessions();
5062
5086
  if (sessions.length) {
5063
- const last = sessions.slice().sort((a, b) => (new Date(b.updatedAt || 0) - new Date(a.updatedAt || 0)))[0] || sessions[0];
5064
- await openSession(last.id);
5087
+ await refreshSessions();
5088
+ const firstRow = els.sessList.querySelector('.sess');
5089
+ if (firstRow && firstRow.dataset.sid) await openSession(firstRow.dataset.sid);
5090
+ else showEmpty(true);
5065
5091
  } else {
5066
5092
  showEmpty(true);
5067
5093
  }
@@ -5072,6 +5098,15 @@ async function init() {
5072
5098
  els.input.focus();
5073
5099
  });
5074
5100
 
5101
+ /* custom pencere butonları: küçült / büyüt / kapat — main'e window:ctrl ile gider.
5102
+ Büyüt ikonu maximize/unmaximize olayıyla senkron (□ / ❐). */
5103
+ const winMin = $('#winMin');
5104
+ const winMax = $('#winMax');
5105
+ const winClose = $('#winClose');
5106
+ if (winMin) winMin.addEventListener('click', () => beast.winCtrl('minimize'));
5107
+ if (winMax) winMax.addEventListener('click', () => beast.winCtrl('maximize'));
5108
+ if (winClose) winClose.addEventListener('click', () => beast.winCtrl('close'));
5109
+
5075
5110
  /* sağ panel — ayar/tema solda; burada yalnızca görev listesi */
5076
5111
 
5077
5112
  const syncThemeBtns = (dark) => {
@@ -5292,6 +5327,7 @@ async function init() {
5292
5327
  }
5293
5328
  toggleRail(!document.body.classList.contains('rail-hidden'));
5294
5329
  railPrefBeforeBrowser = !document.body.classList.contains('rail-hidden');
5330
+ railManualOpen = willOpen; /* elle açıldı → otomatik kapatma dokunmaz */
5295
5331
  });
5296
5332
  if (els.railClear) {
5297
5333
  els.railClear.addEventListener('click', async () => {
@@ -5460,8 +5496,20 @@ async function init() {
5460
5496
  if ($('#botClose')) $('#botClose').addEventListener('click', () => botOverlaySetOpen(false));
5461
5497
  if ($('#botOverviewBack')) $('#botOverviewBack').addEventListener('click', () => openBotPage(null));
5462
5498
  if ($('#botChip')) $('#botChip').addEventListener('click', () => openBotPage(activeBotId));
5463
- /* kalıcı aktif bot: restart sonrası aynı botun UI'ı açılır */
5464
- beast.botsActiveGet().then((r) => { activeBotId = (r && r.id) || 'beast'; updateBotChip(); renderBotCards(); applyState(); }).catch(() => {});
5499
+ /* kalıcı aktif bot: restart sonrası aynı botun UI'ı açılır. Bot bilgisi
5500
+ asenkron geldiğinde oturum listesi de o bota göre yeniden filtrelenir ve
5501
+ YİNE en üstteki sohbet aktif açılır (ilk açılış kuralı tutarlı kalır). */
5502
+ beast.botsActiveGet().then((r) => {
5503
+ activeBotId = (r && r.id) || 'beast';
5504
+ updateBotChip();
5505
+ renderBotCards();
5506
+ applyState();
5507
+ refreshSessions().catch(() => {});
5508
+ const firstRow = els.sessList.querySelector('.sess');
5509
+ if (firstRow && firstRow.dataset.sid && firstRow.dataset.sid !== activeId) {
5510
+ openSession(firstRow.dataset.sid).catch(() => {});
5511
+ }
5512
+ }).catch(() => {});
5465
5513
  document.querySelectorAll('.btab').forEach((b) =>
5466
5514
  b.addEventListener('click', () => {
5467
5515
  document.querySelectorAll('.btab').forEach((x) => x.classList.remove('active'));
@@ -6137,8 +6185,10 @@ async function setIdeMode(on) {
6137
6185
  /* soldaki marka: chat modunda BEAST Agent, IDE modunda BEAST Code */
6138
6186
  const brandSub = document.querySelector('#brand .brand-sub');
6139
6187
  if (brandSub) brandSub.textContent = on ? 'Code' : 'Agent';
6140
- /* IDE modu oturumluk: uygulama HER AÇILIŞTA agent (chat) modunda başlar */
6141
- toggleRail(!!on);
6188
+ /* rail her iki modda da DEFAULT KAPALI çalışan paralel ajan varsa
6189
+ aşağıda (agent moduna dönüşte) maybeAutoOpenRail otomatik açar */
6190
+ toggleRail(true);
6191
+ railManualOpen = false;
6142
6192
  /* IDE'den çıkış: açık tarayıcı da kapansın — her şey default haline dönsün */
6143
6193
  if (!on && document.body.classList.contains('browser-open')) {
6144
6194
  try { beast.toggleBrowser(); } catch {}
@@ -6149,6 +6199,11 @@ async function setIdeMode(on) {
6149
6199
  await loadIdeTree();
6150
6200
  bcBanner();
6151
6201
  codeGutterRender(); /* dosya açık olmasa bile rakamlar görünür */
6202
+ } else {
6203
+ /* agent moduna dönüş: koşan paralel ajan varsa rail otomatik açılır
6204
+ (autoOpened sıfırlanır — Code modundayken başlayan iş için de tetiklensin) */
6205
+ agentState.autoOpened = false;
6206
+ try { await refreshAgentsPane(); } catch {}
6152
6207
  }
6153
6208
  }
6154
6209
 
@@ -7127,9 +7182,13 @@ function bcToolBoxEnd(callId, ok, result, diff) {
7127
7182
  const out = String(result || '').replace(/\s+$/, '');
7128
7183
  if (t) {
7129
7184
  const { sec } = t;
7130
- /* ring burada SÖNDÜRÜLMEZ — iş bitene kadar (bcCloseToolGroup) döner */
7131
7185
  sec.classList.add('done');
7132
7186
  if (!ok) sec.classList.add('failed');
7187
+ /* ring: bu araç BİTİNCE sönür — grup kapanmasını beklemez.
7188
+ (Yeni araç başlarsa bcToolBoxStart yeniden yakar; grup aynı kutuda kalır.) */
7189
+ if (!t.box.querySelector('.bc-toolsection:not(.done)')) {
7190
+ t.box.classList.remove('running');
7191
+ }
7133
7192
  const pre = sec.querySelector('.bc-toolout');
7134
7193
  if (diff && diff.path) {
7135
7194
  /* opencode diff görünümü: başlığa +/- rozeti, gövdeye kırmızı/yeşil diff */
@@ -502,6 +502,41 @@ body.term-open #settingsOverlay { right: var(--tw, 520px); }
502
502
  }
503
503
  .drag-spacer { flex: 1; height: 100%; -webkit-app-region: drag; }
504
504
 
505
+ /* ---------- custom pencere butonları (native overlay yerine) ----------
506
+ Arka plan YOK — topbar'ın kendi zemininde yüzüyor; hover'da uygulamanın
507
+ kendi accent-dim tonu, kapat Windows alışkanlığıyla kırmızı. */
508
+ .win-controls {
509
+ display: flex;
510
+ align-items: center;
511
+ height: 100%;
512
+ margin-left: -4px;
513
+ -webkit-app-region: no-drag;
514
+ }
515
+ .win-controls button {
516
+ width: 42px;
517
+ height: 34px;
518
+ display: flex;
519
+ align-items: center;
520
+ justify-content: center;
521
+ background: transparent;
522
+ border: none;
523
+ border-radius: 7px;
524
+ color: var(--muted);
525
+ font-size: 13px;
526
+ line-height: 1;
527
+ padding: 0;
528
+ cursor: pointer;
529
+ }
530
+ .win-controls button:hover {
531
+ background: var(--accent-dim);
532
+ color: var(--text);
533
+ }
534
+ .win-controls button:active { opacity: 0.7; }
535
+ .win-controls button.win-close:hover {
536
+ background: #c42b1c;
537
+ color: #ffffff;
538
+ }
539
+
505
540
  /* dropdown model picker */
506
541
  .dd { position: relative; -webkit-app-region: no-drag; }
507
542
  .dd-btn {
@@ -1802,8 +1837,9 @@ body.browser-open #settingsDialog { width: min(70vw, calc(100vw - var(--bw, 480p
1802
1837
  border-left: 1px solid var(--border);
1803
1838
  display: flex;
1804
1839
  flex-direction: column;
1805
- /* pencere kontrolleri (– ×) 46px'lik alana oturur; altından başla */
1806
- padding-top: 46px;
1840
+ /* eskiden üstte 46px boşluk vardı: native titleBarOverlay butonları bu
1841
+ alana oturuyordu. Butonlar artık topbar'ın içinde custom çizildiği için
1842
+ rail tam yükseklikte başlar — mod geçişlerinde kaybolma yok. */
1807
1843
  }
1808
1844
 
1809
1845
  #railHead {