feat(terminal): tmux pane-buffer primitives and session/render reliability

Mode-agnostic terminal foundation extracted from the downstream branch:
- formatPaneSnapshot: SGR/grapheme-aware tmux pane capture + active-pane
  resolution, with OSC/CSI redraw suppression and the buffer-load owner-token
  race fix on the terminal fetch path
- socket-correct tmux lifecycle: dedicated -L socket and /tmp launch cwd in
  createSession (restores the FUSE/getcwd hardening from #110), and a
  socket-aware re-attach window-size query (avoids the 120x40 flicker)
- inline-rename: commit/cancel state handling clears _activeRename and skips
  the API call on cancel
- selectSession: restored detached-window raise short-circuit

The codex-specific xterm snapshot/replay, the vendored serialize addon, and
the synchronous live pane-capture on the request path are intentionally
excluded: they depend on a 'codex' SessionMode that doesn't exist on master
and are deferred to COD-34 (which introduces that mode). The capture
primitives remain exported for COD-34 to build on.

Co-Authored-By: Saqeb Akhter <saqeb.akhter@gmail.com>
This commit is contained in:
Aamer Akhter
2026-06-09 15:39:03 -04:00
co-authored by Saqeb Akhter
parent 2952256d65
commit 0569f68b86
11 changed files with 840 additions and 66 deletions
+7 -8
View File
@@ -927,9 +927,8 @@ Object.assign(CodemanApp.prototype, {
const tabName = document.querySelector(`.tab-name[data-session-id="${sessionId}"]`);
if (!tabName) return;
// If a previous rename somehow leaked (shouldn't happen, but defends against
// future code paths that throw before cleanup), abort it before starting fresh.
if (this._activeRename) this._activeRename.cancel();
// Prevent tab re-renders from destroying the input while renaming
this._inlineRenameActive = true;
const currentName = this.getSessionName(session);
const parsed = parseSessionPrefix(session.name);
@@ -957,14 +956,14 @@ Object.assign(CodemanApp.prototype, {
input.focus();
input.select();
let settled = false;
const finishRename = async ({ commit }) => {
if (settled) return;
settled = true;
if (!this._inlineRenameActive) return; // prevent double-fire
this._inlineRenameActive = false;
this._activeRename = null;
// Aborted (e.g. session was deleted mid-rename): just re-render so any
// ghost DOM left behind is replaced with the canonical tab list.
// Aborted (e.g. the session was deleted mid-rename, or Escape): re-render
// so any ghost DOM is replaced with the canonical tab list, and skip the
// API call — a cancel must not fire a stale rename PUT.
if (!commit) {
this.renderSessionTabs();
return;