Remove remaining plan mode frontend code

This commit is contained in:
pewdiepie-archdaemon
2026-06-09 09:44:22 +09:00
parent 2a2a93d845
commit 646f8bd2a9
4 changed files with 2 additions and 224 deletions
-101
View File
@@ -13,7 +13,6 @@ import chatStream from './chatStream.js';
import { addAITTSButton } from './tts-ai.js'; import { addAITTSButton } from './tts-ai.js';
import markdownModule from './markdown.js'; import markdownModule from './markdown.js';
import { svgifyEmoji } from './markdown.js'; import { svgifyEmoji } from './markdown.js';
import planWindowModule from './planWindow.js';
import spinnerModule from './spinner.js'; import spinnerModule from './spinner.js';
import presetsModule from './presets.js'; import presetsModule from './presets.js';
import fileHandlerModule from './fileHandler.js'; import fileHandlerModule from './fileHandler.js';
@@ -111,35 +110,6 @@ import { wireArrowUpRecall, getLastUserMessageFromChatHistory } from './composer
let _streamSessionId = null; // Session ID for the currently active reader loop let _streamSessionId = null; // Session ID for the currently active reader loop
let _lastReaderActivity = 0; // Timestamp of last reader.read() success — used to detect frozen streams let _lastReaderActivity = 0; // Timestamp of last reader.read() success — used to detect frozen streams
let _webLockRelease = null; // Function to release the Web Lock held during streaming let _webLockRelease = null; // Function to release the Web Lock held during streaming
let _forcePlanOff = false; // One-shot: suppress plan_mode for the next send (Approve & Run)
// ── Plan store: the latest proposed/approved checklist for the CURRENT chat ──
// Kept so (a) it can be sent back each turn and pinned in context (a long plan
// on a weak model survives history truncation), and (b) the plan window can be
// re-opened/docked at any time via the plan-button menu. Stored per session in
// localStorage so it survives a reload mid-execution.
function _setStoredPlan(text) {
const sid = sessionModule.getCurrentSessionId();
if (!sid || !text || !text.trim()) return;
Storage.setJSON(Storage.KEYS.PLAN, { sid, text });
// Live-refresh the plan window if it's open (shows progress as the agent
// restates the checklist with [x]).
try {
if (planWindowModule.isPlanWindowOpen && planWindowModule.isPlanWindowOpen()) {
planWindowModule.openPlanWindow(text, null);
}
} catch (_) {}
}
function _getStoredPlan() {
const sid = sessionModule.getCurrentSessionId();
const rec = Storage.getJSON(Storage.KEYS.PLAN, null);
return (rec && rec.sid === sid && rec.text) ? rec.text : '';
}
// A line like "- [ ] step" / "- [x] step" marks a GitHub-style checklist.
const _CHECKLIST_RE = /^\s*[-*]\s+\[[ xX]\]\s+/m;
// Exposed for app.js (plan-button menu) — re-open the stored plan window.
window._getStoredPlan = _getStoredPlan;
window.planWindowModule = planWindowModule;
/** Check if an SSE reader is still actively connected for a session. */ /** Check if an SSE reader is still actively connected for a session. */
function hasActiveStream(sessionId) { function hasActiveStream(sessionId) {
@@ -839,22 +809,6 @@ import { wireArrowUpRecall, getLastUserMessageFromChatHistory } from './composer
if (el('bash-toggle').checked) { if (el('bash-toggle').checked) {
fd.append('allow_bash', 'true'); fd.append('allow_bash', 'true');
} }
// Plan mode: agent investigates read-only and proposes a plan to approve.
// Only meaningful in agent mode, and never alongside deep research.
// _forcePlanOff is a one-shot set by "Approve & Run" so the execution turn
// runs with full tools even though the Plan toggle is still on.
const _planToggle = el('plan-toggle');
const planTurn = !_forcePlanOff && isAgentMode && _planToggle && _planToggle.checked && !el('research-toggle').checked;
_forcePlanOff = false;
if (planTurn) {
fd.append('plan_mode', 'true');
fd.set('mode', 'agent');
} else if (isAgentMode) {
// Executing (not proposing): send the stored plan back so the backend
// pins it in context and the agent can always re-reference it.
const _sp = _getStoredPlan();
if (_sp) fd.append('approved_plan', _sp);
}
const ragChk = el('rag-toggle'); const ragChk = el('rag-toggle');
if (ragChk && !ragChk.checked) { if (ragChk && !ragChk.checked) {
fd.append('use_rag', 'false'); fd.append('use_rag', 'false');
@@ -2770,61 +2724,6 @@ import { wireArrowUpRecall, getLastUserMessageFromChatHistory } from './composer
// Attach footer to the last visible bubble (roundHolder for multi-round agent, holder for single) // Attach footer to the last visible bubble (roundHolder for multi-round agent, holder for single)
const footerTarget = (roundHolder && roundHolder !== holder && roundHolder.style.display !== 'none') ? roundHolder : holder; const footerTarget = (roundHolder && roundHolder !== holder && roundHolder.style.display !== 'none') ? roundHolder : holder;
footerTarget.appendChild(createMsgFooter(footerTarget)); footerTarget.appendChild(createMsgFooter(footerTarget));
// Capture any checklist this message produced as the current plan — both
// the initial proposal AND restated progress during execution. Keeps the
// stored plan (and the docked plan window) in sync with the latest state.
if (accumulated && _CHECKLIST_RE.test(accumulated)) {
_setStoredPlan(accumulated);
}
// Plan mode: the agent has proposed a plan — offer to approve & execute it.
// Approving re-sends with plan_mode suppressed (full tools) for one turn.
if (planTurn && accumulated.trim()) {
const _planText = accumulated;
const _runApproved = () => {
_approveWrap.remove();
_forcePlanOff = true;
// Persist the approved plan for THIS chat so it's (a) re-sent and
// pinned in context every execution turn, and (b) re-openable via the
// plan-button menu. Do this BEFORE flipping the toggle, since the menu
// intercept keys off a stored plan existing.
_setStoredPlan(_planText);
// Approving exits plan mode for good — turn it OFF directly (NOT via
// the button's click, which would now open the plan menu instead of
// toggling) so execution and every follow-up keep full write tools.
try { if (window._setPlanMode) window._setPlanMode(false); } catch (_) {}
const _inp = el('message');
if (_inp) {
_inp.value = 'Approved — execute the plan. The full approved checklist is pinned '
+ 'for you under "## ACTIVE PLAN"; do NOT go looking for it in tasks, notes, or '
+ 'memory. Work through it in order, and after each step call the update_plan tool '
+ 'with the full checklist and that step marked `- [x]`. Do the next unchecked item '
+ 'until all are done.';
_inp.dispatchEvent(new Event('input'));
}
// Show a clean bubble; the full instruction still goes to the model.
_displayOverride = 'Approved the plan.';
handleChatSubmit({ preventDefault() {} });
};
var _approveWrap = document.createElement('div');
_approveWrap.className = 'plan-approve-bar';
const _approveBtn = document.createElement('button');
_approveBtn.type = 'button';
_approveBtn.className = 'plan-approve-btn';
_approveBtn.textContent = 'Approve & Run';
_approveBtn.addEventListener('click', _runApproved);
// Open the plan in a draggable, side-dockable window (reuses the
// shared modal framework). Approving from the window runs it too.
const _openBtn = document.createElement('button');
_openBtn.type = 'button';
_openBtn.className = 'plan-open-btn';
_openBtn.textContent = 'Open in window';
_openBtn.addEventListener('click', () => {
planWindowModule.openPlanWindow(_planText, _runApproved);
});
_approveWrap.appendChild(_approveBtn);
_approveWrap.appendChild(_openBtn);
footerTarget.appendChild(_approveWrap);
}
// Add "View Report" link for completed research // Add "View Report" link for completed research
if (_researchingStreamIds.has(streamSessionId)) { if (_researchingStreamIds.has(streamSessionId)) {
_appendViewReportLink(footerTarget, streamSessionId); _appendViewReportLink(footerTarget, streamSessionId);
-79
View File
@@ -1,79 +0,0 @@
// static/js/planWindow.js
//
// Plan mode: show a proposed plan in a draggable, side-dockable window —
// reusing the same modal + makeWindowDraggable framework the calendar, email,
// and document panels use. Approving from here runs the plan with full tools.
import uiModule from './ui.js';
import markdownModule from './markdown.js';
import { makeWindowDraggable } from './windowDrag.js';
let _modal = null;
let _onApprove = null;
function _getModal() {
if (_modal) return _modal;
_modal = document.createElement('div');
_modal.id = 'plan-window';
_modal.className = 'modal';
_modal.style.display = 'none';
_modal.innerHTML = `
<div class="modal-content plan-window-content">
<div class="modal-header">
<h4><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:6px"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg><span id="plan-window-title">Proposed plan</span></h4>
<button class="close-btn" id="plan-window-close">✖</button>
</div>
<div class="modal-body plan-window-body" id="plan-window-body"></div>
<div class="modal-footer plan-window-footer">
<button type="button" class="plan-approve-btn" id="plan-window-approve">Approve &amp; Run</button>
</div>
</div>`;
document.body.appendChild(_modal);
_modal.querySelector('#plan-window-close').addEventListener('click', closePlanWindow);
_modal.querySelector('#plan-window-approve').addEventListener('click', () => {
const cb = _onApprove;
closePlanWindow();
if (typeof cb === 'function') cb();
});
// Draggable + side-dockable, same one-call helper as the other windows.
const content = _modal.querySelector('.modal-content');
const header = _modal.querySelector('.modal-header');
if (content && header) makeWindowDraggable(_modal, { content, header });
return _modal;
}
/**
* Open the plan window with rendered markdown and an approve callback.
* @param {string} planMarkdown - the agent's proposed plan (raw markdown)
* @param {Function} onApprove - called when the user clicks Approve & Run
*/
export function openPlanWindow(planMarkdown, onApprove) {
const modal = _getModal();
_onApprove = onApprove || null;
const body = modal.querySelector('#plan-window-body');
if (body) {
body.innerHTML = markdownModule.processWithThinking(
markdownModule.squashOutsideCode(planMarkdown || '')
);
if (window.hljs) body.querySelectorAll('pre code').forEach((b) => window.hljs.highlightElement(b));
}
const approveBtn = modal.querySelector('#plan-window-approve');
if (approveBtn) approveBtn.style.display = onApprove ? '' : 'none';
// Title reflects state: still awaiting approval (approve callback present) vs
// already approved and being executed.
const title = modal.querySelector('#plan-window-title');
if (title) title.textContent = onApprove ? 'Proposed plan' : 'Approved plan';
modal.style.display = 'flex';
if (uiModule && uiModule.scrollHistory) { try { uiModule.scrollHistory(); } catch (_) {} }
}
export function closePlanWindow() {
if (_modal) _modal.style.display = 'none';
}
/** True when the plan window is currently visible (for live-refresh on progress). */
export function isPlanWindowOpen() {
return !!(_modal && _modal.style.display !== 'none');
}
export default { openPlanWindow, closePlanWindow, isPlanWindowOpen };
+1 -2
View File
@@ -24,8 +24,7 @@ export const KEYS = {
SECTION_ORDER: 'sidebar-section-order', SECTION_ORDER: 'sidebar-section-order',
ADMIN_LAST_TAB: 'admin-last-tab', ADMIN_LAST_TAB: 'admin-last-tab',
DENSITY: 'odysseus-density', DENSITY: 'odysseus-density',
WORKSPACE: 'odysseus-workspace', WORKSPACE: 'odysseus-workspace'
PLAN: 'odysseus-plan'
}; };
/** /**
+1 -42
View File
@@ -2307,48 +2307,7 @@ body.bg-pattern-sparkles {
color: var(--fg); color: var(--fg);
background: color-mix(in srgb, var(--fg) 9%, transparent); background: color-mix(in srgb, var(--fg) 9%, transparent);
} }
/* Plan mode: "Approve & Run" affordance under a proposed plan */ /* GitHub-style task lists (- [ ] / - [x]) */
.plan-approve-bar {
margin: 8px 0 2px;
}
.plan-approve-btn {
font: inherit;
font-size: 13px;
font-weight: 600;
padding: 6px 14px;
border-radius: 8px;
cursor: pointer;
color: var(--accent);
background: color-mix(in srgb, var(--accent) 12%, transparent);
border: 1px solid var(--accent);
transition: background 0.15s, transform 0.1s;
}
.plan-approve-btn:hover {
background: color-mix(in srgb, var(--accent) 22%, transparent);
}
.plan-approve-btn:active {
transform: scale(0.97);
}
.plan-approve-bar {
display: flex;
gap: 8px;
align-items: center;
}
.plan-open-btn {
font: inherit;
font-size: 13px;
padding: 6px 12px;
border-radius: 8px;
cursor: pointer;
color: var(--fg);
background: color-mix(in srgb, var(--fg) 8%, transparent);
border: 1px solid color-mix(in srgb, var(--fg) 22%, transparent);
transition: background 0.15s;
}
.plan-open-btn:hover {
background: color-mix(in srgb, var(--fg) 15%, transparent);
}
/* GitHub-style task lists (- [ ] / - [x]) — used by plan-mode checklists */
li.task-item { li.task-item {
list-style: none; list-style: none;
margin-left: -1.2em; margin-left: -1.2em;