fix: use writeViaScreen for all programmatic console input

- Auto-compact now uses writeViaScreen with \r
- Auto-clear now uses writeViaScreen with \r
- Standardized respawn controller to use \r consistently
- Removed session name input from options modal (use right-click to rename)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
arkon
2026-01-19 16:39:45 +01:00
co-authored by Claude Opus 4.5
parent 448e975dc1
commit 085b78c5e3
4 changed files with 10 additions and 42 deletions
+3 -3
View File
@@ -416,7 +416,7 @@ export class RespawnController extends EventEmitter {
this.terminalBuffer = ''; // Clear buffer for fresh detection this.terminalBuffer = ''; // Clear buffer for fresh detection
this.stepTimer = setTimeout(() => { this.stepTimer = setTimeout(() => {
const input = this.config.updatePrompt + '\r\n'; // CRLF for screen + Claude CLI const input = this.config.updatePrompt + '\r'; // \r triggers Enter in Ink/Claude CLI
this.log(`Sending update prompt: "${this.config.updatePrompt}"`); this.log(`Sending update prompt: "${this.config.updatePrompt}"`);
this.session.writeViaScreen(input); this.session.writeViaScreen(input);
this.emit('stepSent', 'update', this.config.updatePrompt); this.emit('stepSent', 'update', this.config.updatePrompt);
@@ -432,7 +432,7 @@ export class RespawnController extends EventEmitter {
this.stepTimer = setTimeout(() => { this.stepTimer = setTimeout(() => {
this.log('Sending /clear'); this.log('Sending /clear');
this.session.writeViaScreen('/clear\r\n'); // CRLF for screen + Claude CLI this.session.writeViaScreen('/clear\r'); // \r triggers Enter in Ink/Claude CLI
this.emit('stepSent', 'clear', '/clear'); this.emit('stepSent', 'clear', '/clear');
this.setState('waiting_clear'); this.setState('waiting_clear');
this.promptDetected = false; this.promptDetected = false;
@@ -445,7 +445,7 @@ export class RespawnController extends EventEmitter {
this.stepTimer = setTimeout(() => { this.stepTimer = setTimeout(() => {
this.log('Sending /init'); this.log('Sending /init');
this.session.writeViaScreen('/init\r\n'); // CRLF for screen + Claude CLI this.session.writeViaScreen('/init\r'); // \r triggers Enter in Ink/Claude CLI
this.emit('stepSent', 'init', '/init'); this.emit('stepSent', 'init', '/init');
this.setState('waiting_init'); this.setState('waiting_init');
this.promptDetected = false; this.promptDetected = false;
+4 -4
View File
@@ -839,9 +839,9 @@ export class Session extends EventEmitter {
if (!this._isWorking) { if (!this._isWorking) {
// Send /compact command with optional prompt // Send /compact command with optional prompt
const compactCmd = this._autoCompactPrompt const compactCmd = this._autoCompactPrompt
? `/compact ${this._autoCompactPrompt}\n` ? `/compact ${this._autoCompactPrompt}\r`
: '/compact\n'; : '/compact\r';
this.write(compactCmd); this.writeViaScreen(compactCmd);
this.emit('autoCompact', { this.emit('autoCompact', {
tokens: totalTokens, tokens: totalTokens,
threshold: this._autoCompactThreshold, threshold: this._autoCompactThreshold,
@@ -876,7 +876,7 @@ export class Session extends EventEmitter {
const checkAndClear = () => { const checkAndClear = () => {
if (!this._isWorking) { if (!this._isWorking) {
// Send /clear command // Send /clear command
this.write('/clear\n'); this.writeViaScreen('/clear\r');
// Reset token counts // Reset token counts
this._totalInputTokens = 0; this._totalInputTokens = 0;
this._totalOutputTokens = 0; this._totalOutputTokens = 0;
+3 -29
View File
@@ -1275,8 +1275,6 @@ class ClaudemanApp {
this.editingSessionId = sessionId; this.editingSessionId = sessionId;
document.getElementById('sessionNameInput').value = session.name || '';
// Update respawn status display and buttons // Update respawn status display and buttons
const respawnStatus = document.getElementById('sessionRespawnStatus'); const respawnStatus = document.getElementById('sessionRespawnStatus');
const enableBtn = document.getElementById('modalEnableRespawnBtn'); const enableBtn = document.getElementById('modalEnableRespawnBtn');
@@ -1307,9 +1305,6 @@ class ClaudemanApp {
this.selectDurationPreset(''); this.selectDurationPreset('');
document.getElementById('sessionOptionsModal').classList.add('active'); document.getElementById('sessionOptionsModal').classList.add('active');
// Focus the name input
setTimeout(() => document.getElementById('sessionNameInput').focus(), 100);
} }
// Handle duration preset selection // Handle duration preset selection
@@ -1464,30 +1459,9 @@ class ClaudemanApp {
document.getElementById('sessionOptionsModal').classList.remove('active'); document.getElementById('sessionOptionsModal').classList.remove('active');
} }
async saveSessionOptions() { saveSessionOptions() {
if (!this.editingSessionId) return; // Session options are applied immediately via individual controls
// This just closes the modal
const session = this.sessions.get(this.editingSessionId);
const newName = document.getElementById('sessionNameInput').value.trim();
const oldName = session?.name || '';
// Only update if name actually changed
if (newName !== oldName) {
try {
const res = await fetch(`/api/sessions/${this.editingSessionId}/name`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: newName })
});
const data = await res.json();
if (data.error) throw new Error(data.error);
this.showToast('Session renamed', 'success');
} catch (err) {
this.showToast('Failed to rename: ' + err.message, 'error');
}
}
this.closeSessionOptions(); this.closeSessionOptions();
} }
-6
View File
@@ -189,12 +189,6 @@
<button class="modal-close" onclick="app.closeSessionOptions()">&times;</button> <button class="modal-close" onclick="app.closeSessionOptions()">&times;</button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="form-row-inline">
<input type="text" id="sessionNameInput" placeholder="Session name...">
<button class="btn-toolbar" onclick="app.closeSessionOptions()">Cancel</button>
<button class="btn-toolbar btn-primary" onclick="app.saveSessionOptions()">Save</button>
</div>
<!-- Respawn Settings Section --> <!-- Respawn Settings Section -->
<div class="session-respawn-section" id="sessionRespawnSection"> <div class="session-respawn-section" id="sessionRespawnSection">
<div class="section-divider"> <div class="section-divider">