Skip to content

feat: tab-local selection and per-tab terminal isolation#98

Merged
gbasin merged 9 commits intomasterfrom
feat/local-multi-tab
Feb 24, 2026
Merged

feat: tab-local selection and per-tab terminal isolation#98
gbasin merged 9 commits intomasterfrom
feat/local-multi-tab

Conversation

@gbasin
Copy link
Owner

@gbasin gbasin commented Feb 23, 2026

This PR makes agentboard multi-tab behavior predictable across selection state, terminal switching, and session list animations.

Summary

  • Session selection persistence is now tab-local after initial hydration.
  • PTY terminal switching now stays isolated per websocket connection, preventing tabs from fighting over tmux window focus.
  • Safari session list animation fallback was hardened, including drag displacement behavior.
  • Redundant setSessions snapshots are deduped without dropping lastActivity updates.
  • Patch version bumped to 0.2.19.

What changed

Client state and persistence

  • Added createTabStorage(expectedKey) and wired sessionStore persist key agentboard-session to tab-scoped storage.
  • Kept persisted scope narrow to selectedSessionId.
  • Added tests for hydration, per-tab read isolation, write-through, remove behavior, and key guardrails.

Terminal isolation

  • Updated PtyTerminalProxy to rewrite base-session switch targets (for example agentboard:@2) to grouped per-connection targets (for example agentboard-ws-<connection>:@2).
  • Added isolated proxy test coverage for grouped target rewriting.

Session list behavior and Safari

  • Added Safari-specific fallback for list transitions and layout handling.
  • Ensured DnD transforms are still applied in Safari fallback so non-dragging items displace correctly during sorting.
  • Added targeted transform composition tests.

Snapshot update behavior

  • Deduped redundant setSessions updates to reduce animation churn.
  • Corrected equality logic to preserve lastActivity updates and use order-insensitive session comparisons.
  • Added regression test for lastActivity-only updates.

Notes

  • Cross-tab live sync of selected session remains intentionally disabled after hydration.
  • New tabs/reloads still hydrate from the shared latest persisted default.

Validation

  • bun run lint
  • bun run typecheck
  • bun run test

gbasin and others added 6 commits February 23, 2026 13:14
Each browser tab now maintains independent selectedSessionId state.
createTabStorage reads from localStorage once on hydration (good default
for new tabs and iOS PWA relaunches), then diverges into an in-memory
Map per tab. Writes update both layers so localStorage stays fresh.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add structural equality guard that skips Zustand updates when session
data hasn't meaningfully changed. The kill flow and periodic refresh
broadcast identical session lists as new array references, causing
redundant re-renders that disrupt AnimatePresence exit animations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gbasin gbasin changed the title feat: make session selection tab-local feat: tab-local selection and per-tab terminal isolation Feb 24, 2026
@gbasin gbasin merged commit c1ef981 into master Feb 24, 2026
5 checks passed
@gbasin gbasin deleted the feat/local-multi-tab branch February 24, 2026 22:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant