beast-agent 2.4.5 → 2.6.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
@@ -81,6 +81,10 @@ contextBridge.exposeInMainWorld('beast', {
81
81
  bcUndo: (sessionId, todoId) => ipcRenderer.invoke('bc:undo', { sessionId, todoId }),
82
82
  beastcodeStop: () => ipcRenderer.invoke('beastcode:stop'),
83
83
  beastcodeNew: () => ipcRenderer.invoke('beastcode:new'),
84
+ bcHistory: () => ipcRenderer.invoke('bc:history'),
85
+ bcOpen: (id) => ipcRenderer.invoke('bc:open', { id }),
86
+ bcDelete: (id) => ipcRenderer.invoke('bc:delete', { id }),
87
+ bcDeleteAll: () => ipcRenderer.invoke('bc:deleteAll'),
84
88
  studioSend: (msg, attachments) => ipcRenderer.invoke('studio:send', { msg, attachments }),
85
89
  studioStop: () => ipcRenderer.invoke('studio:stop'),
86
90
  studioNew: () => ipcRenderer.invoke('studio:new'),
@@ -69,7 +69,7 @@
69
69
  tab_notes: 'Oturum Notları',
70
70
  tab_history: 'Oturum Geçmişi',
71
71
  tab_agents: 'Paralel Ajanlar',
72
- tab_tts: 'Sesli Yanıt',
72
+ tab_tts: 'Sesli Yanıt',
73
73
  tab_install: 'Kurulum',
74
74
  tab_email: 'E-posta',
75
75
  tab_integrations: 'Entegrasyonlar',
@@ -131,7 +131,7 @@
131
131
  em_notify_tg: 'Telegram',
132
132
  em_notify_dc: 'Discord',
133
133
  em_notify_sub: 'Seçmezsen ekli ve bağlı entegrasyonların hepsine yazar; hiçbiri bağlı değilse masaüstü sohbete düşer.',
134
- em_interests: 'İlgi alanların — haber filtresi buna göre ağırlıklandırılır',
134
+ em_interests: 'İlgi Alanları',
135
135
  em_interests_ph: 'örn: yapay zeka, yazılım, trading, open source',
136
136
  em_news: 'Haber kaynağı (Google News)',
137
137
  em_news_topics_ph: 'haber konuları, virgülle: yapay zeka, ekonomi…',
@@ -148,10 +148,12 @@
148
148
  em_st_ignored: 'yok sayıldı',
149
149
  em_lv_high: 'YÜKSEK',
150
150
  em_lv_medium: 'ORTA',
151
- em_interests_auto: 'Bunlara ek olarak sohbetlerinden öğrenilen ilgi alanları da otomatik devreye girer.',
151
+ em_interests_auto: 'Konuşmalarından çıkarılan ilgi alanları otomatik eklenir; Google News haber taraması bu ilgilere göre seçimsiz otomatik yapılır.',
152
+ em_behavior: 'Ajan Davranışı',
153
+ em_behavior_ph: 'örn: bana kanka diye hitap et, kısa ve espirili yaz, emoji kullanma, soru sorarak bitir…',
152
154
  em_scan_busy: 'Tarama hâlâ çalışıyor — birkaç saniye sonra tekrar dene.',
153
155
  em_mem_h2: 'Empati Hafızası',
154
- em_mem_sub: 'Konuşmalarınız burada birikir; sohbetlerinden ilgi alanların öğrenilir. Tarama ve bildirim mesajları bu hafızayla sana göre kişiselleşir.',
156
+ em_mem_sub: 'Konuşmalarınız burada birikir; gece yansımasında (günde bir) bu kayıtlardan ilgi alanların çıkarılır. Tarama ve bildirim mesajları bu hafızayla sana göre kişiselleşir.',
155
157
  em_mem_learned: 'Sohbetlerden öğrenilen ilgi alanları',
156
158
  em_mem_no_learned: 'Henüz öğrenilen ilgi yok — sohbet ettikçe burada birikir.',
157
159
  em_mem_recent: 'Son konuşma kayıtları',
@@ -258,7 +260,7 @@
258
260
  tts_sub: 'Açık olursa WhatsApp cevapları metnin yanı sıra sesli not olarak da gönderilir.',
259
261
  tts_active: 'Aktif',
260
262
  tts_save: 'TTS Kaydet',
261
- tts_test: 'Test sesi çal',
263
+ tts_test: 'Test sesi çal',
262
264
  stt_download_now: 'Şimdi indir / hazırla',
263
265
  tts_note: 'Edge TTS: ücretsiz yerel motor — anahtar gerekmez (Ahmet/Emel vb.). OpenAI motoru: uyumlu speech API (tts-1, tts-1-hd; sesler alloy, echo, fable, onyx, nova, shimmer).',
264
266
  tts_engine: 'Motor',
@@ -583,6 +585,8 @@
583
585
  bc_ph: 'Beast Code mesajı yaz — Enter ile gönder…',
584
586
  st_ph: 'Beast Studio mesajı yaz — Enter ile gönder…',
585
587
  bc_new: 'Yeni oturum',
588
+ bc_hist: 'SOHBET GEÇMİŞİ',
589
+ bc_hist_clear: 'Tüm geçmişi sil',
586
590
  bc_clear: 'Çıktıyı temizle',
587
591
  bc_stop: 'Çalışan mesajı durdur',
588
592
  store_title: 'SKILLS STORE',
@@ -690,7 +694,7 @@
690
694
  tab_notes: 'Session Notes',
691
695
  tab_history: 'Session History',
692
696
  tab_agents: 'Parallel Agents',
693
- tab_tts: 'Voice Reply',
697
+ tab_tts: 'Voice Reply',
694
698
  tab_install: 'Setup',
695
699
  tab_email: 'E-mail',
696
700
  tab_integrations: 'Integrations',
@@ -752,7 +756,7 @@
752
756
  em_notify_tg: 'Telegram',
753
757
  em_notify_dc: 'Discord',
754
758
  em_notify_sub: 'If left empty, it writes to all connected integrations; with none connected it lands in the desktop chat.',
755
- em_interests: 'Your interests — news filtering is weighted by these',
759
+ em_interests: 'Interest Areas',
756
760
  em_interests_ph: 'e.g. AI, software, trading, open source',
757
761
  em_news: 'News source (Google News)',
758
762
  em_news_topics_ph: 'news topics, comma separated: AI, economy…',
@@ -769,10 +773,12 @@
769
773
  em_st_ignored: 'ignored',
770
774
  em_lv_high: 'HIGH',
771
775
  em_lv_medium: 'MEDIUM',
772
- em_interests_auto: 'On top of these, interest areas learned from your chats kick in automatically.',
776
+ em_interests_auto: 'Interest areas inferred from your chats are added automatically; Google News scanning runs automatically from these no manual topic selection.',
777
+ em_behavior: 'Agent Behavior',
778
+ em_behavior_ph: 'e.g. call me bro, keep it short and witty, no emojis, end with a question…',
773
779
  em_scan_busy: 'A scan is still running — try again in a few seconds.',
774
780
  em_mem_h2: 'Empathy Memory',
775
- em_mem_sub: 'Your conversations accumulate here; interest areas are learned from your chats. Scans and notification texts are personalized with this memory.',
781
+ em_mem_sub: 'Your conversations accumulate here; your interest areas are inferred from them at the night reflection (once a day). Scans and notification texts are personalized with this memory.',
776
782
  em_mem_learned: 'Interest areas learned from chats',
777
783
  em_mem_no_learned: 'No learned interests yet — they accumulate as you chat.',
778
784
  em_mem_recent: 'Recent conversation records',
@@ -879,7 +885,7 @@
879
885
  tts_sub: 'When on, WhatsApp replies are also sent as voice notes alongside text.',
880
886
  tts_active: 'Active',
881
887
  tts_save: 'Save TTS',
882
- tts_test: 'Play test sound',
888
+ tts_test: 'Play test sound',
883
889
  stt_download_now: 'Download / prepare now',
884
890
  tts_note: 'Edge TTS: free local engine — no key needed (Ahmet/Emel etc.). OpenAI engine: compatible speech API (tts-1, tts-1-hd; voices alloy, echo, fable, onyx, nova, shimmer).',
885
891
  tts_engine: 'Engine',
@@ -1262,6 +1268,8 @@
1262
1268
  bc_ph: 'Type a message for Beast Code — press Enter to send…',
1263
1269
  st_ph: 'Type a message for Beast Studio — press Enter to send…',
1264
1270
  bc_new: 'New session',
1271
+ bc_hist: 'CHAT HISTORY',
1272
+ bc_hist_clear: 'Clear all history',
1265
1273
  bc_clear: 'Clear output',
1266
1274
  bc_stop: 'Stop running message',
1267
1275
  store_title: 'SKILLS STORE',
@@ -35,6 +35,14 @@
35
35
  <div id="filePanelPath" title="">—</div>
36
36
  <div id="tasksPanel" hidden></div>
37
37
  <div id="fileTree"></div>
38
+ <div id="bcHistWrap">
39
+ <div id="bcHistHead">
40
+ <span id="bcHistTitle" data-i18n="bc_hist">SOHBET GEÇMİŞİ</span>
41
+ <button id="bcHistRefresh" title="Yenile">&#x27F3;</button>
42
+ <button id="bcHistClear" title="Tüm geçmişi sil" data-i18n-title="bc_hist_clear"><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 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></button>
43
+ </div>
44
+ <div id="bcHistList"></div>
45
+ </div>
38
46
  </aside>
39
47
  <div id="sideFoot">
40
48
  <button id="gearBtn" title="Ayarlar" data-i18n-title="tipGear">&#x2699;&#xFE0E;</button>
@@ -419,7 +427,6 @@
419
427
  <button id="bbReload" title="Yenile" data-i18n-title="tip_bb_reload">&#x21BB;</button>
420
428
  <input id="bbUrl" placeholder="adres yaz veya ara…" autocomplete="off" spellcheck="false" data-i18n-ph="bb_ph" />
421
429
  <button id="bbPhone" title="Telefon modu — mobil versiyon / web versiyonu" data-i18n-title="tip_bb_phone"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="7" y="2" width="10" height="20" rx="2.5"/><line x1="11" y1="18" x2="13" y2="18"/></svg></button>
422
- <button id="bbMobile" title="Mobil önizleme — telefon silueti (Expo/Metro dev server)" data-i18n-title="tip_bb_mobile"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="1.5" width="14" height="21" rx="3.5"/><line x1="9.5" y1="4.5" x2="14.5" y2="4.5"/><line x1="10.5" y1="19.5" x2="13.5" y2="19.5"/></svg></button>
423
430
  <button id="bbOpenExt" title="Tarayıcıda aç" data-i18n-title="tip_bb_open">&#x2197;</button>
424
431
  <button id="bbClose" title="Kapat" data-i18n-title="btn_close">&#x00D7;</button>
425
432
  </div>
@@ -448,17 +455,6 @@
448
455
  <input type="file" id="fileInput" multiple hidden
449
456
  accept="image/*,.txt,.md,.json,.csv,.log,.js,.ts,.py,.ps1,.bat,.cmd,.html,.css,.yaml,.yml,.xml,.ini" />
450
457
 
451
- <!-- mobil önizleme cihaz seçici: telefonun ALTINDA yüzen modern picker -->
452
- <select id="bbDevice" title="Cihaz ölçüleri" hidden>
453
- <option value="iphone15promax">iPhone 15 Pro Max · 430×932</option>
454
- <option value="iphone15pro">iPhone 15 Pro · 393×852</option>
455
- <option value="iphone14">iPhone 14 · 390×844</option>
456
- <option value="iphonese">iPhone SE · 375×667</option>
457
- <option value="pixel8">Pixel 8 · 412×915</option>
458
- <option value="galaxys23">Galaxy S23 · 360×780</option>
459
- <option value="android">Android · 360×800</option>
460
- </select>
461
-
462
458
  <script src="i18n.js"></script>
463
459
  <script src="handsfree.js"></script>
464
460
  <script src="renderer.js"></script>
@@ -59,8 +59,6 @@ const els = {
59
59
  bbClose: $('#bbClose'),
60
60
  bbResize: $('#bbResize'),
61
61
  bbPhone: $('#bbPhone'),
62
- bbMobile: $('#bbMobile'),
63
- bbDevice: $('#bbDevice'),
64
62
  termCBtn: $('#termCBtn'),
65
63
  termPanel: $('#termPanel'),
66
64
  termCwd: $('#termCwd'),
@@ -77,6 +75,9 @@ const els = {
77
75
  bcStop: $('#bcStop'),
78
76
  bcClear: $('#bcClear'),
79
77
  bcNew: $('#bcNew'),
78
+ bcHistList: $('#bcHistList'),
79
+ bcHistRefresh: $('#bcHistRefresh'),
80
+ bcHistClear: $('#bcHistClear'),
80
81
  bcTodoWrap: $('#bcTodoWrap'),
81
82
  bcStatus: $('#bcStatus'),
82
83
  bcAttach: $('#bcAttach'),
@@ -3076,6 +3077,7 @@ async function renderEmpatiPane() {
3076
3077
  '<div style="font-size:12px">' + escapeHtml(e.title || '') + '</div>' +
3077
3078
  '<div class="ur-meta">' + escapeHtml(e.source || '') + ' · ' + when(e.ts) + ' · %' + (e.priority || 0) +
3078
3079
  (e.reason ? ' · ' + escapeHtml(e.reason) : '') + '</div>' +
3080
+ (e.url ? '<div class="ur-meta"><span class="em-evlink" style="color:var(--accent);cursor:pointer;text-decoration:underline" data-u="' + escapeHtml(e.url) + '">🔗 kaynağı aç</span></div>' : '') +
3079
3081
  (e.text ? '<div class="sub" style="font-size:11px">' + escapeHtml(e.text) + '</div>' : '') +
3080
3082
  '</div>' +
3081
3083
  '<span style="flex:none;font-size:11px;color:var(--muted)">' + (statusT[e.status] || e.status) + lvBadge(e) + '</span>' +
@@ -3109,51 +3111,42 @@ async function renderEmpatiPane() {
3109
3111
  <label class="sub">${_t('em_interests')}</label>
3110
3112
  <textarea id="emInterests" class="inp" rows="2" placeholder="${_t('em_interests_ph')}">${escapeHtml(cfg.interests || '')}</textarea>
3111
3113
  <div class="sub">${_t('em_interests_auto')}</div>
3114
+ ${(() => {
3115
+ const learned = (mem && Array.isArray(mem.learned)) ? mem.learned : [];
3116
+ if (!learned.length) return '<div class="sub" style="margin-top:4px;opacity:.8">' + _t('em_mem_no_learned') + '</div>';
3117
+ return '<div style="display:flex;flex-wrap:wrap;gap:4px;margin-top:6px">' +
3118
+ learned.map((x) =>
3119
+ '<span style="font-size:11px;padding:2px 8px;border:1px solid var(--border);border-radius:10px">' +
3120
+ escapeHtml(x.w) + '</span>'
3121
+ ).join('') + '</div>';
3122
+ })()}
3112
3123
  </div>
3113
- <label class="lock-row" style="margin-top:8px"><input type="checkbox" id="emNews" ${cfg.newsTopics ? 'checked' : ''}/><span>${_t('em_news')}</span></label>
3114
- <input id="emTopics" class="inp" style="${cfg.newsTopics ? '' : 'opacity:.5'}" placeholder="${_t('em_news_topics_ph')}" value="${escapeHtml(cfg.newsTopics || '')}" spellcheck="false"/>
3115
- <div style="display:flex;gap:8px;margin-top:10px;align-items:center">
3124
+ <div style="margin-top:8px">
3125
+ <label class="sub">${_t('em_behavior')}</label>
3126
+ <textarea id="emBehavior" class="inp" rows="2" placeholder="${_t('em_behavior_ph')}">${escapeHtml(cfg.behavior || '')}</textarea>
3127
+ </div>
3128
+ <div style="display:flex;gap:8px;margin-top:12px;align-items:center;justify-content:center">
3116
3129
  <button id="emSave" class="btn">${_t('mcp_save')}</button>
3117
3130
  <button id="emScan" class="btn ghost">${_t('em_scan')}</button>
3118
3131
  <span id="emMsg" class="sub" style="margin:0"></span>
3119
3132
  </div>
3120
- <div class="sub" style="margin-top:6px">${_t('em_note')}</div>
3121
- </div>
3122
- <h3 style="margin-top:16px;color:var(--muted)">${_t('em_mem_h2')}</h3>
3123
- <div class="sub">${_t('em_mem_sub')}</div>
3124
- <div style="margin-top:6px"><label class="sub">${_t('em_mem_learned')}</label>${(() => {
3125
- const learned = (mem && Array.isArray(mem.learned)) ? mem.learned : [];
3126
- if (!learned.length) return '<div class="sub" style="margin-top:2px">' + _t('em_mem_no_learned') + '</div>';
3127
- return '<div style="display:flex;flex-wrap:wrap;gap:4px;margin-top:4px">' +
3128
- learned.map((x) =>
3129
- '<span style="font-size:11px;padding:2px 8px;border:1px solid var(--border);border-radius:10px">' +
3130
- escapeHtml(x.w) + ' <span style="color:var(--muted)">×' + (x.c || 0) + '</span></span>'
3131
- ).join('') + '</div>';
3132
- })()}</div>
3133
- <div style="margin-top:8px"><label class="sub">${_t('em_mem_recent')}</label>${(() => {
3134
- const chats = (mem && Array.isArray(mem.chats)) ? mem.chats : [];
3135
- if (!chats.length) return '<div class="sub" style="margin-top:2px">' + _t('em_mem_no_recent') + '</div>';
3136
- return '<div style="margin-top:4px">' + chats.map((c) =>
3137
- '<div class="usage-row" style="align-items:flex-start">' +
3138
- '<div style="min-width:0;flex:1">' +
3139
- '<div style="font-size:12px">' + escapeHtml(c.t || '') + '</div>' +
3140
- '<div class="ur-meta">' + escapeHtml(c.ch || '') + ' · ' + when(c.ts) + '</div>' +
3141
- '</div></div>').join('') + '</div>';
3142
- })()}
3143
- <button id="emMemClear" class="btn ghost" style="margin-top:8px;font-size:12px">${_t('em_mem_clear')}</button>
3144
3133
  </div>
3145
3134
  <h3 style="margin-top:16px;color:var(--muted)">${_t('em_events')}</h3>`;
3146
3135
  const wrap = document.createElement('div');
3147
3136
  if (!rows) wrap.innerHTML = '<p class="sub">' + _t('em_no_events') + '</p>';
3148
3137
  else wrap.innerHTML = rows;
3149
3138
  pane.appendChild(wrap);
3139
+ /* olay linkleri: tıklayınca harici tarayıcıda açılır */
3140
+ wrap.querySelectorAll('.em-evlink').forEach((el) => {
3141
+ el.addEventListener('click', () => {
3142
+ const u = el.dataset.u;
3143
+ if (u && /^https?:\/\//i.test(u)) beast.openExternal(u);
3144
+ });
3145
+ });
3150
3146
 
3151
3147
  const emOn = q('#emOn');
3152
3148
  const emDetail = q('#emDetail');
3153
- const emNews = q('#emNews');
3154
- const emTopics = q('#emTopics');
3155
3149
  if (emOn && emDetail) emOn.addEventListener('change', () => { emDetail.style.opacity = emOn.checked ? '' : '.5'; });
3156
- if (emNews && emTopics) emNews.addEventListener('change', () => { emTopics.style.opacity = emNews.checked ? '' : '.5'; });
3157
3150
  const emSaveBtn = q('#emSave');
3158
3151
  if (emSaveBtn) emSaveBtn.addEventListener('click', async () => {
3159
3152
  const patch = {
@@ -3163,8 +3156,8 @@ async function renderEmpatiPane() {
3163
3156
  cooldownMin: Number(q('#emCd').value),
3164
3157
  notifyTarget: q('#emTarget') ? q('#emTarget').value : '',
3165
3158
  filterModel: q('#emModel') ? q('#emModel').value : '',
3159
+ behavior: q('#emBehavior') ? q('#emBehavior').value.trim() : '',
3166
3160
  interests: q('#emInterests').value.trim(),
3167
- newsTopics: emNews.checked ? emTopics.value.trim() : '',
3168
3161
  };
3169
3162
  const r = await beast.empatiSet(patch).catch(() => null);
3170
3163
  toast(r ? _t('em_saved') : 'Hata');
@@ -3193,12 +3186,6 @@ async function renderEmpatiPane() {
3193
3186
  const b2 = q('#emScan');
3194
3187
  if (b2) b2.disabled = false;
3195
3188
  });
3196
- const emMemClearBtn = q('#emMemClear');
3197
- if (emMemClearBtn) emMemClearBtn.addEventListener('click', async () => {
3198
- const r = await beast.empatiMemClear().catch(() => null);
3199
- toast(r && r.ok ? _t('em_mem_cleared') : 'Hata');
3200
- if (r && r.ok) renderEmpatiPane();
3201
- });
3202
3189
  }
3203
3190
 
3204
3191
  async function renderWaAllow() {
@@ -5006,14 +4993,6 @@ function onEvent(ev) {
5006
4993
  if (shown && ev.width) document.body.style.setProperty('--bw', ev.width + 'px');
5007
4994
  document.body.classList.toggle('phone-mode', !!ev.phone);
5008
4995
  if (els.bbPhone) els.bbPhone.classList.toggle('on', !!ev.phone);
5009
- /* MOBİL ÖNİZLEME: telefon silueti çerçevesi + düğme durumu + cihaz seçimi */
5010
- document.body.classList.toggle('mobile-preview', !!ev.mobile);
5011
- if (els.bbMobile) els.bbMobile.classList.toggle('on', !!ev.mobile);
5012
- if (ev.device) {
5013
- document.body.dataset.pfDevice = ev.device;
5014
- if (els.bbDevice) els.bbDevice.value = ev.device;
5015
- }
5016
- renderPhoneFrame(ev.phoneRect || null);
5017
4996
  els.browserBar.hidden = !shown;
5018
4997
  els.bbResize.hidden = !shown;
5019
4998
  /* terminal artık ALT dock — tarayıcıyla birlikte yaşar, kapatılmaz */
@@ -5167,22 +5146,28 @@ function termSetHeight(h) {
5167
5146
  const v = Math.max(120, Math.min(Math.round(h), Math.round(window.innerHeight * 0.7)));
5168
5147
  document.body.style.setProperty('--th', v + 'px');
5169
5148
  try { localStorage.setItem('beast.termH', String(v)); } catch {}
5170
- /* native tarayıcı view'ına alt payı bildir — view yüksekliğini kısar */
5171
- beast.browserSetBottomInset(termOpen ? v : 0).catch(() => {});
5149
+ /* native tarayıcı view'ına alt payı bildir — IDE modunda terminal bölme içindedir,
5150
+ tarayıcıya dokunmaz; yalnız ajan modundaki alt dock paylaşımı bildirilir */
5151
+ if (!ideModeOn()) beast.browserSetBottomInset(termOpen ? v : 0).catch(() => {});
5172
5152
  }
5173
5153
 
5174
5154
  function termSetOpen(v) {
5175
- /* BEAST CODE modunda terminal HEP AÇIK: kapatma denemeleri IDE modunda yok sayılır */
5176
- if (!v && ideModeOn()) {
5177
- toast('Beast Code modunda terminal açık kalır');
5178
- return;
5179
- }
5180
5155
  termOpen = !!v;
5181
5156
  els.termPanel.hidden = !v;
5182
- els.termResize.hidden = !v;
5157
+ els.termResize.hidden = !v || ideModeOn(); /* IDE'de terminal bölme içi — boyutlandırma yok */
5183
5158
  document.body.classList.toggle('term-open', v);
5184
5159
  termSetShell(termShell);
5185
- /* alt dock: tarayıcı view'ı terminal payını boşaltır */
5160
+ if (ideModeOn()) {
5161
+ /* IDE modunda terminal soldaki KOD BÖLMÜNDE yaşar: açılınca editörü kapatır,
5162
+ kapanınca editör geri gelir — tarayıcıyla HİÇbir ilişkisi yok */
5163
+ document.body.classList.toggle('term-pane', v);
5164
+ if (v) {
5165
+ els.termInput.focus();
5166
+ termScroll(true);
5167
+ }
5168
+ return;
5169
+ }
5170
+ /* alt dock (ajan modu): tarayıcı view'ı terminal payını boşaltır */
5186
5171
  const th = parseInt(getComputedStyle(document.body).getPropertyValue('--th')) || 180;
5187
5172
  beast.browserSetBottomInset(v ? th : 0).catch(() => {});
5188
5173
  if (v) {
@@ -5226,55 +5211,9 @@ function termShortTool(name, args) {
5226
5211
  } catch { return ''; }
5227
5212
  }
5228
5213
 
5229
- /* ---------------- MOBİL ÖNİZLEME: telefon silueti ----------------
5230
- main, WebContentsView'ı cihaz EKRANI boyutuna küçültür (phoneRect olayıyla
5231
- gelir); çerçeve TEK YUVARLAK HALKA (border 12px, radius 42 — üst/alt köşeler
5232
- birebir aynı) DOM'da çizilir; home çubuğu alt kenar içindedir. */
5233
- const PF_BEZEL = 12;
5234
-
5235
- function renderPhoneFrame(rect) {
5236
- const pk = document.getElementById('bbDevice');
5237
- let f = document.getElementById('phoneFrame');
5238
- if (!rect) {
5239
- if (f) f.style.display = 'none';
5240
- if (pk) pk.style.display = 'none';
5241
- return;
5242
- }
5243
- if (!f) {
5244
- f = document.createElement('div');
5245
- f.id = 'phoneFrame';
5246
- f.innerHTML = '<div class="pf-home"></div>';
5247
- document.body.appendChild(f);
5248
- }
5249
- f.style.display = 'block';
5250
- f.style.left = (rect.x - PF_BEZEL) + 'px';
5251
- f.style.top = (rect.y - PF_BEZEL) + 'px';
5252
- f.style.width = (rect.width + PF_BEZEL * 2) + 'px';
5253
- f.style.height = (rect.height + PF_BEZEL * 2) + 'px';
5254
- /* cihaz seçici: çerçevenin altında ortalanmış */
5255
- if (pk) {
5256
- const frameBottom = rect.y + rect.height + PF_BEZEL;
5257
- pk.hidden = false;
5258
- pk.style.display = 'block';
5259
- pk.style.top = (frameBottom + 12) + 'px';
5260
- pk.style.left = Math.max(8, rect.x + rect.width / 2 - pk.offsetWidth / 2) + 'px';
5261
- }
5262
- }
5263
-
5264
- /* ajan dev sunucu başlattı mı? (expo/metro/vite/next) — mobil önizleme
5265
- açıksa oraya otomatik gidilir, kapatılsa da son URL hatırlanır */
5266
- let devSeenUrl = '';
5267
- const DEV_URL_RE_R = /https?:\/\/(?:localhost|127\.0\.0\.1|\[::1\]|(?:192\.168|10\.\d+|172\.(?:1[6-9]|2\d|3[01]))\.\d+\.\d+):(\d{2,5})/;
5268
- function devServerSeen(text) {
5269
- const m = DEV_URL_RE_R.exec(String(text || ''));
5270
- if (!m) return;
5271
- const port = Number(m[1]);
5272
- if (port === 19000 || port === 19001 || port === 19002) return; // expo native/log portları
5273
- const url = m[0].replace(/\/+$/, '') + '/';
5274
- if (devSeenUrl === url) return;
5275
- devSeenUrl = url;
5276
- if (document.body.classList.contains('mobile-preview')) beast.browserNavigate(url).catch(() => {});
5277
- }
5214
+ /* ---------------- MOBİL ÖNİZLEME kaldırıldı ----------------
5215
+ Telefon silueti (Expo/Metro canlı önizleme) şimdilik devre dışı —
5216
+ önizleme her projede normal tarayıcı dock'unda açılır. */
5278
5217
 
5279
5218
  /* ajan araç etkinliğini terminale akıt (tüm oturumlar: ana sohbet + paralel ajanlar + cron) */
5280
5219
  function termAgentEvent(ev) {
@@ -5283,8 +5222,6 @@ function termAgentEvent(ev) {
5283
5222
  const args = termShortTool(ev.name, ev.args);
5284
5223
  termLine('t-agent', sid + '▸ ' + ev.name + (args ? ': ' + args : ''));
5285
5224
  } else if (ev.type === 'tool-end') {
5286
- /* mobil önizleme: dev sunucu çıktısı yakala ("Local: http://localhost:8081" vb.) */
5287
- devServerSeen(ev.result);
5288
5225
  const shellish = /bash|shell|powershell|cmd|command|script|terminal/i.test(String(ev.name || ''));
5289
5226
  const out = String(ev.result || '').replace(/\s+$/, '');
5290
5227
  const cap = shellish ? 1600 : 240;
@@ -6091,25 +6028,8 @@ async function init() {
6091
6028
  beast.browserPhone(on).catch(() => {});
6092
6029
  });
6093
6030
  }
6094
- if (els.bbMobile) {
6095
- els.bbMobile.addEventListener('click', () => {
6096
- /* MOBİL ÖNİZLEME: telefon silueti içinde canlı dev-server önizlemesi */
6097
- const on = !document.body.classList.contains('mobile-preview');
6098
- beast.browserMobileSet(on).catch(() => {});
6099
- });
6100
- }
6101
- if (els.bbDevice) {
6102
- els.bbDevice.addEventListener('change', () => {
6103
- beast.browserDeviceSet(els.bbDevice.value).catch(() => {});
6104
- });
6105
- }
6106
6031
  els.bbClose.addEventListener('click', () => {
6107
6032
  document.body.classList.remove('browser-open');
6108
- /* mobil önizleme KESİN kapansın: main tarafı zaten kapatıyor, DOM tarafı da
6109
- beklemeden temizlenir (siluet + cihaz seçici + mod düğmesi) */
6110
- document.body.classList.remove('mobile-preview');
6111
- if (els.bbMobile) els.bbMobile.classList.remove('on');
6112
- renderPhoneFrame(null);
6113
6033
  els.browserBar.hidden = true;
6114
6034
  els.bbResize.hidden = true;
6115
6035
  els.browserBtn.classList.remove('on');
@@ -6967,17 +6887,25 @@ async function setIdeMode(on) {
6967
6887
  if (!on && document.body.classList.contains('browser-open')) {
6968
6888
  try { beast.toggleBrowser(); } catch {}
6969
6889
  }
6970
- /* ALT TERMINAL: yalnız Beast Code'a özgü — Agent/Studio moduna dönüşte kapanır */
6971
- if (!on && termOpen) termSetOpen(false);
6972
6890
  if (on) {
6891
+ /* terminal ALT DOCK'tan KOD BÖLMÜNE taşınır: soldaki yer editör + terminal ortak alanı */
6892
+ ideTermPlace(true);
6973
6893
  ideSplitRestore();
6974
6894
  setEditorHidden(localStorage.getItem('beast.editorHidden') === '1');
6975
- /* BEAST CODE modunda terminal HEP AÇIK mod girilirken otomatik açılır */
6976
- if (!termOpen) termSetOpen(true);
6895
+ /* mod geçişinde bir kez: ajan modundan kalabilecek alt dock payını sıfırla */
6896
+ beast.browserSetBottomInset(0).catch(() => {});
6897
+ /* terminal açıksa bölmeyi o alır; kapalıysa editör pref'ine göre başlar —
6898
+ editör görünürse terminal ⌘ butonuyla (veya editör kapatılınca) açılır */
6899
+ termSetOpen(termOpen ? true : editorHiddenOn());
6977
6900
  await loadIdeTree();
6978
6901
  bcBanner();
6902
+ renderBcHistory(); /* soldaki geçmiş listesi: IDE'ye girişte tazelenir */
6979
6903
  codeGutterRender(); /* dosya açık olmasa bile rakamlar görünür */
6980
6904
  } else {
6905
+ /* terminal bölmeye alınmadan önce kapatılır, sonra ALT DOCK'a geri taşınır */
6906
+ if (termOpen) termSetOpen(false);
6907
+ document.body.classList.remove('term-pane');
6908
+ ideTermPlace(false);
6981
6909
  /* agent moduna dönüş: koşan paralel ajan varsa rail otomatik açılır
6982
6910
  (autoOpened sıfırlanır — Code modundayken başlayan iş için de tetiklensin) */
6983
6911
  agentState.autoOpened = false;
@@ -6985,6 +6913,19 @@ async function setIdeMode(on) {
6985
6913
  }
6986
6914
  }
6987
6915
 
6916
+ /* terminal panelini mode'a göre yerleştir: IDE'de #codePane içine, ajan modunda body altına */
6917
+ function ideTermPlace(inside) {
6918
+ const pane = document.getElementById('codePane');
6919
+ if (!pane || !els.termPanel) return;
6920
+ if (inside && els.termPanel.parentElement !== pane) {
6921
+ pane.appendChild(els.termPanel);
6922
+ if (els.termResize) pane.appendChild(els.termResize);
6923
+ } else if (!inside && els.termPanel.parentElement === pane) {
6924
+ document.body.appendChild(els.termResize);
6925
+ document.body.appendChild(els.termPanel);
6926
+ }
6927
+ }
6928
+
6988
6929
  /* ================= BEAST STUDIO MODU =================
6989
6930
  Beast Code ile AYRI dünya: sol klasör konsolu (başlık: BEAST STUDIO),
6990
6931
  sağ → chat + video bölümü. Oturumlar main tarafında studioRoot bazlı ve
@@ -7155,6 +7096,8 @@ function editorHiddenOn() {
7155
7096
  }
7156
7097
 
7157
7098
  function setEditorHidden(h) {
7099
+ /* paylaşılan bölme: editör açılınca terminal kapanır (IDE modu) */
7100
+ if (!h && ideModeOn() && termOpen) termSetOpen(false);
7158
7101
  document.body.classList.toggle('editor-hidden', !!h);
7159
7102
  if (els.codeShow) els.codeShow.hidden = !h;
7160
7103
  try { localStorage.setItem('beast.editorHidden', h ? '1' : '0'); } catch {}
@@ -7611,6 +7554,8 @@ function codeActivate(i) {
7611
7554
  }
7612
7555
 
7613
7556
  async function codeOpen(rel) {
7557
+ /* dosya açılımı = editör açılır → terminal bölmeyi bırakır (paylaşılan bölme) */
7558
+ if (ideModeOn() && termOpen) termSetOpen(false);
7614
7559
  if (editorHiddenOn()) setEditorHidden(false); /* dosya açılınca editör geri gelir */
7615
7560
  const idx = codeTabs.findIndex((t) => t.rel === rel);
7616
7561
  if (idx >= 0) {
@@ -7806,8 +7751,6 @@ $('#filePreview').addEventListener('click', async () => {
7806
7751
  const r = await beast.idePreview().catch(() => null);
7807
7752
  if (r && r.ok) {
7808
7753
  if (ideModeOn() === false) setIdeMode(true);
7809
- /* mobil proje: npm run web + telefon silueti — kullanıcıya net geri bildirim */
7810
- if (r.mobile) toast('Mobil önizleme: dev sunucu başlatıldı — telefon siluetine bak');
7811
7754
  } else {
7812
7755
  toast((r && r.error) || 'preview açılamadı');
7813
7756
  }
@@ -8137,9 +8080,130 @@ function bcOnFolderChanged(p) {
8137
8080
  bcStreamEl = null;
8138
8081
  bcStreamRaw = '';
8139
8082
  bcBannerDone = false;
8083
+
8140
8084
  bcBanner();
8085
+ renderBcHistory();
8086
+ }
8087
+
8088
+ /* ---------- Beast Code SOHBET GEÇMİŞİ (dosya panelinin alt yarısı) ----------
8089
+ Eski Beast Code oturumları listelenir; tıklanınca panelde açılır ve
8090
+ kaldığı yerden devam edilir. Ana sohbet listesiyle ilgisi yoktur. */
8091
+ let bcHistBusy = false;
8092
+
8093
+ function histWhen(iso) {
8094
+ try {
8095
+ return new Date(iso).toLocaleString('tr-TR', { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' });
8096
+ } catch { return ''; }
8141
8097
  }
8142
8098
 
8099
+ async function renderBcHistory() {
8100
+ const list = els.bcHistList;
8101
+ if (!list || !ideModeOn() || bcHistBusy) return;
8102
+ bcHistBusy = true;
8103
+ try {
8104
+ const r = await beast.bcHistory().catch(() => null);
8105
+ if (!r || !r.ok) return;
8106
+ const items = r.items || [];
8107
+ list.innerHTML = '';
8108
+ if (!items.length) {
8109
+ list.innerHTML = '<div class="bc-hist-empty">Henüz Beast Code oturumu yok — mesaj yazınca burada birikir.</div>';
8110
+ return;
8111
+ }
8112
+ for (const it of items) {
8113
+ const row = document.createElement('div');
8114
+ row.className = 'bc-hist-item' + (it.id === bcSessionId ? ' active' : '');
8115
+ const wsShort = it.ws ? String(it.ws).split(/[\\/]/).filter(Boolean).pop() : '';
8116
+ row.innerHTML =
8117
+ '<span class="bh-dot"></span>' +
8118
+ '<div class="bh-main">' +
8119
+ '<span class="bh-title">' + escapeHtml(it.title || 'Beast Code oturumu') + '</span>' +
8120
+ '<span class="bh-meta">' + escapeHtml((wsShort ? wsShort + ' · ' : '') + histWhen(it.updatedAt) + ' · ' + (it.count || 0) + ' msj') + '</span>' +
8121
+ '</div>' +
8122
+ '<button class="bh-del" title="Bu oturumu sil">&#x00D7;</button>';
8123
+ row.title = (it.ws ? it.ws + '\n' : '') + (it.title || '');
8124
+ row.addEventListener('click', () => { bcOpenHistory(it.id); });
8125
+ const del = row.querySelector('.bh-del');
8126
+ if (del) del.addEventListener('click', (e) => {
8127
+ e.stopPropagation();
8128
+ bcDeleteHistory(it.id, it.title);
8129
+ });
8130
+ list.appendChild(row);
8131
+ }
8132
+ } finally {
8133
+ bcHistBusy = false;
8134
+ }
8135
+ }
8136
+
8137
+ async function bcOpenHistory(id) {
8138
+ if (!id) return;
8139
+ if (bcRunning) { toast('Mesaj sürüyor — önce ■ ile durdur'); return; }
8140
+ const r = await beast.bcOpen(id).catch(() => null);
8141
+ if (!r || !r.ok) { toast((r && r.error) || 'oturum açılamadı'); return; }
8142
+ bcSessionId = r.sessionId;
8143
+ if (els.bcOut) els.bcOut.innerHTML = '';
8144
+ bcTools.clear();
8145
+ bcCloseToolGroup();
8146
+ bcHideTodos();
8147
+ bcFlushStream();
8148
+ bcLine('t-sys', '[eski oturum açıldı · ' + (r.messages ? r.messages.length : 0) + ' mesaj — kaldığın yerden devam edebilirsin]');
8149
+ for (const m of r.messages || []) {
8150
+ if (m.role === 'user') bcLine('t-cmd', 'code> ' + m.text);
8151
+ else bcLine('t-out', m.text);
8152
+ }
8153
+ bcSetBusy(!!r.busy);
8154
+ if (r.busy) bcStatusShow('çalışıyor…');
8155
+ else bcStatusHide();
8156
+ renderBcHistory();
8157
+ }
8158
+
8159
+ /* aktif Beast Code panelini taze başlangıca döndür (oturum silinince) */
8160
+ function bcResetPanel() {
8161
+ bcSessionId = null;
8162
+ bcPending = [];
8163
+ renderBcChips();
8164
+ bcTools.clear();
8165
+ bcCloseToolGroup();
8166
+ bcHideTodos();
8167
+ bcFlushStream();
8168
+ if (els.bcOut) els.bcOut.innerHTML = '';
8169
+ bcSetBusy(false);
8170
+ bcStatusHide();
8171
+ }
8172
+
8173
+ /* TEK oturum silme — onay sorulur */
8174
+ async function bcDeleteHistory(id, title) {
8175
+ if (!id) return;
8176
+ if (!confirm('"' + (title || 'Beast Code oturumu') + '" silinsin mi?\n\nBu işlem geri alınamaz.')) return;
8177
+ const r = await beast.bcDelete(id).catch(() => null);
8178
+ if (!r || !r.ok) { toast((r && r.error) || 'silinemedi'); return; }
8179
+ if (bcSessionId === id) {
8180
+ bcResetPanel();
8181
+ bcLine('t-sys', '[oturum silindi — sonraki mesaj taze oturumda başlar]');
8182
+ }
8183
+ toast('Oturum silindi');
8184
+ renderBcHistory();
8185
+ }
8186
+
8187
+ /* TÜM oturumları sil — onay sorulur; çalışan oturumlar atlanır */
8188
+ if (els.bcHistClear) els.bcHistClear.addEventListener('click', async () => {
8189
+ if (bcHistBusy) return;
8190
+ const r0 = await beast.bcHistory().catch(() => null);
8191
+ const n = r0 && r0.ok ? (r0.items || []).length : 0;
8192
+ if (!n) { toast('Silinecek oturum yok'); return; }
8193
+ if (!confirm(n + ' Beast Code oturumunun TÜMÜ silinsin mi?\n\nBu işlem geri alınamaz.')) return;
8194
+ const r = await beast.bcDeleteAll().catch(() => null);
8195
+ if (!r || !r.ok) { toast((r && r.error) || 'silinemedi'); return; }
8196
+ /* aktif oturum da silindiyse panel tazelensin */
8197
+ const r2 = await beast.bcHistory().catch(() => null);
8198
+ const still = r2 && r2.ok ? (r2.items || []).some((x) => x.id === bcSessionId) : true;
8199
+ if (!still) {
8200
+ bcResetPanel();
8201
+ bcLine('t-sys', '[tüm geçmiş silindi — sonraki mesaj taze oturumda başlar]');
8202
+ }
8203
+ toast(r.deleted + ' oturum silindi' + (r.skipped ? ' · ' + r.skipped + ' çalışıyor (atlandı)' : ''));
8204
+ renderBcHistory();
8205
+ });
8206
+
8143
8207
  function bcSetBusy(v) {
8144
8208
  bcRunning = !!v;
8145
8209
  if (els.bcStop) els.bcStop.hidden = !v;
@@ -8493,6 +8557,7 @@ function bcRunCurrent() {
8493
8557
  bcLine('t-cmd', 'code> ' + (msg || (atts.length ? '[' + atts.length + ' ek]' : '')));
8494
8558
  bcHideTodos(); /* yeni sorgu = eski todo list temizlenir; agent yeniden basacak */
8495
8559
  bcSetBusy(true);
8560
+ const prevSid = bcSessionId;
8496
8561
  /* sürüyor/serbest kararını main'deki gerçek engine.isBusy verir —
8497
8562
  panel bayat kilitli kaldıysa ilk mesajla kendini düzeltir */
8498
8563
  beast.beastcodeSend(msg || '[dosya ekleri]', atts).then((r) => {
@@ -8517,6 +8582,8 @@ function bcRunCurrent() {
8517
8582
  bcSetBusy(false);
8518
8583
  bcLine('t-err', (r && r.error) || 'gönderilemedi');
8519
8584
  }
8585
+ /* yeni oturum açıldıysa soldaki geçmiş listesi tazelensin */
8586
+ if (bcSessionId && bcSessionId !== prevSid) renderBcHistory();
8520
8587
  }).catch((e) => {
8521
8588
  bcSetBusy(false);
8522
8589
  bcLine('t-err', String((e && e.message) || e));
@@ -8561,8 +8628,10 @@ if (els.bcNew) els.bcNew.addEventListener('click', async () => {
8561
8628
  bcFlushStream();
8562
8629
  if (els.bcTitle) els.bcTitle.textContent = 'BEAST CODE';
8563
8630
  bcLine('t-sys', 'yeni oturum — sonraki mesaj taze başlar');
8631
+ renderBcHistory(); /* silinen oturum listeden düşsün */
8564
8632
  }
8565
8633
  });
8634
+ if (els.bcHistRefresh) els.bcHistRefresh.addEventListener('click', () => renderBcHistory());
8566
8635
 
8567
8636
  /* ---------- BEAST STUDIO paneli ----------
8568
8637
  Beast Code panelinin birebir karşılığı — AMA ayrı oturum, ayrı kuyruk,