chore: bump version to 0.1634

This commit is contained in:
arkon
2026-02-25 00:32:45 +01:00
parent 57193cb1be
commit 7b931a35d0
6 changed files with 133 additions and 3 deletions
+1 -1
View File
@@ -35,7 +35,7 @@ When user says "COM":
1. Increment version in BOTH `package.json` AND `CLAUDE.md` (verify they match with `grep version package.json && grep Version CLAUDE.md`)
2. Run: `git add -A && git commit -m "chore: bump version to X.XXXX" && git push && npm run build && systemctl --user restart claudeman-web`
**Version**: 0.1633 (must match `package.json`)
**Version**: 0.1634 (must match `package.json`)
## Project Overview
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "claudeman",
"version": "0.1633",
"version": "0.1634",
"description": "The missing control plane for Claude Code - run 20 autonomous agents with real-time monitoring and session persistence",
"type": "module",
"main": "dist/index.js",
+42 -1
View File
@@ -861,6 +861,16 @@ const KeyboardAccessoryBar = {
<button class="accessory-btn" data-action="init" title="/init">/init</button>
<button class="accessory-btn" data-action="clear" title="/clear">/clear</button>
<button class="accessory-btn" data-action="compact" title="/compact">/compact</button>
<button class="accessory-btn accessory-btn-voice" data-action="voice" title="Voice input"
aria-label="Start voice input" aria-pressed="false"
style="${VoiceInput.supported ? '' : 'display:none'}">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/>
<path d="M19 10v2a7 7 0 0 1-14 0v-2"/>
<line x1="12" y1="19" x2="12" y2="23"/>
<line x1="8" y1="23" x2="16" y2="23"/>
</svg>
</button>
<button class="accessory-btn" data-action="paste" title="Paste from clipboard">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/>
@@ -929,6 +939,9 @@ const KeyboardAccessoryBar = {
}
break;
}
case 'voice':
VoiceInput.toggle();
break;
case 'paste':
this.pasteFromClipboard();
break;
@@ -1420,7 +1433,8 @@ class ZerolagInputAddon {
if (!this._terminal) return;
const t = this._terminal;
this._font.fontFamily = t.options.fontFamily || 'monospace';
this._font.fontSize = (t.options.fontSize || 14) + 'px';
const baseFontSize = t.options.fontSize || 14;
this._font.fontSize = baseFontSize + 'px';
this._font.fontWeight = String(t.options.fontWeight || 'normal');
this._font.backgroundColor = this._options.backgroundColor ?? t.options.theme?.background ?? _ZL_DEFAULT_BG;
this._font.color = this._options.foregroundColor ?? t.options.theme?.foreground ?? _ZL_DEFAULT_FG;
@@ -1431,6 +1445,23 @@ class ZerolagInputAddon {
this._font.letterSpacing = cs.letterSpacing;
if (!this._options.foregroundColor && cs.color) this._font.color = cs.color;
}
// Correct font size: DOM text renders larger than xterm's canvas/WebGL text
// at the same nominal font-size. Measure actual DOM char width and scale to
// match the terminal's cell width so the overlay text matches exactly.
const dims = _zl_getCellDimensions(t);
if (dims && dims.width > 0) {
const probe = document.createElement('span');
probe.style.cssText = `position:absolute;visibility:hidden;white-space:pre;font-family:${this._font.fontFamily};font-size:${baseFontSize}px;font-weight:${this._font.fontWeight};font-feature-settings:'liga' 0,'calt' 0`;
if (this._font.letterSpacing) probe.style.letterSpacing = this._font.letterSpacing;
probe.textContent = 'W';
document.body.appendChild(probe);
const domCharW = probe.getBoundingClientRect().width;
document.body.removeChild(probe);
if (domCharW > 0 && Math.abs(domCharW - dims.width) > 0.1) {
const corrected = baseFontSize * (dims.width / domCharW);
this._font.fontSize = corrected + 'px';
}
}
}
_hide() {
if (!this._overlay) return;
@@ -2206,6 +2237,7 @@ class ClaudemanApp {
KeyboardHandler.init();
SwipeHandler.init();
KeyboardAccessoryBar.init();
VoiceInput.init();
this.applyHeaderVisibilitySettings();
this.applyTabWrapSettings();
this.applyMonitorVisibility();
@@ -3171,6 +3203,12 @@ class ClaudemanApp {
e.preventDefault();
this.decreaseFontSize();
}
// Ctrl/Cmd + Shift + V - toggle voice input
if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'V') {
e.preventDefault();
VoiceInput.toggle();
}
}, true); // Use capture phase to handle before terminal
// Token stats click handler (with guard to prevent duplicate handlers on reconnect)
@@ -4405,6 +4443,9 @@ class ClaudemanApp {
}
}
// Stop any active voice recording on reconnect
VoiceInput.cleanup();
this.sessions.clear();
this.ralphStates.clear();
this.terminalBuffers.clear();
+11
View File
@@ -361,6 +361,16 @@
</div>
<div class="toolbar-right">
<button class="btn-toolbar btn-sm btn-voice" id="voiceInputBtn" onclick="VoiceInput.toggle()"
title="Voice input (Ctrl+Shift+V)" aria-label="Start voice input" aria-pressed="false"
style="display: none;">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/>
<path d="M19 10v2a7 7 0 0 1-14 0v-2"/>
<line x1="12" y1="19" x2="12" y2="23"/>
<line x1="8" y1="23" x2="16" y2="23"/>
</svg>
</button>
</div>
</footer>
@@ -382,6 +392,7 @@
<div><kbd>Ctrl</kbd>+<kbd>+</kbd></div><div>Increase Font</div>
<div><kbd>Ctrl</kbd>+<kbd>-</kbd></div><div>Decrease Font</div>
<div><kbd>Ctrl</kbd>+<kbd>?</kbd></div><div>Show Help</div>
<div><kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>V</kbd></div><div>Voice Input</div>
<div><kbd>Escape</kbd></div><div>Close Panels</div>
</div>
</div>
+26
View File
@@ -746,6 +746,32 @@ html.mobile-init .file-browser-panel {
background: #3a3a3a;
}
/* Voice input button */
.accessory-btn-voice {
background: #1a2a3f;
border-color: rgba(59, 130, 246, 0.25);
color: #93c5fd;
}
.accessory-btn-voice:active {
background: #2a3a5f;
}
.accessory-btn-voice.recording {
background: rgba(239, 68, 68, 0.2);
border-color: rgba(239, 68, 68, 0.5);
color: #ef4444;
animation: voice-pulse 1.5s ease-in-out infinite;
}
/* Voice preview — positioned above accessory bar on mobile */
.voice-preview {
bottom: calc(var(--safe-area-bottom) + 94px);
font-size: 0.8rem;
max-width: 90%;
padding: 6px 14px;
}
/* Add case button - compact (keeping for when shown via menu) */
.btn-case-add {
display: none !important;
+52
View File
@@ -1977,6 +1977,58 @@ body {
border-color: var(--red);
}
/* Voice Input Button */
.btn-toolbar.btn-voice {
padding: 0.3rem 0.5rem;
}
.btn-toolbar.btn-voice:hover {
color: var(--text);
border-color: rgba(59, 130, 246, 0.4);
}
.btn-toolbar.btn-voice.recording {
background: rgba(239, 68, 68, 0.15);
border-color: rgba(239, 68, 68, 0.5);
color: #ef4444;
animation: voice-pulse 1.5s ease-in-out infinite;
}
.btn-toolbar.btn-voice.recording:hover {
background: rgba(239, 68, 68, 0.25);
border-color: rgba(239, 68, 68, 0.7);
color: #f87171;
}
@keyframes voice-pulse {
0%, 100% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.1); opacity: 0.75; }
}
/* Voice preview overlay — shows interim transcription */
.voice-preview {
position: fixed;
bottom: 48px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.88);
color: rgba(255, 255, 255, 0.7);
font-style: italic;
font-family: var(--font-mono, monospace);
padding: 8px 20px;
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.1);
font-size: 0.85rem;
max-width: 80%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
z-index: 100;
pointer-events: none;
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
}
.btn-icon-only {
display: flex;
align-items: center;