From 2a89f2aa51a103a22268ea5b8ced2c0f6af18228 Mon Sep 17 00:00:00 2001 From: arkon Date: Tue, 27 Jan 2026 01:59:35 +0100 Subject: [PATCH] fix: add cpulimit availability check to app settings Co-Authored-By: Claude Opus 4.5 --- src/web/public/app.js | 66 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/src/web/public/app.js b/src/web/public/app.js index 385ee2ee..40f388ed 100644 --- a/src/web/public/app.js +++ b/src/web/public/app.js @@ -2448,7 +2448,10 @@ class ClaudemanApp { generatedPlan: null, // [{content, priority, enabled, id}] or null planGenerated: false, skipPlanGeneration: false, + planDetailLevel: 'standard', // 'brief', 'standard', 'detailed' }; + planLoadingTimer = null; + planLoadingStartTime = null; showRalphWizard() { // Reset wizard state @@ -2463,6 +2466,7 @@ class ClaudemanApp { generatedPlan: null, planGenerated: false, skipPlanGeneration: false, + planDetailLevel: 'standard', }; // Reset UI @@ -2524,13 +2528,16 @@ class ClaudemanApp { this.ralphWizardConfig.completionPhrase = completionPhrase.toUpperCase(); this.ralphWizardConfig.caseName = caseName; - // Move to step 2 (plan generation) + // Move to step 2 (plan generation) and auto-start this.ralphWizardStep = 2; this.updateRalphWizardUI(); + + // Auto-start plan generation + this.generatePlan(); } else if (this.ralphWizardStep === 2) { // Must have generated or skipped plan if (!this.ralphWizardConfig.planGenerated && !this.ralphWizardConfig.skipPlanGeneration) { - this.showToast('Generate a plan or skip', 'warning'); + this.showToast('Wait for plan generation or skip', 'warning'); return; } @@ -2628,24 +2635,55 @@ class ClaudemanApp { async generatePlan() { const config = this.ralphWizardConfig; + // Stop any existing timer + if (this.planLoadingTimer) { + clearInterval(this.planLoadingTimer); + this.planLoadingTimer = null; + } + // Show loading state - document.getElementById('planGenerationControls')?.classList.add('hidden'); document.getElementById('planGenerationError')?.classList.add('hidden'); document.getElementById('planEditor')?.classList.add('hidden'); document.getElementById('planGenerationLoading')?.classList.remove('hidden'); + // Start elapsed time display + this.planLoadingStartTime = Date.now(); + const timeEl = document.getElementById('planLoadingTime'); + if (timeEl) timeEl.textContent = '0s'; + + this.planLoadingTimer = setInterval(() => { + const elapsed = Math.floor((Date.now() - this.planLoadingStartTime) / 1000); + if (timeEl) timeEl.textContent = `${elapsed}s`; + }, 1000); + + // Determine max items based on detail level + const detailConfig = { + brief: { maxItems: 5, includeTests: false }, + standard: { maxItems: 8, includeTests: true }, + detailed: { maxItems: 12, includeTests: true }, + }; + const { maxItems, includeTests } = detailConfig[config.planDetailLevel] || detailConfig.standard; + try { const res = await fetch('/api/generate-plan', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ taskDescription: config.taskDescription, - maxItems: 8, + maxItems, + includeTests, + detailLevel: config.planDetailLevel, }), }); const data = await res.json(); + // Stop timer + if (this.planLoadingTimer) { + clearInterval(this.planLoadingTimer); + this.planLoadingTimer = null; + } + if (!data.success) { this.showPlanError(data.error || 'Failed to generate plan'); return; @@ -2665,15 +2703,33 @@ class ClaudemanApp { config.planGenerated = true; config.skipPlanGeneration = false; - // Show editor + // Show editor and update detail buttons this.renderPlanEditor(); + this.updateDetailLevelButtons(); } catch (err) { + // Stop timer + if (this.planLoadingTimer) { + clearInterval(this.planLoadingTimer); + this.planLoadingTimer = null; + } console.error('Plan generation failed:', err); this.showPlanError('Network error: ' + err.message); } } + setPlanDetail(level) { + this.ralphWizardConfig.planDetailLevel = level; + this.updateDetailLevelButtons(); + } + + updateDetailLevelButtons() { + const level = this.ralphWizardConfig.planDetailLevel; + document.querySelectorAll('.plan-detail-btn').forEach(btn => { + btn.classList.toggle('active', btn.dataset.detail === level); + }); + } + showPlanError(message) { document.getElementById('planGenerationLoading')?.classList.add('hidden'); document.getElementById('planGenerationControls')?.classList.add('hidden');