beast-agent 2.44.14 → 2.46.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/src/preload.js CHANGED
@@ -55,6 +55,11 @@ contextBridge.exposeInMainWorld('beast', {
55
55
  mcpConfigGet: () => ipcRenderer.invoke('mcp:config:get'),
56
56
  mcpConfigSet: (raw) => ipcRenderer.invoke('mcp:config:set', raw),
57
57
  mcpRefresh: (name) => ipcRenderer.invoke('mcp:refresh', name),
58
+ mcpChatOpen: (payload) => ipcRenderer.invoke('mcp:chat:open', payload),
59
+ mcpChatSend: (payload) => ipcRenderer.invoke('mcp:chat:send', payload),
60
+ mcpChatStop: () => ipcRenderer.invoke('mcp:chat:stop'),
61
+ mcpChatNew: () => ipcRenderer.invoke('mcp:chat:new'),
62
+ mcpChatHistory: () => ipcRenderer.invoke('mcp:chat:history'),
58
63
  getLimits: () => ipcRenderer.invoke('limits:get'),
59
64
  setLimits: (cfg) => ipcRenderer.invoke('limits:set', cfg),
60
65
  secGet: () => ipcRenderer.invoke('sec:get'),
@@ -483,6 +483,24 @@
483
483
  <textarea id="mcpJson" spellcheck="false"></textarea>
484
484
  </div>
485
485
  </section>
486
+
487
+ <div id="mcpSplit" title="Sürükleyerek boyutlandır"></div>
488
+
489
+ <section id="mcpChat">
490
+ <div id="mcpChatHead">
491
+ <span id="mcpChatTitle">MCP SOHBET</span>
492
+ <select id="mcpChatHist" title="MCP sohbet geçmişi — ana sohbetten ayrıdır"></select>
493
+ <span class="file-spacer"></span>
494
+ <button id="mcpChatNew" title="Yeni sohbet (mevcut sohbet geçmişte kalır)">*</button>
495
+ </div>
496
+ <div id="mcpChatOut"></div>
497
+ <div id="mcpChatStatus" hidden></div>
498
+ <div id="mcpChatInputRow">
499
+ <textarea id="mcpChatInput" rows="1" spellcheck="false" autocomplete="off" placeholder="MCP sohbeti — sunucu araçları ajanın emrinde…"></textarea>
500
+ <button id="mcpChatSend" title="Gönder (Enter)"><svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg></button>
501
+ <button id="mcpChatStop" title="Çalışan mesajı durdur" hidden data-i18n-title="bc_stop"><svg viewBox="0 0 24 24" width="13" height="13" fill="currentColor" stroke="none"><rect x="6" y="6" width="12" height="12" rx="2"/></svg></button>
502
+ </div>
503
+ </section>
486
504
  </div>
487
505
  </main>
488
506
 
@@ -162,6 +162,15 @@ const els = {
162
162
  mcpJsonPath: $('#mcpJsonPath'),
163
163
  mcpSave: $('#mcpSave'),
164
164
  mcpMsg: $('#mcpMsg'),
165
+ mcpSplit: $('#mcpSplit'),
166
+ mcpChat: $('#mcpChat'),
167
+ mcpChatOut: $('#mcpChatOut'),
168
+ mcpChatStatus: $('#mcpChatStatus'),
169
+ mcpChatHist: $('#mcpChatHist'),
170
+ mcpChatNew: $('#mcpChatNew'),
171
+ mcpChatInput: $('#mcpChatInput'),
172
+ mcpChatSend: $('#mcpChatSend'),
173
+ mcpChatStop: $('#mcpChatStop'),
165
174
  stPanel: $('#stPanel'),
166
175
  stTitle: $('#stTitle'),
167
176
  stCwd: $('#stCwd'),
@@ -5951,6 +5960,12 @@ function onEvent(ev) {
5951
5960
  bcLine('t-dim', '⏳ onay bekleniyor: ' + (ev.tool || '?') + ' — IDE modundan çıkıp sohbetteki kartı onayla');
5952
5961
  return;
5953
5962
  }
5963
+ /* Beast MCP sohbet oturumunun onayı: panelde ipucu + kart sohbete düşer */
5964
+ if (mcpChatSid && ev.sessionId === mcpChatSid) {
5965
+ showApprovalCard(ev);
5966
+ mcpLine('t-dim', '⏳ onay bekleniyor: ' + (ev.tool || '?') + ' — ana sohbetteki kartı onayla');
5967
+ return;
5968
+ }
5954
5969
  if (ev.sessionId && ev.sessionId !== activeId) return;
5955
5970
  showApprovalCard(ev);
5956
5971
  return;
@@ -5961,6 +5976,12 @@ function onEvent(ev) {
5961
5976
  if (ev.type === 'permission.asked') {
5962
5977
  const req = ev.request || {};
5963
5978
  const isBc = bcSessionId && ev.sessionId === bcSessionId;
5979
+ /* Beast MCP sohbet oturumunun izni: kart sohbete düşer, panelde ipucu */
5980
+ if (mcpChatSid && ev.sessionId === mcpChatSid) {
5981
+ showPermissionCard(req, false);
5982
+ mcpLine('t-dim', '⏳ izin bekleniyor: ' + (req.permission || '?') + ' — ana sohbetteki kartı yanıtla');
5983
+ return;
5984
+ }
5964
5985
  if (!isBc && ev.sessionId && ev.sessionId !== activeId) return;
5965
5986
  showPermissionCard(req, isBc);
5966
5987
  return;
@@ -6064,6 +6085,12 @@ function onEvent(ev) {
6064
6085
  sbRunIngest(ev);
6065
6086
  return;
6066
6087
  }
6088
+ /* Beast MCP sohbeti: olaylar SADECE MCP modundaki sağ sohbete akar — ana
6089
+ sohbeti ve Code/Studio/Sandbox panellerini kirletmez (dünyalar ayrı) */
6090
+ if (mcpChatSid && ev.sessionId === mcpChatSid) {
6091
+ mcpIngest(ev);
6092
+ return;
6093
+ }
6067
6094
  /* Beast Sandbox oturumu: olaylar SADECE Sandbox paneline akar — ana sohbeti
6068
6095
  ve Code/Studio panellerini kirletmez (dünyalar ayrı) */
6069
6096
  if (sbSessionId && ev.sessionId === sbSessionId) {
@@ -12514,6 +12541,8 @@ async function setMcpMode(on) {
12514
12541
  if (brandSub) brandSub.textContent = on ? 'MCP' : 'Agent';
12515
12542
  if (on) {
12516
12543
  await renderMcpPanel();
12544
+ mcpSplitRestore(); /* sohbet/detay oranı */
12545
+ mcpChatEnsure(); /* ayrı MCP sohbet oturumu (yoksa aç/geçmişten sürdür) */
12517
12546
  if (!mcpTimer) {
12518
12547
  mcpTimer = setInterval(() => { if (mcpModeOn()) renderMcpPanel(); }, 5000);
12519
12548
  }
@@ -12645,6 +12674,284 @@ if (els.mcpAddBtn) els.mcpAddBtn.addEventListener('click', () => {
12645
12674
  } catch {}
12646
12675
  });
12647
12676
 
12677
+ /* ---------- MCP SOHBETİ (sağ panel): ana sohbetten AYRI oturum ----------
12678
+ Oturum main'de bgTitle 'Beast MCP' ile yaşar; olaylar sessionId eşleşmesiyle
12679
+ yalnız bu panele akar (onEvent yönlendirmesi). Geçmiş seçici eski MCP
12680
+ sohbetlerini açar; '*' taze sohbet başlatır (eskisi geçmişte kalır). */
12681
+ let mcpChatSid = '';
12682
+ let mcpChatBusy = false;
12683
+ let mcpChatOpening = false;
12684
+ let mcpChatItems = [];
12685
+ let mcpStreamEl = null;
12686
+ let mcpStreamRaw = '';
12687
+
12688
+ function mcpLine(cls, text) {
12689
+ if (!els.mcpChatOut) return null;
12690
+ const div = document.createElement('div');
12691
+ div.className = cls || 't-out';
12692
+ div.textContent = String(text || '');
12693
+ els.mcpChatOut.appendChild(div);
12694
+ els.mcpChatOut.scrollTop = els.mcpChatOut.scrollHeight;
12695
+ return div;
12696
+ }
12697
+
12698
+ function mcpStreamDelta(delta) {
12699
+ if (!els.mcpChatOut) return;
12700
+ if (!mcpStreamEl) mcpStreamEl = mcpLine('t-out', '');
12701
+ mcpStreamRaw += String(delta || '');
12702
+ mcpStreamEl.textContent = mcpStreamRaw;
12703
+ els.mcpChatOut.scrollTop = els.mcpChatOut.scrollHeight;
12704
+ }
12705
+
12706
+ function mcpFlushStream() {
12707
+ mcpStreamEl = null;
12708
+ mcpStreamRaw = '';
12709
+ }
12710
+
12711
+ function mcpSetBusy(b) {
12712
+ mcpChatBusy = !!b;
12713
+ if (els.mcpChatStop) els.mcpChatStop.hidden = !mcpChatBusy;
12714
+ }
12715
+
12716
+ function mcpStatusShow(text) {
12717
+ if (els.mcpChatStatus) {
12718
+ els.mcpChatStatus.hidden = false;
12719
+ els.mcpChatStatus.textContent = text;
12720
+ }
12721
+ }
12722
+
12723
+ function mcpStatusHide() {
12724
+ if (els.mcpChatStatus) els.mcpChatStatus.hidden = true;
12725
+ }
12726
+
12727
+ /* MCP oturumunun engine olayları → panel (sbIngest'in MCP karşılığı) */
12728
+ function mcpIngest(ev) {
12729
+ if (!mcpChatSid || ev.sessionId !== mcpChatSid) return;
12730
+ switch (ev.type) {
12731
+ case 'token':
12732
+ mcpStreamDelta(ev.delta);
12733
+ break;
12734
+ case 'message': {
12735
+ const m = ev.message;
12736
+ if (!m) break;
12737
+ /* kullanıcı echo basılmaz — gönderirken 'sen>' satırı düştü */
12738
+ if (m.role === 'assistant') {
12739
+ mcpFlushStream();
12740
+ const hasTools = Array.isArray(m.tool_calls) && m.tool_calls.length > 0;
12741
+ const txt = typeof m.content === 'string' ? m.content.trim() : '';
12742
+ if (txt && !hasTools) mcpLine('t-out', txt);
12743
+ }
12744
+ break;
12745
+ }
12746
+ case 'tool-start':
12747
+ mcpSetBusy(true);
12748
+ mcpLine('t-dim', '\u2692 ' + (ev.name || '?') + (sbArgsSummary(ev.args) ? ' \u00B7 ' + sbArgsSummary(ev.args) : ''));
12749
+ break;
12750
+ case 'tool-end': {
12751
+ const ok = ev.ok !== false;
12752
+ mcpLine(ok ? 't-dim' : 't-err', (ok ? ' \u2713 ' : ' \u2717 ') + String(ev.result || '').replace(/\s+/g, ' ').slice(0, 160));
12753
+ break;
12754
+ }
12755
+ case 'status':
12756
+ if (ev.status === 'idle') {
12757
+ mcpSetBusy(false);
12758
+ mcpStatusHide();
12759
+ } else {
12760
+ mcpSetBusy(true);
12761
+ mcpStatusShow(ev.status === 'thinking' ? 'düşünüyor…' : String(ev.status || ''));
12762
+ }
12763
+ break;
12764
+ case 'done':
12765
+ mcpFlushStream();
12766
+ mcpSetBusy(false);
12767
+ mcpStatusHide();
12768
+ mcpLine('t-dim', ev.aborted ? '[durduruldu' + (ev.reason ? ' — ' + ev.reason : '') + ']' : '(tamamlandı)');
12769
+ mcpHistRefresh();
12770
+ break;
12771
+ case 'error':
12772
+ mcpFlushStream();
12773
+ mcpSetBusy(false);
12774
+ mcpStatusHide();
12775
+ mcpLine('t-err', '[hata] ' + (ev.error || ''));
12776
+ break;
12777
+ }
12778
+ }
12779
+
12780
+ function mcpHistFill(items) {
12781
+ if (!els.mcpChatHist) return;
12782
+ mcpChatItems = Array.isArray(items) ? items : [];
12783
+ const sel = mcpChatSid || '';
12784
+ els.mcpChatHist.innerHTML = '';
12785
+ if (!mcpChatItems.length) {
12786
+ const o = document.createElement('option');
12787
+ o.value = '';
12788
+ o.textContent = 'Geçmiş yok';
12789
+ els.mcpChatHist.appendChild(o);
12790
+ els.mcpChatHist.value = '';
12791
+ return;
12792
+ }
12793
+ for (const it of mcpChatItems) {
12794
+ const o = document.createElement('option');
12795
+ o.value = it.id;
12796
+ o.textContent = (it.title || 'MCP sohbeti').slice(0, 64) + (it.count ? ' · ' + it.count : '');
12797
+ els.mcpChatHist.appendChild(o);
12798
+ }
12799
+ if (sel && mcpChatItems.some((x) => x.id === sel)) els.mcpChatHist.value = sel;
12800
+ }
12801
+
12802
+ async function mcpHistRefresh() {
12803
+ const r = await beast.mcpChatHistory().catch(() => null);
12804
+ if (r && r.ok) mcpHistFill(r.items || []);
12805
+ }
12806
+
12807
+ async function mcpChatOpen(id) {
12808
+ if (mcpChatBusy || mcpChatOpening) return;
12809
+ mcpChatOpening = true;
12810
+ const r = await beast.mcpChatOpen(id ? { id } : undefined).catch(() => null);
12811
+ mcpChatOpening = false;
12812
+ if (!r || !r.ok) {
12813
+ mcpLine('t-err', (r && r.error) || 'MCP sohbet oturumu açılamadı');
12814
+ return;
12815
+ }
12816
+ mcpChatSid = r.sessionId || '';
12817
+ if (els.mcpChatOut) els.mcpChatOut.innerHTML = '';
12818
+ mcpFlushStream();
12819
+ for (const m of r.messages || []) {
12820
+ mcpLine(m.role === 'assistant' ? 't-out' : 't-cmd', (m.role === 'assistant' ? '' : 'sen> ') + m.text);
12821
+ }
12822
+ if (!(r.messages || []).length) {
12823
+ mcpLine('t-dim', 'MCP sohbeti hazır — MCP sunucu araçlarını kullanabilen ajanla konuş.');
12824
+ }
12825
+ mcpHistFill(r.items || []);
12826
+ mcpSetBusy(!!r.busy);
12827
+ mcpStatusHide();
12828
+ }
12829
+
12830
+ /* moda girişte: mevcut oturum yoksa aç (çalışan sohbeti ASLA yeniden yükleme) */
12831
+ async function mcpChatEnsure() {
12832
+ if (!mcpChatSid && !mcpChatBusy) await mcpChatOpen();
12833
+ }
12834
+
12835
+ function mcpInputResize() {
12836
+ const ta = els.mcpChatInput;
12837
+ if (!ta) return;
12838
+ ta.style.height = 'auto';
12839
+ ta.style.height = Math.min(ta.scrollHeight, 140) + 'px';
12840
+ ta.classList.toggle('expand', ta.scrollHeight > 140);
12841
+ }
12842
+
12843
+ function mcpRunCurrent() {
12844
+ const msg = els.mcpChatInput.value.trim();
12845
+ if (!msg || mcpChatOpening) return;
12846
+ els.mcpChatInput.value = '';
12847
+ mcpInputResize();
12848
+ mcpLine('t-cmd', 'sen> ' + msg);
12849
+ mcpSetBusy(true);
12850
+ beast.mcpChatSend({ msg }).then((r) => {
12851
+ if (r && r.ok) {
12852
+ if (r.sessionId) mcpChatSid = r.sessionId;
12853
+ if (r.steered) mcpLine('t-dim', '\u23E9 koşan tura eklendi');
12854
+ if (r.queued) mcpLine('t-dim', '\u23F3 kuyrukta (' + r.count + ') — iş bitince gönderilir');
12855
+ } else {
12856
+ mcpSetBusy(false);
12857
+ mcpLine('t-err', (r && r.error) || 'gönderilemedi');
12858
+ }
12859
+ }).catch((e) => {
12860
+ mcpSetBusy(false);
12861
+ mcpLine('t-err', String((e && e.message) || e));
12862
+ });
12863
+ }
12864
+
12865
+ if (els.mcpChatSend) els.mcpChatSend.addEventListener('click', () => {
12866
+ mcpRunCurrent();
12867
+ if (els.mcpChatInput) els.mcpChatInput.focus();
12868
+ });
12869
+ if (els.mcpChatStop) els.mcpChatStop.addEventListener('click', () => {
12870
+ beast.mcpChatStop().then((r) => {
12871
+ if (r && r.ok && r.wasBusy === false) {
12872
+ mcpSetBusy(false);
12873
+ mcpStatusHide();
12874
+ }
12875
+ }).catch(() => {});
12876
+ });
12877
+ if (els.mcpChatNew) els.mcpChatNew.addEventListener('click', async () => {
12878
+ const r = await beast.mcpChatNew().catch(() => null);
12879
+ if (!r || !r.ok) { toast((r && r.error) || 'yeni sohbet açılamadı'); return; }
12880
+ mcpChatSid = '';
12881
+ if (els.mcpChatOut) els.mcpChatOut.innerHTML = '';
12882
+ mcpFlushStream();
12883
+ mcpSetBusy(false);
12884
+ mcpStatusHide();
12885
+ mcpLine('t-dim', 'yeni MCP sohbeti — ilk mesajla başlar');
12886
+ mcpHistFill(r.items || []);
12887
+ if (els.mcpChatInput) els.mcpChatInput.focus();
12888
+ });
12889
+ if (els.mcpChatHist) els.mcpChatHist.addEventListener('change', () => {
12890
+ const id = String(els.mcpChatHist.value || '');
12891
+ if (!id || id === mcpChatSid) return;
12892
+ if (mcpChatBusy) {
12893
+ mcpHistFill(mcpChatItems);
12894
+ toast('mesaj sürüyor — önce ■ ile durdur');
12895
+ return;
12896
+ }
12897
+ mcpChatOpen(id);
12898
+ });
12899
+ if (els.mcpChatInput) {
12900
+ els.mcpChatInput.addEventListener('input', mcpInputResize);
12901
+ els.mcpChatInput.addEventListener('keydown', (e) => {
12902
+ if (e.key === 'Enter' && !e.shiftKey) {
12903
+ e.preventDefault();
12904
+ mcpRunCurrent();
12905
+ }
12906
+ });
12907
+ }
12908
+
12909
+ /* ---------- MCP sohbet/detay ayırıcı (sandbox deseni, sohbet SAĞDA) ----------
12910
+ Kaydedilen değer sohbet panelinin mcpRow içindeki payı (0-1). */
12911
+ let mcpSplitFrac = 0;
12912
+
12913
+ function mcpSplitApplyFrac() {
12914
+ const rowW = els.mcpRow && els.mcpRow.clientWidth ? els.mcpRow.clientWidth : window.innerWidth - 250;
12915
+ if (!mcpSplitFrac) {
12916
+ const w = Math.max(320, Math.min(520, Math.round(rowW * 0.34)));
12917
+ document.body.style.setProperty('--mcpSplit', w + 'px');
12918
+ return;
12919
+ }
12920
+ mcpSplitFrac = Math.max(0.2, Math.min(mcpSplitFrac, 0.85));
12921
+ const w = Math.max(300, Math.min(Math.round(rowW * mcpSplitFrac), Math.max(320, rowW - 240)));
12922
+ document.body.style.setProperty('--mcpSplit', w + 'px');
12923
+ }
12924
+
12925
+ function mcpSplitRestore() {
12926
+ let saved = 0;
12927
+ try { saved = parseFloat(localStorage.getItem('beast.mcpSplit')) || 0; } catch {}
12928
+ mcpSplitFrac = saved > 0.05 && saved < 0.95 ? saved : 0;
12929
+ mcpSplitApplyFrac();
12930
+ }
12931
+
12932
+ if (els.mcpSplit) {
12933
+ els.mcpSplit.addEventListener('mousedown', (e) => {
12934
+ e.preventDefault();
12935
+ els.mcpSplit.classList.add('dragging');
12936
+ const rightEdge = els.mcpChat ? els.mcpChat.getBoundingClientRect().right : window.innerWidth;
12937
+ const rowW = Math.max(600, els.mcpRow && els.mcpRow.clientWidth ? els.mcpRow.clientWidth : window.innerWidth - 250);
12938
+ const move = (ev) => {
12939
+ const w = Math.max(300, Math.min(rightEdge - ev.clientX, rowW - 240));
12940
+ mcpSplitFrac = Math.max(0.2, Math.min(w / rowW, 0.85));
12941
+ document.body.style.setProperty('--mcpSplit', Math.round(w) + 'px');
12942
+ };
12943
+ const up = () => {
12944
+ document.removeEventListener('mousemove', move);
12945
+ document.removeEventListener('mouseup', up);
12946
+ els.mcpSplit.classList.remove('dragging');
12947
+ try { localStorage.setItem('beast.mcpSplit', String(mcpSplitFrac)); } catch {}
12948
+ };
12949
+ document.addEventListener('mousemove', move);
12950
+ document.addEventListener('mouseup', up);
12951
+ });
12952
+ window.addEventListener('resize', () => { if (mcpModeOn()) mcpSplitApplyFrac(); });
12953
+ }
12954
+
12648
12955
  /* ---------- ÇALIŞTIRICI v2: butonlar DETERMİNİSTİK ----------
12649
12956
  Proje tipi algılanır (package.json/requirements.txt/pyproject/Cargo.toml/
12650
12957
  go.mod/hugo/jekyll/mkdocs/index.html); Başlat/Dev gerekirse bağımlılıkları
@@ -4588,7 +4588,7 @@ body.mcp-mode #mcpRow { display: flex; flex-direction: row; }
4588
4588
  display: flex;
4589
4589
  flex-direction: column;
4590
4590
  flex: 1;
4591
- min-width: 0;
4591
+ min-width: 220px;
4592
4592
  min-height: 0;
4593
4593
  background: var(--bg);
4594
4594
  border-left: 1px solid var(--border);
@@ -4764,6 +4764,130 @@ body.mcp-mode #mcpRow { display: flex; flex-direction: row; }
4764
4764
  outline: none;
4765
4765
  white-space: pre;
4766
4766
  }
4767
+
4768
+ /* MCP sağ sohbet paneli: ana sohbetten TAMAMEN AYRI oturum (bgTitle 'Beast MCP') */
4769
+ #mcpChat {
4770
+ display: flex;
4771
+ flex-direction: column;
4772
+ min-height: 0;
4773
+ min-width: 280px;
4774
+ flex: 0 0 var(--mcpSplit, 440px);
4775
+ background: var(--bg);
4776
+ overflow: hidden;
4777
+ }
4778
+ #mcpSplit {
4779
+ flex: none;
4780
+ width: 6px;
4781
+ cursor: col-resize;
4782
+ background: var(--border);
4783
+ opacity: 0.55;
4784
+ transition: opacity 0.15s;
4785
+ }
4786
+ #mcpSplit:hover { opacity: 1; }
4787
+ #mcpChatHead {
4788
+ flex: none;
4789
+ display: flex;
4790
+ align-items: center;
4791
+ gap: 8px;
4792
+ padding: 9px 12px;
4793
+ border-bottom: 1px solid var(--border);
4794
+ background: var(--panel);
4795
+ }
4796
+ #mcpChatTitle { font-size: 11px; font-weight: 800; letter-spacing: 1px; color: var(--accent); flex: none; }
4797
+ #mcpChatHist {
4798
+ flex: 1;
4799
+ min-width: 0;
4800
+ background: var(--panel2);
4801
+ border: 1px solid var(--border);
4802
+ color: var(--text);
4803
+ font-size: 11px;
4804
+ padding: 3px 6px;
4805
+ border-radius: 6px;
4806
+ cursor: pointer;
4807
+ }
4808
+ #mcpChatHist:hover { border-color: var(--accent); }
4809
+ #mcpChatHead button {
4810
+ background: none;
4811
+ border: none;
4812
+ color: var(--muted);
4813
+ font-size: 14px;
4814
+ cursor: pointer;
4815
+ padding: 2px 7px;
4816
+ border-radius: 6px;
4817
+ }
4818
+ #mcpChatHead button:hover { background: var(--panel2); color: var(--text); }
4819
+ #mcpChatOut {
4820
+ flex: 1;
4821
+ min-height: 0;
4822
+ overflow-y: auto;
4823
+ padding: 10px 12px;
4824
+ font-family: Consolas, monospace;
4825
+ font-size: 12px;
4826
+ line-height: 1.5;
4827
+ white-space: pre-wrap;
4828
+ word-break: break-word;
4829
+ }
4830
+ #mcpChatStatus {
4831
+ flex: none;
4832
+ align-self: center;
4833
+ margin: 0 12px 6px;
4834
+ padding: 3px 10px;
4835
+ font-size: 11px;
4836
+ color: var(--accent);
4837
+ background: var(--accent-dim);
4838
+ border: 1px solid var(--accent);
4839
+ border-radius: 999px;
4840
+ max-width: calc(100% - 24px);
4841
+ overflow: hidden;
4842
+ text-overflow: ellipsis;
4843
+ white-space: nowrap;
4844
+ }
4845
+ #mcpChatStatus[hidden] { display: none; }
4846
+ #mcpChatInputRow {
4847
+ flex: none;
4848
+ display: flex;
4849
+ gap: 6px;
4850
+ align-items: flex-end;
4851
+ padding: 8px 12px;
4852
+ border-top: 1px solid var(--border);
4853
+ background: var(--panel);
4854
+ }
4855
+ #mcpChatInput {
4856
+ flex: 1;
4857
+ min-width: 0;
4858
+ resize: none;
4859
+ background: var(--panel2);
4860
+ border: 1px solid var(--border);
4861
+ color: var(--text);
4862
+ font-size: 12.5px;
4863
+ padding: 7px 9px;
4864
+ border-radius: 8px;
4865
+ font-family: inherit;
4866
+ overflow-y: hidden;
4867
+ max-height: 140px;
4868
+ line-height: 1.45;
4869
+ display: block;
4870
+ }
4871
+ #mcpChatInput:focus { border-color: var(--accent); outline: none; }
4872
+ #mcpChatInput.expand { overflow-y: auto; }
4873
+ #mcpChatInputRow button {
4874
+ flex: none;
4875
+ background: var(--panel2);
4876
+ border: 1px solid var(--border);
4877
+ color: var(--text);
4878
+ border-radius: 7px;
4879
+ cursor: pointer;
4880
+ font-size: 11px;
4881
+ padding: 6px 9px;
4882
+ line-height: 1;
4883
+ margin-bottom: 1px;
4884
+ }
4885
+ #mcpChatInputRow button:hover { border-color: var(--accent); }
4886
+ #mcpChatSend { color: var(--accent); }
4887
+ #mcpChatSend:hover { background: var(--accent-dim); }
4888
+ #mcpChatStop { color: var(--err); }
4889
+ #mcpChatStop[hidden] { display: none; }
4890
+ #mcpChatStop:hover { border-color: var(--err); }
4767
4891
  #sbRunBtns {
4768
4892
  flex: none;
4769
4893
  display: flex;