mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-01 21:19:41 +02:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15a3b3996b | ||
|
|
1b76e6e2e2 |
@@ -1,5 +1,11 @@
|
|||||||
# aicodeman
|
# aicodeman
|
||||||
|
|
||||||
|
## 0.3.4
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Fix Chrome tab freeze from flicker filter buffer accumulation during active sessions, and fix shell mode feedback delay by excluding shell sessions from cursor-up filter
|
||||||
|
|
||||||
## 0.3.3
|
## 0.3.3
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ When user says "COM":
|
|||||||
4. **Sync CLAUDE.md version**: Update the `**Version**` line below to match the new version from `package.json`
|
4. **Sync CLAUDE.md version**: Update the `**Version**` line below to match the new version from `package.json`
|
||||||
5. **Commit and deploy**: `git add -A && git commit -m "chore: version packages" && git push && npm run build && systemctl --user restart codeman-web`
|
5. **Commit and deploy**: `git add -A && git commit -m "chore: version packages" && git push && npm run build && systemctl --user restart codeman-web`
|
||||||
|
|
||||||
**Version**: 0.3.3 (must match `package.json`)
|
**Version**: 0.3.4 (must match `package.json`)
|
||||||
|
|
||||||
## Project Overview
|
## Project Overview
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "aicodeman",
|
"name": "aicodeman",
|
||||||
"version": "0.3.3",
|
"version": "0.3.4",
|
||||||
"description": "The missing control plane for AI coding agents - run 20 autonomous agents with real-time monitoring and session persistence",
|
"description": "The missing control plane for AI coding agents - run 20 autonomous agents with real-time monitoring and session persistence",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
|
|||||||
+40
-6
@@ -1097,18 +1097,47 @@ class CodemanApp {
|
|||||||
// Ink's status bar updates use cursor-up + erase-line + rewrite, which can split
|
// Ink's status bar updates use cursor-up + erase-line + rewrite, which can split
|
||||||
// across render frames causing old/new status text to overlap (garbled output).
|
// across render frames causing old/new status text to overlap (garbled output).
|
||||||
// Buffering for 50ms ensures the full redraw arrives atomically.
|
// Buffering for 50ms ensures the full redraw arrives atomically.
|
||||||
const hasCursorUpRedraw = /\x1b\[\d{1,2}A/.test(data);
|
//
|
||||||
|
// Shell mode is excluded: shell readline also uses cursor-up for prompt redraws
|
||||||
|
// (e.g. zsh syntax highlighting on every keystroke), and there's no Ink status bar
|
||||||
|
// to protect. Applying the filter in shell mode delays character feedback until the
|
||||||
|
// user stops typing for 50ms, making the terminal feel unresponsive.
|
||||||
|
const isShellMode = session?.mode === 'shell';
|
||||||
|
const hasCursorUpRedraw = !isShellMode && /\x1b\[\d{1,2}A/.test(data);
|
||||||
if (hasCursorUpRedraw || (this.flickerFilterActive && !flickerFilterEnabled)) {
|
if (hasCursorUpRedraw || (this.flickerFilterActive && !flickerFilterEnabled)) {
|
||||||
this.flickerFilterActive = true;
|
this.flickerFilterActive = true;
|
||||||
this.flickerFilterBuffer += data;
|
this.flickerFilterBuffer += data;
|
||||||
|
|
||||||
if (this.flickerFilterTimeout) {
|
// Only reset the 50ms timer on cursor-up events (start of a new Ink redraw cycle).
|
||||||
clearTimeout(this.flickerFilterTimeout);
|
// Non-cursor-up events while the filter is active are trailing data from the same
|
||||||
|
// redraw — don't extend the deadline further. Without this guard, a busy Claude
|
||||||
|
// session emitting terminal data faster than SYNC_WAIT_TIMEOUT_MS never flushes,
|
||||||
|
// accumulating MBs in flickerFilterBuffer that freeze Chrome all at once.
|
||||||
|
if (hasCursorUpRedraw) {
|
||||||
|
if (this.flickerFilterTimeout) {
|
||||||
|
clearTimeout(this.flickerFilterTimeout);
|
||||||
|
}
|
||||||
|
this.flickerFilterTimeout = setTimeout(() => {
|
||||||
|
this.flickerFilterTimeout = null;
|
||||||
|
this.flushFlickerBuffer();
|
||||||
|
}, SYNC_WAIT_TIMEOUT_MS); // 50ms buffer window
|
||||||
|
} else if (!this.flickerFilterTimeout) {
|
||||||
|
// Safety: if no timer is running for some reason, ensure we eventually flush.
|
||||||
|
this.flickerFilterTimeout = setTimeout(() => {
|
||||||
|
this.flickerFilterTimeout = null;
|
||||||
|
this.flushFlickerBuffer();
|
||||||
|
}, SYNC_WAIT_TIMEOUT_MS);
|
||||||
}
|
}
|
||||||
this.flickerFilterTimeout = setTimeout(() => {
|
|
||||||
this.flickerFilterTimeout = null;
|
// Safety valve: if buffer grew very large (e.g. from a burst before the timer fired),
|
||||||
|
// flush immediately to avoid writing a huge block all at once.
|
||||||
|
if (this.flickerFilterBuffer.length > 256 * 1024) {
|
||||||
|
if (this.flickerFilterTimeout) {
|
||||||
|
clearTimeout(this.flickerFilterTimeout);
|
||||||
|
this.flickerFilterTimeout = null;
|
||||||
|
}
|
||||||
this.flushFlickerBuffer();
|
this.flushFlickerBuffer();
|
||||||
}, SYNC_WAIT_TIMEOUT_MS); // 50ms buffer window
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1238,6 +1267,11 @@ class CodemanApp {
|
|||||||
} catch { return null; }
|
} catch { return null; }
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else if (session.mode === 'shell') {
|
||||||
|
// Shell mode: the shell provides its own PTY echo so the overlay isn't needed.
|
||||||
|
// Disable it by clearing any pending text.
|
||||||
|
this._localEchoOverlay.clear();
|
||||||
|
this._localEchoEnabled = false;
|
||||||
} else {
|
} else {
|
||||||
// Claude Code: scan for ❯ prompt character
|
// Claude Code: scan for ❯ prompt character
|
||||||
this._localEchoOverlay.setPrompt({ type: 'character', char: '\u276f', offset: 2 });
|
this._localEchoOverlay.setPrompt({ type: 'character', char: '\u276f', offset: 2 });
|
||||||
|
|||||||
Reference in New Issue
Block a user