mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-15 17:25:26 -04:00
Remove remaining plan mode frontend code
This commit is contained in:
@@ -13,7 +13,6 @@ import chatStream from './chatStream.js';
|
||||
import { addAITTSButton } from './tts-ai.js';
|
||||
import markdownModule from './markdown.js';
|
||||
import { svgifyEmoji } from './markdown.js';
|
||||
import planWindowModule from './planWindow.js';
|
||||
import spinnerModule from './spinner.js';
|
||||
import presetsModule from './presets.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 _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 _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. */
|
||||
function hasActiveStream(sessionId) {
|
||||
@@ -839,22 +809,6 @@ import { wireArrowUpRecall, getLastUserMessageFromChatHistory } from './composer
|
||||
if (el('bash-toggle').checked) {
|
||||
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');
|
||||
if (ragChk && !ragChk.checked) {
|
||||
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)
|
||||
const footerTarget = (roundHolder && roundHolder !== holder && roundHolder.style.display !== 'none') ? roundHolder : holder;
|
||||
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
|
||||
if (_researchingStreamIds.has(streamSessionId)) {
|
||||
_appendViewReportLink(footerTarget, streamSessionId);
|
||||
|
||||
@@ -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 & 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 };
|
||||
@@ -24,8 +24,7 @@ export const KEYS = {
|
||||
SECTION_ORDER: 'sidebar-section-order',
|
||||
ADMIN_LAST_TAB: 'admin-last-tab',
|
||||
DENSITY: 'odysseus-density',
|
||||
WORKSPACE: 'odysseus-workspace',
|
||||
PLAN: 'odysseus-plan'
|
||||
WORKSPACE: 'odysseus-workspace'
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+1
-42
@@ -2307,48 +2307,7 @@ body.bg-pattern-sparkles {
|
||||
color: var(--fg);
|
||||
background: color-mix(in srgb, var(--fg) 9%, transparent);
|
||||
}
|
||||
/* Plan mode: "Approve & Run" affordance under a proposed plan */
|
||||
.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 */
|
||||
/* GitHub-style task lists (- [ ] / - [x]) */
|
||||
li.task-item {
|
||||
list-style: none;
|
||||
margin-left: -1.2em;
|
||||
|
||||
Reference in New Issue
Block a user