claude-code-plus-plus 0.2.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ansi.d.ts +42 -0
- package/dist/ansi.d.ts.map +1 -0
- package/dist/ansi.js +53 -0
- package/dist/ansi.js.map +1 -0
- package/dist/constants.d.ts +67 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +109 -0
- package/dist/constants.js.map +1 -0
- package/dist/sidebar/app.d.ts +2 -1
- package/dist/sidebar/app.d.ts.map +1 -1
- package/dist/sidebar/app.js +129 -205
- package/dist/sidebar/app.js.map +1 -1
- package/dist/sidebar/commands.d.ts +64 -0
- package/dist/sidebar/commands.d.ts.map +1 -0
- package/dist/sidebar/commands.js +180 -0
- package/dist/sidebar/commands.js.map +1 -0
- package/dist/sidebar/pane-orchestrator.d.ts +31 -0
- package/dist/sidebar/pane-orchestrator.d.ts.map +1 -0
- package/dist/sidebar/pane-orchestrator.js +185 -0
- package/dist/sidebar/pane-orchestrator.js.map +1 -0
- package/dist/sidebar/render.d.ts +2 -23
- package/dist/sidebar/render.d.ts.map +1 -1
- package/dist/sidebar/render.js +100 -129
- package/dist/sidebar/render.js.map +1 -1
- package/dist/sidebar/session-manager.d.ts +23 -0
- package/dist/sidebar/session-manager.d.ts.map +1 -0
- package/dist/sidebar/session-manager.js +122 -0
- package/dist/sidebar/session-manager.js.map +1 -0
- package/dist/sidebar/terminal-manager.d.ts +48 -0
- package/dist/sidebar/terminal-manager.d.ts.map +1 -0
- package/dist/sidebar/terminal-manager.js +223 -0
- package/dist/sidebar/terminal-manager.js.map +1 -0
- package/dist/terminal/bar-handler.js +6 -19
- package/dist/terminal/bar-handler.js.map +1 -1
- package/dist/terminal/bar-render.d.ts.map +1 -1
- package/dist/terminal/bar-render.js +15 -35
- package/dist/terminal/bar-render.js.map +1 -1
- package/package.json +1 -2
- package/assets/screenshot.png +0 -0
package/dist/sidebar/app.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Sidebar Application
|
|
4
4
|
*
|
|
5
5
|
* Main sidebar class that handles state management, input handling, and rendering.
|
|
6
|
+
* Uses extracted managers for session, terminal, and pane operations.
|
|
6
7
|
*/
|
|
7
8
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
9
|
if (k2 === undefined) k2 = k;
|
|
@@ -40,102 +41,28 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
40
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
42
|
exports.SidebarApp = void 0;
|
|
42
43
|
const fs_1 = require("fs");
|
|
43
|
-
const child_process_1 = require("child_process");
|
|
44
44
|
const path_1 = require("path");
|
|
45
45
|
const tmux = __importStar(require("../tmux"));
|
|
46
46
|
const git_1 = require("../git");
|
|
47
47
|
const input_1 = require("./input");
|
|
48
48
|
const render_1 = require("./render");
|
|
49
|
-
|
|
49
|
+
const constants_1 = require("../constants");
|
|
50
|
+
const pane_orchestrator_1 = require("./pane-orchestrator");
|
|
51
|
+
const sessionManager = __importStar(require("./session-manager"));
|
|
52
|
+
const terminalManager = __importStar(require("./terminal-manager"));
|
|
53
|
+
const logger_1 = require("../utils/logger");
|
|
54
|
+
const errors_1 = require("../utils/errors");
|
|
55
|
+
const validation_1 = require("../utils/validation");
|
|
56
|
+
const commands_1 = require("./commands");
|
|
57
|
+
// Create logger for sidebar
|
|
58
|
+
const logger = new logger_1.Logger({
|
|
59
|
+
level: 'debug',
|
|
60
|
+
context: 'Sidebar',
|
|
61
|
+
filePath: constants_1.SIDEBAR_LOG_PATH,
|
|
62
|
+
});
|
|
63
|
+
// Debug logging helper (for backwards compatibility)
|
|
50
64
|
function debugLog(...args) {
|
|
51
|
-
|
|
52
|
-
(0, fs_1.appendFileSync)('/tmp/claude-pp-sidebar.log', msg);
|
|
53
|
-
}
|
|
54
|
-
// ============================================================================
|
|
55
|
-
// Constants
|
|
56
|
-
// ============================================================================
|
|
57
|
-
const SIDEBAR_WIDTH = 25;
|
|
58
|
-
const DEFAULT_CLAUDE_CMD = 'claude --dangerously-skip-permissions';
|
|
59
|
-
const TERMINAL_BAR_HEIGHT = 1;
|
|
60
|
-
const CLAUDE_PANE_PERCENT = 70; // Claude pane gets 70%, terminal area gets 30%
|
|
61
|
-
/**
|
|
62
|
-
* Set up terminal bar resize enforcement (hook + mouse binding).
|
|
63
|
-
* Uses a file-based script to avoid complex quoting issues.
|
|
64
|
-
* Sets up both after-resize-pane hook AND MouseDragEnd1Border binding.
|
|
65
|
-
*/
|
|
66
|
-
function setupTerminalBarResize(sessionName, claudePaneId, barPaneId, terminalBodyPaneId) {
|
|
67
|
-
const hookCmd = getTerminalBarResizeHook(claudePaneId, barPaneId, terminalBodyPaneId);
|
|
68
|
-
// Set up the after-resize-pane hook
|
|
69
|
-
tmux.setHook(sessionName, 'after-resize-pane', hookCmd);
|
|
70
|
-
// Also bind MouseDragEnd1Border to run the script when mouse drag ends
|
|
71
|
-
// This ensures the fix runs when user releases mouse after dragging border
|
|
72
|
-
const safeName = `${claudePaneId}-${barPaneId}`.replace(/%/g, '');
|
|
73
|
-
const scriptPath = `/tmp/cpp-resize-hook-${safeName}.sh`;
|
|
74
|
-
try {
|
|
75
|
-
(0, child_process_1.execSync)(`tmux bind-key -T root MouseDragEnd1Border run-shell "sh ${scriptPath}"`, { stdio: 'ignore' });
|
|
76
|
-
}
|
|
77
|
-
catch {
|
|
78
|
-
// Ignore errors
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Create a shell script for terminal bar resize hook and return the hook command.
|
|
83
|
-
* Uses a file-based script to avoid complex quoting issues.
|
|
84
|
-
*/
|
|
85
|
-
function getTerminalBarResizeHook(claudePaneId, barPaneId, terminalBodyPaneId) {
|
|
86
|
-
// Use pane IDs in filename to make it unique per terminal configuration
|
|
87
|
-
const safeName = `${claudePaneId}-${barPaneId}`.replace(/%/g, '');
|
|
88
|
-
const scriptPath = `/tmp/cpp-resize-hook-${safeName}.sh`;
|
|
89
|
-
// Write the script file
|
|
90
|
-
const scriptContent = `#!/bin/sh
|
|
91
|
-
# Terminal bar resize hook - keeps bar at ${TERMINAL_BAR_HEIGHT} row(s)
|
|
92
|
-
# Lock check - prevent recursion
|
|
93
|
-
LOCK=$(tmux show-option -gqv @cpp-resizing 2>/dev/null)
|
|
94
|
-
[ -n "$LOCK" ] && exit 0
|
|
95
|
-
|
|
96
|
-
# Get current heights
|
|
97
|
-
BAR_H=$(tmux display-message -p -t "${barPaneId}" '#{pane_height}' 2>/dev/null)
|
|
98
|
-
[ -z "$BAR_H" ] && exit 0
|
|
99
|
-
[ "$BAR_H" -eq ${TERMINAL_BAR_HEIGHT} ] && exit 0
|
|
100
|
-
|
|
101
|
-
CLAUDE_H=$(tmux display-message -p -t "${claudePaneId}" '#{pane_height}' 2>/dev/null)
|
|
102
|
-
BODY_H=$(tmux display-message -p -t "${terminalBodyPaneId}" '#{pane_height}' 2>/dev/null)
|
|
103
|
-
|
|
104
|
-
# Get previous heights (to detect which pane shrank)
|
|
105
|
-
PREV_CLAUDE=$(tmux show-option -gqv @cpp-prev-claude 2>/dev/null)
|
|
106
|
-
PREV_BODY=$(tmux show-option -gqv @cpp-prev-body 2>/dev/null)
|
|
107
|
-
|
|
108
|
-
# Acquire lock and set trap
|
|
109
|
-
tmux set-option -g @cpp-resizing 1
|
|
110
|
-
trap 'tmux set-option -gu @cpp-resizing 2>/dev/null' EXIT
|
|
111
|
-
|
|
112
|
-
# Calculate how much bar is over target
|
|
113
|
-
D=$((BAR_H - ${TERMINAL_BAR_HEIGHT}))
|
|
114
|
-
|
|
115
|
-
# Determine which pane to grow based on which one shrank
|
|
116
|
-
if [ -n "$PREV_CLAUDE" ] && [ "$CLAUDE_H" -lt "$PREV_CLAUDE" ]; then
|
|
117
|
-
# Claude shrank (user dragged tabs ceiling UP) -> grow Terminal body
|
|
118
|
-
tmux resize-pane -t "${terminalBodyPaneId}" -U "$D" 2>/dev/null
|
|
119
|
-
elif [ -n "$PREV_BODY" ] && [ "$BODY_H" -lt "$PREV_BODY" ]; then
|
|
120
|
-
# Terminal body shrank (user dragged body ceiling DOWN) -> grow Claude
|
|
121
|
-
tmux resize-pane -t "${claudePaneId}" -D "$D" 2>/dev/null
|
|
122
|
-
else
|
|
123
|
-
# Fallback: just set bar height directly, let tmux decide
|
|
124
|
-
:
|
|
125
|
-
fi
|
|
126
|
-
|
|
127
|
-
# Set bar to exact height
|
|
128
|
-
tmux resize-pane -t "${barPaneId}" -y ${TERMINAL_BAR_HEIGHT} 2>/dev/null
|
|
129
|
-
|
|
130
|
-
# Store FINAL heights (after adjustment) for next comparison
|
|
131
|
-
FINAL_CLAUDE=$(tmux display-message -p -t "${claudePaneId}" '#{pane_height}' 2>/dev/null)
|
|
132
|
-
FINAL_BODY=$(tmux display-message -p -t "${terminalBodyPaneId}" '#{pane_height}' 2>/dev/null)
|
|
133
|
-
tmux set-option -g @cpp-prev-claude "$FINAL_CLAUDE"
|
|
134
|
-
tmux set-option -g @cpp-prev-body "$FINAL_BODY"
|
|
135
|
-
`;
|
|
136
|
-
// Write script to file (synchronously)
|
|
137
|
-
(0, fs_1.writeFileSync)(scriptPath, scriptContent, { mode: 0o755 });
|
|
138
|
-
return `"run-shell 'sh ${scriptPath}'"`;
|
|
65
|
+
logger.debug(args.map(a => typeof a === 'object' ? JSON.stringify(a) : String(a)).join(' '));
|
|
139
66
|
}
|
|
140
67
|
// ============================================================================
|
|
141
68
|
// Sidebar App
|
|
@@ -252,8 +179,8 @@ class SidebarApp {
|
|
|
252
179
|
process.stdout.write(output);
|
|
253
180
|
}
|
|
254
181
|
syncCollapsedState() {
|
|
255
|
-
const width = process.stdout.columns || SIDEBAR_WIDTH;
|
|
256
|
-
this.state.collapsed = width < SIDEBAR_WIDTH / 2;
|
|
182
|
+
const width = process.stdout.columns || constants_1.SIDEBAR_WIDTH;
|
|
183
|
+
this.state.collapsed = width < constants_1.SIDEBAR_WIDTH / 2;
|
|
257
184
|
}
|
|
258
185
|
// ==========================================================================
|
|
259
186
|
// Input Handling
|
|
@@ -319,97 +246,76 @@ class SidebarApp {
|
|
|
319
246
|
}
|
|
320
247
|
}
|
|
321
248
|
handleMainInput(key) {
|
|
322
|
-
//
|
|
323
|
-
if (key.ctrl && key.key === 'c') {
|
|
324
|
-
this.enterFullscreenModal();
|
|
325
|
-
this.state.modal = 'quit';
|
|
326
|
-
this.state.modalSelection = 0;
|
|
327
|
-
this.render();
|
|
328
|
-
return;
|
|
329
|
-
}
|
|
330
|
-
// If collapsed, only expand on any key
|
|
249
|
+
// If collapsed, expand on any key first
|
|
331
250
|
if (this.state.collapsed) {
|
|
332
251
|
this.state.collapsed = false;
|
|
333
252
|
this.enforceSidebarWidth();
|
|
334
253
|
this.render();
|
|
335
254
|
return;
|
|
336
255
|
}
|
|
337
|
-
//
|
|
338
|
-
|
|
339
|
-
this.
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
}
|
|
393
|
-
this.
|
|
394
|
-
this.
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
// r - rename
|
|
401
|
-
if (key.key === 'r') {
|
|
402
|
-
const item = this.getSelectedItem();
|
|
403
|
-
if (item && !(item.type === 'worktree' && item.worktree?.isMain)) {
|
|
404
|
-
this.enterFullscreenModal();
|
|
405
|
-
this.state.modal = 'rename';
|
|
406
|
-
this.state.inputBuffer = item.type === 'session'
|
|
407
|
-
? item.session?.title || ''
|
|
408
|
-
: item.worktree?.branch || '';
|
|
409
|
-
this.render();
|
|
410
|
-
}
|
|
411
|
-
return;
|
|
412
|
-
}
|
|
256
|
+
// Create command context with action handlers
|
|
257
|
+
const context = {
|
|
258
|
+
state: this.state,
|
|
259
|
+
actions: {
|
|
260
|
+
moveUp: () => {
|
|
261
|
+
this.state.selectedIndex = Math.max(0, this.state.selectedIndex - 1);
|
|
262
|
+
this.render();
|
|
263
|
+
},
|
|
264
|
+
moveDown: () => {
|
|
265
|
+
const maxIndex = this.getMaxIndex();
|
|
266
|
+
this.state.selectedIndex = Math.min(maxIndex, this.state.selectedIndex + 1);
|
|
267
|
+
this.render();
|
|
268
|
+
},
|
|
269
|
+
activateSelected: () => {
|
|
270
|
+
debugLog('handleMainInput: enter pressed, calling activateSelected');
|
|
271
|
+
this.activateSelected();
|
|
272
|
+
},
|
|
273
|
+
showQuitModal: () => {
|
|
274
|
+
this.enterFullscreenModal();
|
|
275
|
+
this.state.modal = 'quit';
|
|
276
|
+
this.state.modalSelection = 0;
|
|
277
|
+
this.render();
|
|
278
|
+
},
|
|
279
|
+
showDeleteModal: () => {
|
|
280
|
+
const item = this.getSelectedItem();
|
|
281
|
+
if (item && !(item.type === 'worktree' && item.worktree?.isMain)) {
|
|
282
|
+
this.state.deleteTarget = {
|
|
283
|
+
type: item.type,
|
|
284
|
+
id: item.id,
|
|
285
|
+
name: item.type === 'session' ? (item.session?.title || '') : (item.worktree?.branch || ''),
|
|
286
|
+
worktree: item.worktree,
|
|
287
|
+
session: item.session,
|
|
288
|
+
};
|
|
289
|
+
this.enterFullscreenModal();
|
|
290
|
+
this.state.modal = 'delete';
|
|
291
|
+
this.state.modalSelection = 0;
|
|
292
|
+
this.render();
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
showNewWorktreeModal: () => {
|
|
296
|
+
this.enterFullscreenModal();
|
|
297
|
+
this.state.modal = 'new-worktree';
|
|
298
|
+
this.state.inputBuffer = '';
|
|
299
|
+
this.render();
|
|
300
|
+
},
|
|
301
|
+
showRenameModal: () => {
|
|
302
|
+
const item = this.getSelectedItem();
|
|
303
|
+
if (item && !(item.type === 'worktree' && item.worktree?.isMain)) {
|
|
304
|
+
this.enterFullscreenModal();
|
|
305
|
+
this.state.modal = 'rename';
|
|
306
|
+
this.state.inputBuffer = item.type === 'session'
|
|
307
|
+
? item.session?.title || ''
|
|
308
|
+
: item.worktree?.branch || '';
|
|
309
|
+
this.render();
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
toggleCollapsed: () => this.toggleCollapsed(),
|
|
313
|
+
createTerminal: () => this.createTerminal(),
|
|
314
|
+
render: () => this.render(),
|
|
315
|
+
},
|
|
316
|
+
};
|
|
317
|
+
// Execute command from map
|
|
318
|
+
(0, commands_1.executeCommand)(commands_1.MAIN_COMMANDS, key, context);
|
|
413
319
|
}
|
|
414
320
|
handleQuitModalInput(key) {
|
|
415
321
|
// Escape - close modal
|
|
@@ -559,20 +465,38 @@ class SidebarApp {
|
|
|
559
465
|
}
|
|
560
466
|
}
|
|
561
467
|
confirmTextInput(value) {
|
|
468
|
+
const trimmed = value.trim();
|
|
562
469
|
switch (this.state.modal) {
|
|
563
470
|
case 'new-worktree':
|
|
564
|
-
|
|
471
|
+
if (!(0, validation_1.isValidBranchName)(trimmed)) {
|
|
472
|
+
this.showError('Invalid branch name. Avoid special characters like ~ ^ : ? * [ ] \\');
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
this.createWorktree(trimmed);
|
|
565
476
|
break;
|
|
566
477
|
case 'rename':
|
|
567
|
-
|
|
478
|
+
if (!(0, validation_1.isValidSessionName)(trimmed)) {
|
|
479
|
+
this.showError('Invalid name. Please use a shorter name without control characters.');
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
this.renameSelected(trimmed);
|
|
568
483
|
break;
|
|
569
484
|
case 'new-session':
|
|
570
|
-
|
|
485
|
+
if (!(0, validation_1.isValidSessionName)(trimmed)) {
|
|
486
|
+
this.showError('Invalid session name. Please use a shorter name without control characters.');
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
// Check for duplicate session names
|
|
490
|
+
if (this.state.sessions.some(s => s.title === trimmed)) {
|
|
491
|
+
this.showError('A session with this name already exists.');
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
this.createSession(trimmed);
|
|
571
495
|
break;
|
|
572
496
|
}
|
|
573
497
|
}
|
|
574
498
|
handleClick(row, col) {
|
|
575
|
-
const cols = process.stdout.columns || SIDEBAR_WIDTH;
|
|
499
|
+
const cols = process.stdout.columns || constants_1.SIDEBAR_WIDTH;
|
|
576
500
|
if (this.state.collapsed) {
|
|
577
501
|
this.state.collapsed = false;
|
|
578
502
|
this.enforceSidebarWidth();
|
|
@@ -638,8 +562,8 @@ class SidebarApp {
|
|
|
638
562
|
this.render();
|
|
639
563
|
}
|
|
640
564
|
catch (err) {
|
|
641
|
-
|
|
642
|
-
this.showError(`Failed to create worktree: ${
|
|
565
|
+
logger.error('Failed to create worktree', err);
|
|
566
|
+
this.showError(`Failed to create worktree: ${(0, errors_1.getErrorMessage)(err)}`);
|
|
643
567
|
}
|
|
644
568
|
}
|
|
645
569
|
createSession(title) {
|
|
@@ -652,9 +576,9 @@ class SidebarApp {
|
|
|
652
576
|
}
|
|
653
577
|
const worktree = item.worktree;
|
|
654
578
|
debugLog('createSession: worktree=' + worktree.branch, 'path=' + worktree.path);
|
|
655
|
-
const sessionId =
|
|
579
|
+
const sessionId = sessionManager.generateSessionId();
|
|
656
580
|
let paneId;
|
|
657
|
-
const claudeCmd = DEFAULT_CLAUDE_CMD;
|
|
581
|
+
const claudeCmd = constants_1.DEFAULT_CLAUDE_CMD;
|
|
658
582
|
if (this.state.sessions.length === 0) {
|
|
659
583
|
// First session - use existing main pane
|
|
660
584
|
// If in fullscreen mode, the pane is broken but we can still send keys to it
|
|
@@ -734,10 +658,10 @@ class SidebarApp {
|
|
|
734
658
|
tmux.joinPane(activeTerminal.paneId, session.terminalBarPaneId, false);
|
|
735
659
|
}
|
|
736
660
|
// Ensure terminal bar is exactly 1 row
|
|
737
|
-
tmux.resizePane(session.terminalBarPaneId, undefined, TERMINAL_BAR_HEIGHT);
|
|
661
|
+
tmux.resizePane(session.terminalBarPaneId, undefined, constants_1.TERMINAL_BAR_HEIGHT);
|
|
738
662
|
// Update resize enforcement for this session's terminal bar
|
|
739
663
|
if (activeTerminal) {
|
|
740
|
-
setupTerminalBarResize(this.state.sessionName, session.paneId, session.terminalBarPaneId, activeTerminal.paneId);
|
|
664
|
+
(0, pane_orchestrator_1.setupTerminalBarResize)(this.state.sessionName, session.paneId, session.terminalBarPaneId, activeTerminal.paneId);
|
|
741
665
|
}
|
|
742
666
|
// Update terminal bar display
|
|
743
667
|
this.updateTerminalBar(session);
|
|
@@ -791,10 +715,10 @@ class SidebarApp {
|
|
|
791
715
|
if (activeTerminal) {
|
|
792
716
|
tmux.joinPane(activeTerminal.paneId, nextSession.terminalBarPaneId, false);
|
|
793
717
|
}
|
|
794
|
-
tmux.resizePane(nextSession.terminalBarPaneId, undefined, TERMINAL_BAR_HEIGHT);
|
|
718
|
+
tmux.resizePane(nextSession.terminalBarPaneId, undefined, constants_1.TERMINAL_BAR_HEIGHT);
|
|
795
719
|
// Update resize enforcement for the new session's terminal bar
|
|
796
720
|
if (activeTerminal) {
|
|
797
|
-
setupTerminalBarResize(this.state.sessionName, nextSession.paneId, nextSession.terminalBarPaneId, activeTerminal.paneId);
|
|
721
|
+
(0, pane_orchestrator_1.setupTerminalBarResize)(this.state.sessionName, nextSession.paneId, nextSession.terminalBarPaneId, activeTerminal.paneId);
|
|
798
722
|
}
|
|
799
723
|
this.updateTerminalBar(nextSession);
|
|
800
724
|
}
|
|
@@ -849,10 +773,10 @@ class SidebarApp {
|
|
|
849
773
|
if (activeTerminal) {
|
|
850
774
|
tmux.joinPane(activeTerminal.paneId, nextSession.terminalBarPaneId, false);
|
|
851
775
|
}
|
|
852
|
-
tmux.resizePane(nextSession.terminalBarPaneId, undefined, TERMINAL_BAR_HEIGHT);
|
|
776
|
+
tmux.resizePane(nextSession.terminalBarPaneId, undefined, constants_1.TERMINAL_BAR_HEIGHT);
|
|
853
777
|
// Update resize enforcement for the new session's terminal bar
|
|
854
778
|
if (activeTerminal) {
|
|
855
|
-
setupTerminalBarResize(this.state.sessionName, nextSession.paneId, nextSession.terminalBarPaneId, activeTerminal.paneId);
|
|
779
|
+
(0, pane_orchestrator_1.setupTerminalBarResize)(this.state.sessionName, nextSession.paneId, nextSession.terminalBarPaneId, activeTerminal.paneId);
|
|
856
780
|
}
|
|
857
781
|
this.updateTerminalBar(nextSession);
|
|
858
782
|
}
|
|
@@ -865,8 +789,8 @@ class SidebarApp {
|
|
|
865
789
|
await this.worktreeManager.remove(worktree.path, true);
|
|
866
790
|
}
|
|
867
791
|
catch (err) {
|
|
868
|
-
|
|
869
|
-
this.showError(`Failed to delete worktree: ${
|
|
792
|
+
logger.error('Failed to delete worktree', err);
|
|
793
|
+
this.showError(`Failed to delete worktree: ${(0, errors_1.getErrorMessage)(err)}`);
|
|
870
794
|
return;
|
|
871
795
|
}
|
|
872
796
|
// Remove from state
|
|
@@ -899,7 +823,7 @@ class SidebarApp {
|
|
|
899
823
|
}
|
|
900
824
|
enforceSidebarWidth() {
|
|
901
825
|
if (!this.state.collapsed) {
|
|
902
|
-
|
|
826
|
+
(0, pane_orchestrator_1.enforceSidebarWidth)(this.state.sidebarPaneId);
|
|
903
827
|
}
|
|
904
828
|
}
|
|
905
829
|
// ==========================================================================
|
|
@@ -923,7 +847,7 @@ class SidebarApp {
|
|
|
923
847
|
case 'switch':
|
|
924
848
|
const index = parseInt(data, 10);
|
|
925
849
|
if (!isNaN(index) && session) {
|
|
926
|
-
this.
|
|
850
|
+
this.switchToTerminal(session, index);
|
|
927
851
|
}
|
|
928
852
|
break;
|
|
929
853
|
case 'new':
|
|
@@ -964,22 +888,22 @@ class SidebarApp {
|
|
|
964
888
|
return;
|
|
965
889
|
const terminalNum = session.terminals.length + 1;
|
|
966
890
|
const terminalTitle = `Terminal ${terminalNum}`;
|
|
967
|
-
const terminalId =
|
|
891
|
+
const terminalId = terminalManager.generateTerminalId();
|
|
968
892
|
debugLog('createTerminal:', terminalTitle, 'for session', session.title);
|
|
969
893
|
if (session.terminals.length === 0) {
|
|
970
894
|
// First terminal - need to create terminal bar pane + terminal pane
|
|
971
895
|
// Split Claude pane vertically (Claude gets top 70%, terminal area gets bottom 30%)
|
|
972
896
|
tmux.selectPane(session.paneId);
|
|
973
|
-
const terminalAreaPaneId = tmux.splitVertical(this.state.sessionName, 100 - CLAUDE_PANE_PERCENT, worktree.path);
|
|
897
|
+
const terminalAreaPaneId = tmux.splitVertical(this.state.sessionName, 100 - constants_1.CLAUDE_PANE_PERCENT, worktree.path);
|
|
974
898
|
// Split terminal area: top 1 row for bar, rest for terminal
|
|
975
899
|
tmux.selectPane(terminalAreaPaneId);
|
|
976
900
|
const terminalPaneId = tmux.splitVertical(this.state.sessionName, 95, worktree.path);
|
|
977
901
|
// The terminalAreaPaneId is now the bar pane (top part after split)
|
|
978
902
|
const terminalBarPaneId = terminalAreaPaneId;
|
|
979
903
|
// Resize bar pane to exactly 1 row
|
|
980
|
-
tmux.resizePane(terminalBarPaneId, undefined, TERMINAL_BAR_HEIGHT);
|
|
904
|
+
tmux.resizePane(terminalBarPaneId, undefined, constants_1.TERMINAL_BAR_HEIGHT);
|
|
981
905
|
// Set up resize enforcement (hook + mouse binding)
|
|
982
|
-
setupTerminalBarResize(this.state.sessionName, session.paneId, terminalBarPaneId, terminalPaneId);
|
|
906
|
+
(0, pane_orchestrator_1.setupTerminalBarResize)(this.state.sessionName, session.paneId, terminalBarPaneId, terminalPaneId);
|
|
983
907
|
// Update session
|
|
984
908
|
session.terminalBarPaneId = terminalBarPaneId;
|
|
985
909
|
session.terminals.push({
|
|
@@ -1014,7 +938,7 @@ class SidebarApp {
|
|
|
1014
938
|
session.activeTerminalIndex = session.terminals.length - 1;
|
|
1015
939
|
// Ensure terminal bar stays at 1 row after the split
|
|
1016
940
|
if (session.terminalBarPaneId) {
|
|
1017
|
-
tmux.resizePane(session.terminalBarPaneId, undefined, TERMINAL_BAR_HEIGHT);
|
|
941
|
+
tmux.resizePane(session.terminalBarPaneId, undefined, constants_1.TERMINAL_BAR_HEIGHT);
|
|
1018
942
|
}
|
|
1019
943
|
// Update terminal bar
|
|
1020
944
|
this.updateTerminalBar(session);
|
|
@@ -1028,12 +952,12 @@ class SidebarApp {
|
|
|
1028
952
|
/**
|
|
1029
953
|
* Switch to a different terminal tab within a session
|
|
1030
954
|
*/
|
|
1031
|
-
|
|
955
|
+
switchToTerminal(session, targetIndex) {
|
|
1032
956
|
if (targetIndex < 0 || targetIndex >= session.terminals.length)
|
|
1033
957
|
return;
|
|
1034
958
|
if (targetIndex === session.activeTerminalIndex)
|
|
1035
959
|
return;
|
|
1036
|
-
debugLog('
|
|
960
|
+
debugLog('switchToTerminal:', targetIndex, 'in session', session.title);
|
|
1037
961
|
const currentTerminal = session.terminals[session.activeTerminalIndex];
|
|
1038
962
|
const newTerminal = session.terminals[targetIndex];
|
|
1039
963
|
// Break current terminal to background
|
|
@@ -1042,7 +966,7 @@ class SidebarApp {
|
|
|
1042
966
|
if (session.terminalBarPaneId) {
|
|
1043
967
|
tmux.joinPane(newTerminal.paneId, session.terminalBarPaneId, false);
|
|
1044
968
|
// Ensure terminal bar stays at 1 row
|
|
1045
|
-
tmux.resizePane(session.terminalBarPaneId, undefined, TERMINAL_BAR_HEIGHT);
|
|
969
|
+
tmux.resizePane(session.terminalBarPaneId, undefined, constants_1.TERMINAL_BAR_HEIGHT);
|
|
1046
970
|
}
|
|
1047
971
|
// Update active index
|
|
1048
972
|
session.activeTerminalIndex = targetIndex;
|
|
@@ -1091,7 +1015,7 @@ class SidebarApp {
|
|
|
1091
1015
|
const newActiveTerminal = session.terminals[session.activeTerminalIndex];
|
|
1092
1016
|
if (newActiveTerminal && session.terminalBarPaneId) {
|
|
1093
1017
|
tmux.joinPane(newActiveTerminal.paneId, session.terminalBarPaneId, false);
|
|
1094
|
-
tmux.resizePane(session.terminalBarPaneId, undefined, TERMINAL_BAR_HEIGHT);
|
|
1018
|
+
tmux.resizePane(session.terminalBarPaneId, undefined, constants_1.TERMINAL_BAR_HEIGHT);
|
|
1095
1019
|
}
|
|
1096
1020
|
}
|
|
1097
1021
|
// Update terminal bar
|
|
@@ -1218,7 +1142,7 @@ class SidebarApp {
|
|
|
1218
1142
|
tmux.joinPane(activeTerminal.paneId, activeSession.terminalBarPaneId, false);
|
|
1219
1143
|
}
|
|
1220
1144
|
// Ensure terminal bar is exactly 1 row
|
|
1221
|
-
tmux.resizePane(activeSession.terminalBarPaneId, undefined, TERMINAL_BAR_HEIGHT);
|
|
1145
|
+
tmux.resizePane(activeSession.terminalBarPaneId, undefined, constants_1.TERMINAL_BAR_HEIGHT);
|
|
1222
1146
|
// Update terminal bar display
|
|
1223
1147
|
this.updateTerminalBar(activeSession);
|
|
1224
1148
|
debugLog('exitFullscreenModal: joined terminal panes');
|