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.
Files changed (39) hide show
  1. package/dist/ansi.d.ts +42 -0
  2. package/dist/ansi.d.ts.map +1 -0
  3. package/dist/ansi.js +53 -0
  4. package/dist/ansi.js.map +1 -0
  5. package/dist/constants.d.ts +67 -0
  6. package/dist/constants.d.ts.map +1 -0
  7. package/dist/constants.js +109 -0
  8. package/dist/constants.js.map +1 -0
  9. package/dist/sidebar/app.d.ts +2 -1
  10. package/dist/sidebar/app.d.ts.map +1 -1
  11. package/dist/sidebar/app.js +129 -205
  12. package/dist/sidebar/app.js.map +1 -1
  13. package/dist/sidebar/commands.d.ts +64 -0
  14. package/dist/sidebar/commands.d.ts.map +1 -0
  15. package/dist/sidebar/commands.js +180 -0
  16. package/dist/sidebar/commands.js.map +1 -0
  17. package/dist/sidebar/pane-orchestrator.d.ts +31 -0
  18. package/dist/sidebar/pane-orchestrator.d.ts.map +1 -0
  19. package/dist/sidebar/pane-orchestrator.js +185 -0
  20. package/dist/sidebar/pane-orchestrator.js.map +1 -0
  21. package/dist/sidebar/render.d.ts +2 -23
  22. package/dist/sidebar/render.d.ts.map +1 -1
  23. package/dist/sidebar/render.js +100 -129
  24. package/dist/sidebar/render.js.map +1 -1
  25. package/dist/sidebar/session-manager.d.ts +23 -0
  26. package/dist/sidebar/session-manager.d.ts.map +1 -0
  27. package/dist/sidebar/session-manager.js +122 -0
  28. package/dist/sidebar/session-manager.js.map +1 -0
  29. package/dist/sidebar/terminal-manager.d.ts +48 -0
  30. package/dist/sidebar/terminal-manager.d.ts.map +1 -0
  31. package/dist/sidebar/terminal-manager.js +223 -0
  32. package/dist/sidebar/terminal-manager.js.map +1 -0
  33. package/dist/terminal/bar-handler.js +6 -19
  34. package/dist/terminal/bar-handler.js.map +1 -1
  35. package/dist/terminal/bar-render.d.ts.map +1 -1
  36. package/dist/terminal/bar-render.js +15 -35
  37. package/dist/terminal/bar-render.js.map +1 -1
  38. package/package.json +1 -2
  39. package/assets/screenshot.png +0 -0
@@ -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
- // Debug logging
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
- const msg = `[${new Date().toISOString()}] ${args.map(a => typeof a === 'object' ? JSON.stringify(a) : String(a)).join(' ')}\n`;
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
- // Ctrl+C - show quit modal (when sidebar is focused)
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
- // Ctrl+Q - show quit modal (works from any pane via tmux binding)
338
- if (key.ctrl && key.key === 'q') {
339
- this.enterFullscreenModal();
340
- this.state.modal = 'quit';
341
- this.state.modalSelection = 0;
342
- this.render();
343
- return;
344
- }
345
- // Ctrl+G - toggle collapsed
346
- if (key.ctrl && key.key === 'g') {
347
- this.toggleCollapsed();
348
- return;
349
- }
350
- // Ctrl+T - create new terminal for active session
351
- if (key.ctrl && key.key === 't') {
352
- this.createTerminal();
353
- return;
354
- }
355
- // Navigation
356
- if (key.key === 'up' || key.key === 'k') {
357
- this.state.selectedIndex = Math.max(0, this.state.selectedIndex - 1);
358
- this.render();
359
- return;
360
- }
361
- if (key.key === 'down' || key.key === 'j') {
362
- const maxIndex = this.getMaxIndex();
363
- this.state.selectedIndex = Math.min(maxIndex, this.state.selectedIndex + 1);
364
- this.render();
365
- return;
366
- }
367
- // Enter - activate selected
368
- if (key.key === 'enter') {
369
- debugLog('handleMainInput: enter pressed, calling activateSelected');
370
- this.activateSelected();
371
- return;
372
- }
373
- // n - new worktree
374
- if (key.key === 'n') {
375
- this.enterFullscreenModal();
376
- this.state.modal = 'new-worktree';
377
- this.state.inputBuffer = '';
378
- this.render();
379
- return;
380
- }
381
- // d - delete
382
- if (key.key === 'd') {
383
- const item = this.getSelectedItem();
384
- if (item && !(item.type === 'worktree' && item.worktree?.isMain)) {
385
- // Store delete target info for context in modal
386
- this.state.deleteTarget = {
387
- type: item.type,
388
- id: item.id,
389
- name: item.type === 'session' ? (item.session?.title || '') : (item.worktree?.branch || ''),
390
- worktree: item.worktree,
391
- session: item.session,
392
- };
393
- this.enterFullscreenModal();
394
- this.state.modal = 'delete';
395
- this.state.modalSelection = 0; // Default to No
396
- this.render();
397
- }
398
- return;
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
- this.createWorktree(value);
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
- this.renameSelected(value);
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
- this.createSession(value);
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
- const message = err instanceof Error ? err.message : String(err);
642
- this.showError(`Failed to create worktree: ${message}`);
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 = `session-${Date.now()}`;
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
- const message = err instanceof Error ? err.message : String(err);
869
- this.showError(`Failed to delete worktree: ${message}`);
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
- tmux.resizePane(this.state.sidebarPaneId, SIDEBAR_WIDTH);
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.switchTerminal(session, index);
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 = `terminal-${Date.now()}`;
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
- switchTerminal(session, targetIndex) {
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('switchTerminal:', targetIndex, 'in session', session.title);
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');