mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-04 22:49:41 +02:00
refactor: simplify respawn controller display and improve CLAUDE.md
Respawn banner changes: - Human-friendly state labels (e.g., "Kickstarting..." vs "waiting_kickstart") - Removed redundant "→ waiting for" text - Simplified AI check display (only shows when actively checking) - Shorter cycle counter (#1 vs "Cycle 1") - Fixed NaN timer bug with validation - Flatter HTML structure CLAUDE.md improvements: - Reorganized Commands section into clear subsections - Test port allocation in table format - Simplified TypeScript config section - Removed duplicate keyboard shortcuts (already in README) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
+56
-52
@@ -917,18 +917,12 @@ class ClaudemanApp {
|
||||
}
|
||||
});
|
||||
|
||||
this.eventSource.addEventListener('respawn:stepSent', (e) => {
|
||||
const data = JSON.parse(e.data);
|
||||
if (data.sessionId === this.activeSessionId) {
|
||||
document.getElementById('respawnStep').textContent = data.input;
|
||||
}
|
||||
this.eventSource.addEventListener('respawn:stepSent', (_e) => {
|
||||
// Step info is shown via state label (e.g., "Sending prompt", "Clearing context")
|
||||
});
|
||||
|
||||
this.eventSource.addEventListener('respawn:autoAcceptSent', (e) => {
|
||||
const data = JSON.parse(e.data);
|
||||
if (data.sessionId === this.activeSessionId) {
|
||||
document.getElementById('respawnStep').textContent = '⏎ Auto-accepted plan';
|
||||
}
|
||||
const session = this.sessions.get(data.sessionId);
|
||||
this.notificationManager?.notify({
|
||||
urgency: 'info',
|
||||
@@ -950,34 +944,20 @@ class ClaudemanApp {
|
||||
}
|
||||
});
|
||||
|
||||
this.eventSource.addEventListener('respawn:aiCheckStarted', (e) => {
|
||||
const data = JSON.parse(e.data);
|
||||
if (data.sessionId === this.activeSessionId) {
|
||||
document.getElementById('respawnStep').textContent = 'AI Check: Analyzing...';
|
||||
}
|
||||
this.eventSource.addEventListener('respawn:aiCheckStarted', (_e) => {
|
||||
// AI check status shown via updateDetectionDisplay
|
||||
});
|
||||
|
||||
this.eventSource.addEventListener('respawn:aiCheckCompleted', (e) => {
|
||||
const data = JSON.parse(e.data);
|
||||
if (data.sessionId === this.activeSessionId) {
|
||||
const icon = data.verdict === 'IDLE' ? '✓' : '⏳';
|
||||
document.getElementById('respawnStep').textContent = `AI Check: ${data.verdict} ${icon}`;
|
||||
}
|
||||
this.eventSource.addEventListener('respawn:aiCheckCompleted', (_e) => {
|
||||
// AI check status shown via updateDetectionDisplay
|
||||
});
|
||||
|
||||
this.eventSource.addEventListener('respawn:aiCheckFailed', (e) => {
|
||||
const data = JSON.parse(e.data);
|
||||
if (data.sessionId === this.activeSessionId) {
|
||||
document.getElementById('respawnStep').textContent = `AI Check: Error - ${data.error?.substring(0, 50)}`;
|
||||
}
|
||||
this.eventSource.addEventListener('respawn:aiCheckFailed', (_e) => {
|
||||
// AI check status shown via updateDetectionDisplay
|
||||
});
|
||||
|
||||
this.eventSource.addEventListener('respawn:aiCheckCooldown', (e) => {
|
||||
const data = JSON.parse(e.data);
|
||||
if (data.sessionId === this.activeSessionId && data.active) {
|
||||
const remaining = Math.ceil((data.endsAt - Date.now()) / 1000);
|
||||
document.getElementById('respawnStep').textContent = `AI Check: WORKING (cooldown ${remaining}s)`;
|
||||
}
|
||||
this.eventSource.addEventListener('respawn:aiCheckCooldown', (_e) => {
|
||||
// AI check status shown via updateDetectionDisplay
|
||||
});
|
||||
|
||||
// Respawn run timer events (timed respawn runs)
|
||||
@@ -1981,8 +1961,28 @@ class ClaudemanApp {
|
||||
this.hideRespawnTimer();
|
||||
}
|
||||
|
||||
// Human-friendly state labels
|
||||
getStateLabel(state) {
|
||||
const labels = {
|
||||
'stopped': 'Stopped',
|
||||
'watching': 'Watching',
|
||||
'confirming_idle': 'Confirming idle',
|
||||
'ai_checking': 'AI checking',
|
||||
'sending_update': 'Sending prompt',
|
||||
'waiting_update': 'Running prompt',
|
||||
'sending_clear': 'Clearing context',
|
||||
'waiting_clear': 'Clearing...',
|
||||
'sending_init': 'Initializing',
|
||||
'waiting_init': 'Initializing...',
|
||||
'monitoring_init': 'Waiting for work',
|
||||
'sending_kickstart': 'Kickstarting',
|
||||
'waiting_kickstart': 'Kickstarting...',
|
||||
};
|
||||
return labels[state] || state.replace(/_/g, ' ');
|
||||
}
|
||||
|
||||
updateRespawnBanner(state) {
|
||||
this.$('respawnState').textContent = state.replace(/_/g, ' ');
|
||||
this.$('respawnState').textContent = this.getStateLabel(state);
|
||||
}
|
||||
|
||||
updateDetectionDisplay(detection) {
|
||||
@@ -1991,50 +1991,48 @@ class ClaudemanApp {
|
||||
const statusEl = this.$('detectionStatus');
|
||||
const waitingEl = this.$('detectionWaiting');
|
||||
const confidenceEl = this.$('detectionConfidence');
|
||||
const aiCheckEl = document.getElementById('detectionAiCheck');
|
||||
|
||||
// Update status text
|
||||
statusEl.textContent = detection.statusText || '';
|
||||
|
||||
// Update waiting for text
|
||||
if (detection.waitingFor) {
|
||||
waitingEl.textContent = `→ ${detection.waitingFor}`;
|
||||
// Simplified status - only show when meaningful
|
||||
if (detection.statusText && detection.statusText !== 'Watching...') {
|
||||
statusEl.textContent = detection.statusText;
|
||||
statusEl.style.display = '';
|
||||
} else {
|
||||
waitingEl.textContent = '';
|
||||
statusEl.style.display = 'none';
|
||||
}
|
||||
|
||||
// Update confidence level
|
||||
// Hide "waiting for" text - it's redundant with the state label
|
||||
waitingEl.style.display = 'none';
|
||||
|
||||
// Show confidence only when confirming (>0%)
|
||||
const confidence = detection.confidenceLevel || 0;
|
||||
if (confidence > 0) {
|
||||
confidenceEl.textContent = `${confidence}%`;
|
||||
confidenceEl.style.display = '';
|
||||
confidenceEl.className = 'detection-confidence';
|
||||
if (confidence >= 60) {
|
||||
confidenceEl.classList.add('high');
|
||||
} else if (confidence >= 30) {
|
||||
confidenceEl.classList.add('medium');
|
||||
}
|
||||
if (confidence >= 60) confidenceEl.classList.add('high');
|
||||
else if (confidence >= 30) confidenceEl.classList.add('medium');
|
||||
} else {
|
||||
confidenceEl.style.display = 'none';
|
||||
}
|
||||
|
||||
// Show AI check info if available
|
||||
const aiCheckEl = document.getElementById('detectionAiCheck');
|
||||
// Simplified AI check display
|
||||
if (aiCheckEl && detection.aiCheck) {
|
||||
const ai = detection.aiCheck;
|
||||
let aiText = '';
|
||||
if (ai.status === 'checking') {
|
||||
aiText = 'AI: Analyzing...';
|
||||
aiText = 'AI analyzing...';
|
||||
} else if (ai.status === 'cooldown' && ai.cooldownEndsAt) {
|
||||
const remaining = Math.ceil((ai.cooldownEndsAt - Date.now()) / 1000);
|
||||
aiText = `AI: WORKING (${remaining}s cooldown)`;
|
||||
if (remaining > 0) aiText = `Cooldown ${remaining}s`;
|
||||
} else if (ai.status === 'disabled') {
|
||||
aiText = `AI: Disabled (${ai.disabledReason || 'errors'})`;
|
||||
} else if (ai.lastVerdict) {
|
||||
aiText = `AI: Last=${ai.lastVerdict}`;
|
||||
if (ai.lastCheckDurationMs) aiText += ` (${Math.round(ai.lastCheckDurationMs / 1000)}s)`;
|
||||
aiText = 'AI disabled';
|
||||
}
|
||||
// Don't show "last verdict" - it's noise
|
||||
aiCheckEl.textContent = aiText;
|
||||
aiCheckEl.style.display = aiText ? '' : 'none';
|
||||
} else if (aiCheckEl) {
|
||||
aiCheckEl.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2062,6 +2060,12 @@ class ClaudemanApp {
|
||||
}
|
||||
|
||||
const timer = this.respawnTimers[this.activeSessionId];
|
||||
// Guard against invalid timer data
|
||||
if (!timer.endAt || isNaN(timer.endAt)) {
|
||||
this.hideRespawnTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
const now = Date.now();
|
||||
const remaining = Math.max(0, timer.endAt - now);
|
||||
|
||||
|
||||
@@ -70,25 +70,19 @@
|
||||
<div class="respawn-banner-row">
|
||||
<span class="respawn-indicator">↻</span>
|
||||
<span class="respawn-state" id="respawnState">Watching</span>
|
||||
<span class="respawn-detection" id="respawnDetection">
|
||||
<span class="detection-status" id="detectionStatus"></span>
|
||||
<span class="detection-waiting" id="detectionWaiting"></span>
|
||||
<span class="detection-confidence" id="detectionConfidence"></span>
|
||||
<span class="detection-ai-check" id="detectionAiCheck" style="display: none;"></span>
|
||||
</span>
|
||||
<span class="respawn-cycles">Cycle <span id="respawnCycleCount">0</span></span>
|
||||
<span class="detection-status" id="detectionStatus"></span>
|
||||
<span class="detection-waiting" id="detectionWaiting" style="display: none;"></span>
|
||||
<span class="detection-confidence" id="detectionConfidence"></span>
|
||||
<span class="detection-ai-check" id="detectionAiCheck" style="display: none;"></span>
|
||||
<span class="respawn-spacer"></span>
|
||||
<span class="respawn-cycles">#<span id="respawnCycleCount">0</span></span>
|
||||
<span class="respawn-timer" id="respawnTimer" style="display: none;"></span>
|
||||
<span class="respawn-tokens" id="respawnTokens" style="display: none;"></span>
|
||||
<span class="respawn-step" id="respawnStep"></span>
|
||||
<button class="btn-icon-only" onclick="app.stopRespawn()" title="Stop Respawn">■</button>
|
||||
</div>
|
||||
<div class="respawn-timers-row" id="respawnTimersRow" style="display: none;">
|
||||
<div class="respawn-countdown-timers" id="respawnCountdownTimers">
|
||||
<!-- Dynamically populated countdown timers -->
|
||||
</div>
|
||||
<div class="respawn-action-log" id="respawnActionLog">
|
||||
<!-- Recent actions scrolling list -->
|
||||
</div>
|
||||
<div class="respawn-countdown-timers" id="respawnCountdownTimers"></div>
|
||||
<div class="respawn-action-log" id="respawnActionLog"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -568,20 +568,16 @@ body {
|
||||
.respawn-state {
|
||||
color: var(--green);
|
||||
font-weight: 500;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.respawn-spacer {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.respawn-cycles {
|
||||
color: var(--text-dim);
|
||||
}
|
||||
|
||||
.respawn-step {
|
||||
flex: 1;
|
||||
color: var(--text-muted);
|
||||
font-family: monospace;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-family: 'SF Mono', Monaco, monospace;
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
.respawn-timer {
|
||||
@@ -599,23 +595,14 @@ body {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
.respawn-detection {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0 0.5rem;
|
||||
border-left: 1px solid rgba(34, 197, 94, 0.2);
|
||||
}
|
||||
|
||||
.detection-status {
|
||||
color: var(--text-muted);
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
.detection-waiting {
|
||||
.detection-ai-check {
|
||||
color: var(--accent);
|
||||
font-size: 0.7rem;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.detection-confidence {
|
||||
|
||||
Reference in New Issue
Block a user