Skip to content

Releases: Wintersta7e/agentdeck

v6.3.0 — TerminalGridMirror tab-preservation infrastructure

02 May 18:40

Choose a tag to compare

What's new

A parallel cell-grid mirror that tracks where every \t byte landed, so copy can substitute literal tabs for the cell ranges that came from a tab character. Implemented as a self-contained ANSI parser (~700 LOC) covering CSI cursor positioning, erase ops, scroll regions, alt-buffer toggles, DECSC/RC, and string sequences (OSC / DCS / APC / PM). Backed by a wcwidth helper for CJK / emoji 2-cell width arithmetic. 35 mirror tests + 17 wcwidth tests + 9 copy-path tests added; total suite at 1181/1181 passing.

The mirror is fed unconditionally from pty.onData (regardless of pane visibility), resized in lockstep with xterm, and cached alongside the cached Terminal across tab switches. Copy substitution applies to spans that fit entirely inside the per-row selection; spans that cross either boundary stay as spaces (visual fidelity over imperfect substitution at boundaries).

Honest caveat — Windows + WSL via ConPTY

On Windows + WSL setups (which is AgentDeck's primary target), tabs are stripped upstream of our process by ConPTY (Windows Pseudo Console). ConPTY parses VT input into a cell grid, then re-serializes the grid as bytes for the host — tab characters that advanced the cursor over blank cells are re-emitted as spaces, not tabs. This is documented in microsoft/terminal #411 and affects every node-pty + ConPTY consumer (VS Code, Hyper, Windows Terminal). v6.3.0's tab preservation infrastructure is correct end-to-end but is currently a no-op under ConPTY because the input stream never contains \t bytes.

The mirror code remains useful for any future non-ConPTY path (winpty mode, native Linux/macOS PTY, custom pipelines) and lays groundwork for additional cell-tracking features down the line.

Other improvements

  • Alt-buffer save-cursor fixDECSC inside the alt buffer no longer clobbers main's saved cursor across DECRST 1049.
  • stripAnsi extracted to src/shared/ansi.ts — single source of truth for the ANSI escape regex consumed by main and renderer.
  • Hot-path optimizations — wcwidth ASCII fast-path + chunk-slice plain ASCII printable runs in mirror.ingest. Estimated 10-50× faster on plain text bursts.
  • getLogicalSelection signature switched to (term, options?) so future fields can land without churning call sites.

v6.2.0 — FilesTab tree + EnvTab per-agent snapshot

25 Apr 19:20

Choose a tag to compare

[6.2.0] - 2026-04-25

Session-UI rework. Strips the left sidebar and retired right-panel tabs,
introduces a browser-style session tab strip and single-row session header,
adds a file-based template store with user + project scopes, and layers an
approval lifecycle (idle → review → kept | discarded) on top of session status.
TerminalPane no longer auto-removes exited sessions after 800ms — they persist
until the user KEEPs / DISCARDs them or closes the tab via the × control.

The Files and Env right-panel tabs are also reworked: Files is now a recursive,
gitignore-aware filesystem tree rooted at the active session's project (or its
isolated worktree), and Env shows a per-agent snapshot of hooks, skills, MCP
servers, and config — resolved from session.agentOverride ?? project.agent
and refreshable on demand.

Added

  • Browser-style session tab strip (SessionTabs) above the Sessions view with per-tab agent icon, project name, branch label, status dot, and hover-× close control.
  • Single-row session header (SessionHeader) with agent + project + live branch + dirty-count from gitStatuses, state word, and context-appropriate action buttons (KEEP / DISCARD on review; RERUN on kept/discarded).
  • Sessions-overview button on the SessionTabs strip — clears the active selection without touching openSessionIds, so users can return to the SessionsScreen overview while keeping every open session in the strip.
  • Prompts inspector in the right panel (replaces retired tabs) with search, pin, usage count, per-template ◆ IN USE marker, preview pane, and Inject → pty.write that routes through incrementUsage + setSeedTemplateId.
  • Files tab in the right panel as a recursive, lazy-loaded filesystem tree rooted at the active session's project path (or its isolated worktree). Gitignored entries are filtered server-side via git check-ignore --stdin over wsl.exe. Tree is keyboard-navigable (Arrow keys / Home / End / Enter); manual refresh button hard-remounts the tree. New IPCs files:listDir({path,projectPath}) and files:openExternal({path,projectPath}) enforce a lexical project-scope check so the renderer can't enumerate arbitrary WSL paths.
  • Env tab in the right panel as a per-agent snapshot — Hooks (per-event count + scope badge, expandable), Skills (count + first 5 + show-all), MCP servers (name/type/command/status), Config (flat key/value with copy), Paths (debug footer with agentdeckRoot, templateUserRoot, WSL distro/home, project .agentdeck). Future-tier agents (gemini-cli, amazon-q, opencode) render a "not yet supported" placeholder above the paths footer. New main-process modules wsl-paths (resolves WSL $HOME / $CLAUDE_CONFIG_DIR / $CODEX_HOME via wsl.exe, reads files through wslPathToWindows + UNC fallback) and agent-env-resolver dispatch to per-agent readers (agent-env-claude, agent-env-codex, agent-env-other). New IPC env:getAgentSnapshot({agentId, projectId?, force?}) with 30s TTL cache, in-flight dedup, and SAFE_ID_RE-validated projectId lookup against the project store.
  • File-based template store at ~/.agentdeck/templates/ and <project>/.agentdeck/templates/ with per-template mutex, atomic writes (randomBytes tmp-rename), 200ms-debounced fs.watch (10s poll fallback), global ID uniqueness enforcement (E_TEMPLATE_ID_EXISTS), and stale-save detection (E_TEMPLATE_STALE).
  • One-shot staging-dir migration from electron-store templates key to files (appPrefs.templatesMigrated gate) with fresh-install seeding path.
  • Approval lifecycle on sessions: running → exited via pty-exit auto-flips idle → review; user's KEEP / DISCARD transitions to kept / discarded; RERUN spawns a new session with fresh context-window snapshot.
  • openSessionIds ordered tab list on the sessions slice; openSession(seed) creates sessions through one entry point; pruneSessionFromTabs(id) handles tab removal with pane backfill; clearActiveSession() deselects without closing.
  • closeSession orchestrator at src/renderer/utils/session-close.ts — inspect worktree → prompt on dirty → applySessionStatus(user-kill) → pty.kill → conditional re-inspect → worktree commit/keep/discard → releasePrimary → clearWorktreePath → prune.
  • One-shot project.path normalization in project-store (gated by appPrefs.pathsNormalized).

Changed

  • Right inspector reduced from 7 tabs to 5: Files / Diff / Prompts / Env / Config (default: Files).
  • Files tab content: was activity-feed-derived list of read/written paths; now a project-rooted filesystem tree. Activity-feed events are still tracked internally for cost/timeline/digest but no longer surface as a panel.
  • Env tab content: was a flat dump of CLAUDE_CONFIG_DIR / CODEX_HOME / agentdeckRoot / templateUserRoot / WSL distro+home / agent versions / project .agentdeck paths; now a per-agent snapshot. The legacy paths still appear in the Paths footer at the bottom of the new view.
  • Close-session flow now inspects worktree safety, prompts on dirty changes with Keep-branch / Discard / Cancel options, and commits worktree state after pty kill.
  • addNotification extended with a discriminated union: existing basic toasts keep their shape under kind: 'basic'; new kind: 'confirm' notifications carry options[] + a resolve() promise for actionable prompts.
  • ViewType narrowed to drop the singular 'session' — the plural 'sessions' tab renders the list when no session is active and the terminal when one is.
  • Resolver dispatch and per-agent summary logs (hooks/skills/mcp/config counts) emit at info level so production traces are visible without AGENTDECK_DEBUG.
  • Test layout: 63 unit tests relocated from __tests__/ directories to sit next to their source files; integration / multi-module / structural tests stay in __tests__/.

Removed

  • Left Sidebar (Pinned / Templates / Workflows) and its state (sidebarOpen, sidebarWidth, sidebarSections, toggleSidebar, setSidebarWidth, toggleSidebarSection, Ctrl+B).
  • Per-pane PaneTopbar — each pane is just the xterm host now.
  • StepsRail — terminal reclaims the column.
  • Titlebar's inline session-tab row — SessionTabs owns that UX now.
  • Retired right-panel tabs: Activity, Memory, Cost, Context.
  • TerminalPane's 800ms auto-remove of exited sessions.
  • LegacyTemplate alias from the renderer pipeline (kept in main-process legacy-store fallback; retired in v6.2.0).

Dependencies

  • No runtime dependency changes — uses existing smol-toml, yaml, jsonc-parser, electron-store, node:fs (fs.watch), node:crypto (randomBytes).