diff --git a/routes/chat_routes.py b/routes/chat_routes.py index a718d3fbe..9880522c8 100644 --- a/routes/chat_routes.py +++ b/routes/chat_routes.py @@ -452,7 +452,9 @@ def setup_chat_routes( search_context = form_data.get("search_context") # pre-fetched web search results (compare mode) compare_mode = str(form_data.get("compare_mode", "")).lower() == "true" incognito = str(form_data.get("incognito", "")).lower() == "true" - plan_mode = str(form_data.get("plan_mode", "")).lower() == "true" + # Plan mode is not part of the merge-ready UI. Ignore stale clients or + # manual form posts that still send plan_mode=true. + plan_mode = False chat_mode = str(form_data.get("mode", "")).lower() # 'chat' or 'agent' # Workspace: confine the agent's file/shell tools to this folder. Validate # it's a real directory; ignore (no confinement) otherwise. diff --git a/static/app.js b/static/app.js index 8216d6485..20ef1f705 100644 --- a/static/app.js +++ b/static/app.js @@ -1555,7 +1555,6 @@ function initializeEventListeners() { const MODE_TOOLS = [ { btnId: 'web-toggle-btn', checkboxId: 'web-toggle', stateKey: 'web' }, { btnId: 'bash-toggle-btn', checkboxId: 'bash-toggle', stateKey: 'bash' }, - { btnId: 'plan-toggle-btn', checkboxId: 'plan-toggle', stateKey: 'plan' }, ]; function _modeKey(stateKey, mode) { return `${stateKey}_${mode}`; } @@ -1564,9 +1563,6 @@ function initializeEventListeners() { const state = loadToggleState(); const key = _modeKey(stateKey, mode); if (Object.prototype.hasOwnProperty.call(state, key)) return !!state[key]; - // Plan mode is opt-in: never default it on, otherwise every agent turn - // would be forced into planning. - if (stateKey === 'plan') return false; return mode === 'agent'; // default: ON in agent, OFF in chat } @@ -1579,7 +1575,6 @@ function initializeEventListeners() { const TOOL_TOGGLE_TOAST_LABELS = { web: 'Web search', bash: 'Shell', - plan: 'Plan mode', }; function showToolToggleToast(stateKey, active) { @@ -1592,8 +1587,8 @@ function initializeEventListeners() { MODE_TOOLS.forEach(({ btnId, checkboxId, stateKey }) => { const btn = el(btnId); if (!btn) return; - // Hide bash and plan buttons in chat mode - if (mode === 'chat' && (stateKey === 'bash' || stateKey === 'plan')) { + // Hide bash button in chat mode + if (mode === 'chat' && stateKey === 'bash') { btn.style.display = 'none'; return; } @@ -1614,12 +1609,10 @@ function initializeEventListeners() { const state = loadToggleState(); let currentMode = state.mode || 'chat'; - // Immediately hide bash/plan buttons in chat mode on page load + // Immediately hide bash button in chat mode on page load if (currentMode === 'chat') { const bashBtn = el('bash-toggle-btn'); - const planBtn = el('plan-toggle-btn'); if (bashBtn) bashBtn.style.display = 'none'; - if (planBtn) planBtn.style.display = 'none'; } function setMode(mode) { @@ -1710,79 +1703,6 @@ function initializeEventListeners() { setupToggle('web-toggle-btn', 'web-toggle', 'web'); setupToggle('bash-toggle-btn', 'bash-toggle', 'bash'); try { workspaceModule.initWorkspace(); } catch (_) {} - setupToggle('plan-toggle-btn', 'plan-toggle', 'plan'); - - // Set plan mode on/off directly (checkbox + button state + saved pref) WITHOUT - // going through the button's click handler — used by the plan menu and by the - // "Approve & Run" flow. Going through .click() would hit the plan-menu - // intercept below (a stored plan re-opens the menu instead of toggling), which - // is exactly the bug that left approved plans stuck in plan mode. - function _setPlanMode(on) { - const btn = el('plan-toggle-btn'); - const chk = el('plan-toggle'); - const mode = (loadToggleState().mode) || 'chat'; - if (chk) chk.checked = !!on; - if (btn) { btn.classList.toggle('active', !!on); btn.setAttribute('aria-pressed', String(!!on)); } - saveToolPref('plan', mode, !!on); - } - window._setPlanMode = _setPlanMode; - - // ── Plan-button menu ── - // When a plan exists for this chat, clicking the plan button opens a small - // menu (Show plan / Plan mode on-off) instead of plain-toggling — so the plan - // window can be re-opened and docked at any time while the agent works. With - // no plan, the button behaves as before (one-click toggle). - (function initPlanMenu() { - const planBtn = el('plan-toggle-btn'); - if (!planBtn) return; - const _hasPlan = () => { try { return !!(window._getStoredPlan && window._getStoredPlan()); } catch (_) { return false; } }; - const _close = () => { const m = document.getElementById('plan-menu'); if (m) m.remove(); }; - function _open() { - _close(); - const planChk = el('plan-toggle'); - const on = !!(planChk && planChk.checked); - const menu = document.createElement('div'); - menu.id = 'plan-menu'; - menu.className = 'overflow-menu plan-menu'; - menu.innerHTML = - '' - + ''; - document.body.appendChild(menu); - const r = planBtn.getBoundingClientRect(); - menu.style.position = 'fixed'; - menu.style.left = Math.round(r.left) + 'px'; - menu.style.top = Math.round(r.top - menu.offsetHeight - 6) + 'px'; - menu.querySelector('[data-act="show"]').addEventListener('click', () => { - _close(); - const txt = window._getStoredPlan ? window._getStoredPlan() : ''; - if (txt && window.planWindowModule) window.planWindowModule.openPlanWindow(txt, null); - }); - menu.querySelector('[data-act="toggle"]').addEventListener('click', () => { - _close(); - _setPlanMode(!on); // flip state directly (no click → no menu re-open) - }); - // Dismiss on any outside click (capture so it beats other handlers) / Escape. - setTimeout(() => { - const off = (e) => { - if (!menu.contains(e.target) && e.target !== planBtn) { - _close(); document.removeEventListener('click', off, true); document.removeEventListener('keydown', esc, true); - } - }; - const esc = (e) => { if (e.key === 'Escape') { _close(); document.removeEventListener('click', off, true); document.removeEventListener('keydown', esc, true); } }; - document.addEventListener('click', off, true); - document.addEventListener('keydown', esc, true); - }, 0); - } - planBtn.addEventListener('click', (e) => { - // With a stored plan, the button opens the menu (Show plan / toggle). - // Without one, it falls through to the normal one-click toggle. - if (_hasPlan()) { e.preventDefault(); e.stopImmediatePropagation(); _open(); } - }, true); // capture phase: intercept before setupToggle's bubble handler - })(); try { workspaceModule.initWorkspace(); } catch (_) {} diff --git a/static/index.html b/static/index.html index 522129fe9..ec4af199f 100644 --- a/static/index.html +++ b/static/index.html @@ -1084,12 +1084,6 @@ - -