beast-agent 2.45.0 → 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/package.json +1 -1
- package/src/agent/engine.js +16 -6
- package/src/main.js +206 -0
- package/src/preload.js +5 -0
- package/src/renderer/index.html +18 -0
- package/src/renderer/renderer.js +307 -0
- package/src/renderer/style.css +125 -1
package/package.json
CHANGED
package/src/agent/engine.js
CHANGED
|
@@ -1428,10 +1428,10 @@ class Engine {
|
|
|
1428
1428
|
return out.slice(0, 100);
|
|
1429
1429
|
}
|
|
1430
1430
|
|
|
1431
|
-
/*
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1431
|
+
/* Panel oturumları: belirli bir bgTitle taşıyan gizli oturumlar (Beast Code,
|
|
1432
|
+
Beast MCP…) — ana sohbet listesinden (listSessions) TAMAMEN AYRIDIR. */
|
|
1433
|
+
_listTitledSessions(title, limit = 100) {
|
|
1434
|
+
const wanted = String(title || '');
|
|
1435
1435
|
let files = [];
|
|
1436
1436
|
try {
|
|
1437
1437
|
files = fs.readdirSync(this.sessionsDir).filter((f) => f.endsWith('.jsonl'));
|
|
@@ -1441,7 +1441,7 @@ class Engine {
|
|
|
1441
1441
|
const id = f.replace(/\.jsonl$/, '');
|
|
1442
1442
|
let s;
|
|
1443
1443
|
try { s = this._load(id); } catch { continue; }
|
|
1444
|
-
if (s.bgTitle !==
|
|
1444
|
+
if (s.bgTitle !== wanted) continue;
|
|
1445
1445
|
let title = '';
|
|
1446
1446
|
for (const m of s.messages) {
|
|
1447
1447
|
if (m.role !== 'user') continue;
|
|
@@ -1453,7 +1453,7 @@ class Engine {
|
|
|
1453
1453
|
}
|
|
1454
1454
|
out.push({
|
|
1455
1455
|
id,
|
|
1456
|
-
title: title || '
|
|
1456
|
+
title: title || wanted + ' oturumu',
|
|
1457
1457
|
updatedAt: s.updatedAt,
|
|
1458
1458
|
createdAt: s.createdAt,
|
|
1459
1459
|
count: s.messages.length,
|
|
@@ -1464,6 +1464,16 @@ class Engine {
|
|
|
1464
1464
|
return out.slice(0, Math.max(1, Math.min(200, Number(limit) || 100)));
|
|
1465
1465
|
}
|
|
1466
1466
|
|
|
1467
|
+
/* Beast Code panel oturumları: soldaki dosya panelinin geçmiş listesi gösterir */
|
|
1468
|
+
listBcSessions(limit = 100) {
|
|
1469
|
+
return this._listTitledSessions('Beast Code', limit);
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
/* Beast MCP sohbet oturumları: MCP modundaki sağ sohbet paneli gösterir */
|
|
1473
|
+
listMcpSessions(limit = 100) {
|
|
1474
|
+
return this._listTitledSessions('Beast MCP', limit);
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1467
1477
|
createSession() {
|
|
1468
1478
|
const id = uid();
|
|
1469
1479
|
const code = this._newCode();
|
package/src/main.js
CHANGED
|
@@ -3311,6 +3311,7 @@ function reloadBackend() {
|
|
|
3311
3311
|
bcFlushOnDone(ev); /* Beast Code kuyruğunu iş bitiminde boşalt */
|
|
3312
3312
|
stFlushOnDone(ev); /* Beast Studio kuyruğunu iş bitiminde boşalt */
|
|
3313
3313
|
sbFlushOnDone(ev); /* Sandbox kuyruğunu iş bitiminde boşalt */
|
|
3314
|
+
mcpChatFlushOnDone(ev); /* MCP sohbet kuyruğunu iş bitiminde boşalt */
|
|
3314
3315
|
finFlushOnDone(ev); /* Finance trader döngüsü: iş bitince sıradaki turu planla */
|
|
3315
3316
|
/* BC canlı önizleme: ajan bir dev server başlattıysa adresi yakala —
|
|
3316
3317
|
preview butonu ve otomatik açılış DAİMA bu sunucuyu öncelikli kullanır */
|
|
@@ -6635,6 +6636,211 @@ ipcMain.handle('mcp:refresh', async (_e, name) => {
|
|
|
6635
6636
|
}
|
|
6636
6637
|
});
|
|
6637
6638
|
|
|
6639
|
+
/* ---------------- BEAST MCP SOHBETİ (MCP modu SAĞ panel) ----------------
|
|
6640
|
+
MCP moduna özel, ANA SOHBETTEN TAMAMEN AYRI oturum: bgTitle 'Beast MCP'
|
|
6641
|
+
(listSessions gizler, listMcpSessions listeler; geçmiş seçici eski
|
|
6642
|
+
oturumları açabilir). MCP sunucu araçları zaten tüm engine turlarına
|
|
6643
|
+
enjekte edilir; panel yalnız oturum yaşam döngüsünü yönetir.
|
|
6644
|
+
Gönderim main chat disiplininin aynısı: boşta kısa debounce (ard arda
|
|
6645
|
+
mesajlar birleşir), meşgulken steer (koşan tura anında eklenir). */
|
|
6646
|
+
let mcpChatSid = ''; /* aktif MCP sohbet oturumu */
|
|
6647
|
+
let mcpChatFresh = false; /* 'Yeni' istendi: eski sohbete DÖNME, taze aç */
|
|
6648
|
+
const mcpChatQueue = new Map(); /* 'mcp' → { timer, msgs[] } */
|
|
6649
|
+
const MCP_CHAT_DEBOUNCE_MS = 900;
|
|
6650
|
+
|
|
6651
|
+
function mcpChatCreate() {
|
|
6652
|
+
const s = engine._load(engine.createSession().id);
|
|
6653
|
+
s.messages = s.messages || [];
|
|
6654
|
+
s.bgTitle = 'Beast MCP'; /* _view.isBg → ana sohbet geçmişi listesinde gizli */
|
|
6655
|
+
try {
|
|
6656
|
+
fs.appendFileSync(
|
|
6657
|
+
engine._file(s.id),
|
|
6658
|
+
JSON.stringify({ t: 'meta2', bgOf: '', title: 'Beast MCP', at: new Date().toISOString() }) + '\n'
|
|
6659
|
+
);
|
|
6660
|
+
} catch {}
|
|
6661
|
+
engine.cache.set(s.id, s);
|
|
6662
|
+
mcpChatSid = s.id;
|
|
6663
|
+
mcpChatFresh = false;
|
|
6664
|
+
return s;
|
|
6665
|
+
}
|
|
6666
|
+
|
|
6667
|
+
function mcpChatSession() {
|
|
6668
|
+
if (mcpChatSid) {
|
|
6669
|
+
try {
|
|
6670
|
+
const s = engine.cache.get(mcpChatSid) || engine._load(mcpChatSid);
|
|
6671
|
+
if (s && s.bgTitle === 'Beast MCP') return s;
|
|
6672
|
+
} catch {}
|
|
6673
|
+
mcpChatSid = '';
|
|
6674
|
+
}
|
|
6675
|
+
/* 'Yeni' istenmediyse son MCP sohbetine dön: uygulama yeniden açıldığında
|
|
6676
|
+
sohbet kaldığı yerden sürer (geçmiş seçiciden eski oturumlar açılabilir) */
|
|
6677
|
+
if (!mcpChatFresh) {
|
|
6678
|
+
try {
|
|
6679
|
+
const last = engine.listMcpSessions(50).find((it) => it.count > 0);
|
|
6680
|
+
if (last) {
|
|
6681
|
+
const s = engine._load(last.id);
|
|
6682
|
+
if (s && s.bgTitle === 'Beast MCP') {
|
|
6683
|
+
engine.cache.set(s.id, s);
|
|
6684
|
+
mcpChatSid = s.id;
|
|
6685
|
+
return s;
|
|
6686
|
+
}
|
|
6687
|
+
}
|
|
6688
|
+
} catch {}
|
|
6689
|
+
}
|
|
6690
|
+
return mcpChatCreate();
|
|
6691
|
+
}
|
|
6692
|
+
|
|
6693
|
+
/* geçmiş yükü: yalnız metin mesajları (tool çağrıları panele basılmaz) */
|
|
6694
|
+
function mcpChatMessages(s) {
|
|
6695
|
+
const msgs = [];
|
|
6696
|
+
for (const m of s.messages || []) {
|
|
6697
|
+
if (m.tool_calls) continue;
|
|
6698
|
+
const txt = bcMsgText(m);
|
|
6699
|
+
if (!txt) continue;
|
|
6700
|
+
msgs.push({ role: m.role === 'assistant' ? 'assistant' : 'user', text: txt.slice(0, 4000) });
|
|
6701
|
+
}
|
|
6702
|
+
return msgs.slice(-200);
|
|
6703
|
+
}
|
|
6704
|
+
|
|
6705
|
+
/* geçmiş listesi: boş oturumlar gizlenir (aktif olan daima görünür) */
|
|
6706
|
+
function mcpChatHistory() {
|
|
6707
|
+
let items = [];
|
|
6708
|
+
try { items = engine.listMcpSessions(100); } catch {}
|
|
6709
|
+
return items.filter((it) => it.id === mcpChatSid || it.count > 0);
|
|
6710
|
+
}
|
|
6711
|
+
|
|
6712
|
+
function mcpChatQueuePush(text, attachments) {
|
|
6713
|
+
let q = mcpChatQueue.get('mcp');
|
|
6714
|
+
if (!q) {
|
|
6715
|
+
q = { timer: null, msgs: [] };
|
|
6716
|
+
mcpChatQueue.set('mcp', q);
|
|
6717
|
+
}
|
|
6718
|
+
q.msgs.push({
|
|
6719
|
+
text,
|
|
6720
|
+
attachments: Array.isArray(attachments) && attachments.length ? attachments : undefined,
|
|
6721
|
+
});
|
|
6722
|
+
return q;
|
|
6723
|
+
}
|
|
6724
|
+
|
|
6725
|
+
function mcpChatFlush() {
|
|
6726
|
+
const q = mcpChatQueue.get('mcp');
|
|
6727
|
+
if (!q || !q.msgs.length) return;
|
|
6728
|
+
const s = mcpChatSession();
|
|
6729
|
+
if (engine.isBusy(s.id)) return; /* hâlâ çalışıyor — steer yolu mesajı zaten aldı */
|
|
6730
|
+
let merged = '';
|
|
6731
|
+
let mergedAtts = null;
|
|
6732
|
+
for (const m of q.msgs) {
|
|
6733
|
+
if (m.text) merged += (merged ? '\n' : '') + m.text;
|
|
6734
|
+
if (!mergedAtts && Array.isArray(m.attachments) && m.attachments.length) mergedAtts = m.attachments;
|
|
6735
|
+
}
|
|
6736
|
+
mcpChatQueue.delete('mcp');
|
|
6737
|
+
clearTimeout(q.timer);
|
|
6738
|
+
if (!merged.trim() && !mergedAtts) return;
|
|
6739
|
+
try {
|
|
6740
|
+
engine.send(s.id, mergedAtts ? { text: merged, attachments: mergedAtts } : merged, { userAction: true });
|
|
6741
|
+
} catch (e) {
|
|
6742
|
+
/* senkron patlama: panel busy'de kilitlenmesin — hata olayı düş */
|
|
6743
|
+
try {
|
|
6744
|
+
if (win && !win.isDestroyed()) {
|
|
6745
|
+
win.webContents.send('agent:event', { sessionId: s.id, type: 'error', error: String((e && e.message) || e) });
|
|
6746
|
+
}
|
|
6747
|
+
} catch {}
|
|
6748
|
+
}
|
|
6749
|
+
}
|
|
6750
|
+
|
|
6751
|
+
function mcpChatFlushOnDone(ev) {
|
|
6752
|
+
if (!ev || (ev.type !== 'done' && ev.type !== 'error') || !ev.sessionId) return;
|
|
6753
|
+
if (mcpChatQueue.has('mcp') && String(ev.sessionId) === String(mcpChatSid)) {
|
|
6754
|
+
setTimeout(() => { try { mcpChatFlush(); } catch {} }, 150);
|
|
6755
|
+
}
|
|
6756
|
+
}
|
|
6757
|
+
|
|
6758
|
+
ipcMain.handle('mcp:chat:open', async (_e, payload) => {
|
|
6759
|
+
if (!engine) return { ok: false, error: 'ajan hazır değil' };
|
|
6760
|
+
/* bekleyen debounce kuyruğu varsa ÖNCE eski oturuma teslim et (mesaj kaybolmaz) */
|
|
6761
|
+
try {
|
|
6762
|
+
if (mcpChatQueue.has('mcp') && mcpChatSid) mcpChatFlush();
|
|
6763
|
+
} catch {}
|
|
6764
|
+
const q = mcpChatQueue.get('mcp');
|
|
6765
|
+
if (q) {
|
|
6766
|
+
clearTimeout(q.timer);
|
|
6767
|
+
mcpChatQueue.delete('mcp');
|
|
6768
|
+
}
|
|
6769
|
+
const id = String((payload && payload.id) || '');
|
|
6770
|
+
let s;
|
|
6771
|
+
if (id) {
|
|
6772
|
+
try { s = engine._load(id); } catch { return { ok: false, error: 'oturum açılamadı' }; }
|
|
6773
|
+
if (s.bgTitle !== 'Beast MCP') return { ok: false, error: 'bu oturum MCP sohbeti değil' };
|
|
6774
|
+
mcpChatSid = id;
|
|
6775
|
+
mcpChatFresh = false;
|
|
6776
|
+
} else {
|
|
6777
|
+
s = mcpChatSession();
|
|
6778
|
+
}
|
|
6779
|
+
engine.cache.set(s.id, s);
|
|
6780
|
+
return {
|
|
6781
|
+
ok: true,
|
|
6782
|
+
sessionId: s.id,
|
|
6783
|
+
busy: !!engine.isBusy(s.id),
|
|
6784
|
+
messages: mcpChatMessages(s),
|
|
6785
|
+
items: mcpChatHistory(),
|
|
6786
|
+
};
|
|
6787
|
+
});
|
|
6788
|
+
|
|
6789
|
+
ipcMain.handle('mcp:chat:send', async (_e, payload) => {
|
|
6790
|
+
const text = String((payload && payload.msg) || '').trim();
|
|
6791
|
+
const attachments = Array.isArray(payload && payload.attachments) ? payload.attachments : [];
|
|
6792
|
+
if (!text && !attachments.length) return { ok: false, error: 'boş mesaj' };
|
|
6793
|
+
if (!engine) return { ok: false, error: 'ajan hazır değil' };
|
|
6794
|
+
if (!engine.publicState().hasModel) return { ok: false, error: 'model yok — Ayarlar → Provider sekmesinden ekle' };
|
|
6795
|
+
const s = mcpChatSession();
|
|
6796
|
+
if (engine.isBusy(s.id)) {
|
|
6797
|
+
/* MAIN CHAT STEER: koşan tur varken mesaj ANINDA konuşmaya eklenir */
|
|
6798
|
+
engine.send(s.id, attachments.length ? { text, attachments } : text, { userAction: true });
|
|
6799
|
+
return { ok: true, sessionId: s.id, steered: true };
|
|
6800
|
+
}
|
|
6801
|
+
const q = mcpChatQueuePush(text, attachments);
|
|
6802
|
+
clearTimeout(q.timer);
|
|
6803
|
+
q.timer = setTimeout(() => { try { mcpChatFlush(); } catch {} }, MCP_CHAT_DEBOUNCE_MS);
|
|
6804
|
+
return { ok: true, sessionId: s.id, pending: true };
|
|
6805
|
+
});
|
|
6806
|
+
|
|
6807
|
+
ipcMain.handle('mcp:chat:stop', async () => {
|
|
6808
|
+
const q = mcpChatQueue.get('mcp');
|
|
6809
|
+
if (q) {
|
|
6810
|
+
clearTimeout(q.timer);
|
|
6811
|
+
mcpChatQueue.delete('mcp');
|
|
6812
|
+
}
|
|
6813
|
+
const sid = mcpChatSid;
|
|
6814
|
+
const wasBusy = sid ? engine.isBusy(sid) : false;
|
|
6815
|
+
let r = false;
|
|
6816
|
+
if (wasBusy) {
|
|
6817
|
+
try { r = engine.interrupt(sid, 'kullanıcı MCP sohbet panelinden ■ ile durdurdu'); } catch {}
|
|
6818
|
+
}
|
|
6819
|
+
return { ok: true, wasBusy, interrupted: r };
|
|
6820
|
+
});
|
|
6821
|
+
|
|
6822
|
+
ipcMain.handle('mcp:chat:new', async () => {
|
|
6823
|
+
if (!engine) return { ok: false, error: 'ajan hazır değil' };
|
|
6824
|
+
const sid = mcpChatSid;
|
|
6825
|
+
if (sid && engine.isBusy(sid)) return { ok: false, error: 'mesaj sürüyor — önce ■ ile durdur' };
|
|
6826
|
+
const q = mcpChatQueue.get('mcp');
|
|
6827
|
+
if (q) {
|
|
6828
|
+
clearTimeout(q.timer);
|
|
6829
|
+
mcpChatQueue.delete('mcp');
|
|
6830
|
+
}
|
|
6831
|
+
mcpChatSid = '';
|
|
6832
|
+
mcpChatFresh = true; /* sonraki oturum TAZE açılır; eski sohbet geçmişte kalır */
|
|
6833
|
+
return { ok: true, sessionId: '', messages: [], items: mcpChatHistory() };
|
|
6834
|
+
});
|
|
6835
|
+
|
|
6836
|
+
ipcMain.handle('mcp:chat:history', async () => {
|
|
6837
|
+
try {
|
|
6838
|
+
return { ok: true, items: mcpChatHistory() };
|
|
6839
|
+
} catch (e) {
|
|
6840
|
+
return { ok: false, error: String((e && e.message) || e), items: [] };
|
|
6841
|
+
}
|
|
6842
|
+
});
|
|
6843
|
+
|
|
6638
6844
|
/* ---------------- FALLOUT IPC ---------------- */
|
|
6639
6845
|
|
|
6640
6846
|
function defaultFallout() {
|
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'),
|
package/src/renderer/index.html
CHANGED
|
@@ -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
|
|
package/src/renderer/renderer.js
CHANGED
|
@@ -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ı
|
package/src/renderer/style.css
CHANGED
|
@@ -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:
|
|
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;
|