102 lines
3.6 KiB
Markdown
102 lines
3.6 KiB
Markdown
# Terminal Multi Tabs Implementation Plan
|
|
|
|
> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
|
|
**Goal:** Allow the connection list to open multiple terminal tabs for the same connection, with each click creating a fresh terminal session.
|
|
|
|
**Architecture:** Keep the existing `/terminal` workspace and Pinia-driven tab model, but change terminal tab creation from connection-deduplicated to always-new. Add lightweight title numbering so repeated tabs for the same connection remain distinguishable without changing routing or terminal widget lifecycle.
|
|
|
|
**Tech Stack:** Vue 3, TypeScript, Pinia, Vue Router, xterm.js, Vite, vue-tsc
|
|
|
|
---
|
|
|
|
## File Structure
|
|
|
|
- Modify: `frontend/src/stores/terminalTabs.ts`
|
|
- Change tab creation semantics and add repeated-title numbering.
|
|
- Modify: `frontend/src/views/ConnectionsView.vue`
|
|
- Use the new always-open terminal action from the connection list.
|
|
- Verify: `frontend/src/views/TerminalWorkspaceView.vue`
|
|
- Confirm current per-tab widget mounting already supports independent sessions.
|
|
- Verify: `frontend/src/layouts/MainLayout.vue`
|
|
- Confirm terminal sidebar tab rendering needs no structure change beyond new titles.
|
|
- Reference: `docs/superpowers/specs/2026-03-26-terminal-multi-tabs-design.md`
|
|
- Source of truth for behavior and acceptance criteria.
|
|
|
|
### Task 1: Change Terminal Tabs Store to Always Create New Tabs
|
|
|
|
**Files:**
|
|
- Modify: `frontend/src/stores/terminalTabs.ts`
|
|
- Reference: `frontend/src/stores/sftpTabs.ts`
|
|
|
|
- [ ] **Step 1: Inspect current tab store behavior**
|
|
|
|
Read `frontend/src/stores/terminalTabs.ts` and confirm the existing dedup-by-connection behavior.
|
|
|
|
- [ ] **Step 2: Add repeated-title generation**
|
|
|
|
Add a helper that counts currently open tabs for the same `connectionId` and returns:
|
|
|
|
```ts
|
|
function getTabTitle(connection: Connection) {
|
|
const sameConnectionCount = tabs.value.filter(t => t.connectionId === connection.id).length
|
|
|
|
if (sameConnectionCount === 0) {
|
|
return connection.name
|
|
}
|
|
|
|
return `${connection.name} (${sameConnectionCount + 1})`
|
|
}
|
|
```
|
|
|
|
- [ ] **Step 3: Replace dedup open logic with always-new creation**
|
|
|
|
Change the open action so it always creates a new `TerminalTab` and activates it immediately.
|
|
|
|
- [ ] **Step 4: Keep activate/close behavior unchanged**
|
|
|
|
Do not change tab activation and close-neighbor behavior except what is necessary to support the new open logic.
|
|
|
|
### Task 2: Wire the Connection List to the New Behavior
|
|
|
|
**Files:**
|
|
- Modify: `frontend/src/views/ConnectionsView.vue`
|
|
- Use: `frontend/src/stores/terminalTabs.ts`
|
|
|
|
- [ ] **Step 1: Rename the method usage to match semantics**
|
|
|
|
Update `openTerminal(conn)` to call the new always-open store action.
|
|
|
|
- [ ] **Step 2: Preserve routing behavior**
|
|
|
|
Keep `router.push('/terminal')` unchanged after opening the tab.
|
|
|
|
### Task 3: Verify Integration and Build
|
|
|
|
**Files:**
|
|
- Verify: `frontend/src/layouts/MainLayout.vue`
|
|
- Verify: `frontend/src/views/TerminalWorkspaceView.vue`
|
|
|
|
- [ ] **Step 1: Confirm sidebar rendering already keys by `tab.id`**
|
|
|
|
No structural code changes should be required if repeated tabs render correctly with distinct titles.
|
|
|
|
- [ ] **Step 2: Run final frontend build**
|
|
|
|
Run in `frontend/`:
|
|
|
|
```bash
|
|
npm run build
|
|
```
|
|
|
|
Expected: `vue-tsc -b` and `vite build` both pass.
|
|
|
|
- [ ] **Step 3: Manual runtime verification**
|
|
|
|
Check:
|
|
|
|
1. Same connection opens multiple terminal tabs.
|
|
2. Repeated tabs are titled distinctly.
|
|
3. Each tab remains an independent terminal session.
|
|
4. Close/switch behavior still works.
|