ccmanager 3.2.4 → 3.2.5

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.
@@ -54,6 +54,28 @@ describe('CodexStateDetector', () => {
54
54
  // Assert
55
55
  expect(state).toBe('waiting_input');
56
56
  });
57
+ it('should detect waiting_input state for "Press enter to confirm or esc to cancel" pattern', () => {
58
+ // Arrange
59
+ terminal = createMockTerminal([
60
+ 'Some output',
61
+ 'Press enter to confirm or esc to cancel',
62
+ ]);
63
+ // Act
64
+ const state = detector.detectState(terminal, 'idle');
65
+ // Assert
66
+ expect(state).toBe('waiting_input');
67
+ });
68
+ it('should prioritize "Press enter to confirm" over busy state with esc interrupt', () => {
69
+ // Arrange
70
+ terminal = createMockTerminal([
71
+ 'esc to interrupt',
72
+ 'Press enter to confirm or esc to cancel',
73
+ ]);
74
+ // Act
75
+ const state = detector.detectState(terminal, 'idle');
76
+ // Assert
77
+ expect(state).toBe('waiting_input');
78
+ });
57
79
  it('should detect busy state for Esc to interrupt pattern', () => {
58
80
  // Arrange
59
81
  terminal = createMockTerminal([
@@ -94,4 +116,31 @@ describe('CodexStateDetector', () => {
94
116
  // Assert
95
117
  expect(state).toBe('waiting_input');
96
118
  });
119
+ it('should detect waiting_input state for "Confirm with ... Enter" pattern', () => {
120
+ // Arrange
121
+ terminal = createMockTerminal(['Some output', 'Confirm with Y Enter']);
122
+ // Act
123
+ const state = detector.detectState(terminal, 'idle');
124
+ // Assert
125
+ expect(state).toBe('waiting_input');
126
+ });
127
+ it('should detect waiting_input for "Confirm with" pattern with longer text', () => {
128
+ // Arrange
129
+ terminal = createMockTerminal([
130
+ 'Some output',
131
+ 'Confirm with Shift + Y Enter',
132
+ ]);
133
+ // Act
134
+ const state = detector.detectState(terminal, 'idle');
135
+ // Assert
136
+ expect(state).toBe('waiting_input');
137
+ });
138
+ it('should prioritize "Confirm with ... Enter" over busy state', () => {
139
+ // Arrange
140
+ terminal = createMockTerminal(['Esc to interrupt', 'Confirm with Y Enter']);
141
+ // Act
142
+ const state = detector.detectState(terminal, 'idle');
143
+ // Assert
144
+ expect(state).toBe('waiting_input');
145
+ });
97
146
  });
@@ -20,6 +20,18 @@ describe('GeminiStateDetector', () => {
20
20
  // Assert
21
21
  expect(state).toBe('waiting_input');
22
22
  });
23
+ it('should detect waiting_input when "Apply this change" prompt is present (without ?)', () => {
24
+ // Arrange
25
+ terminal = createMockTerminal([
26
+ 'Some output from Gemini',
27
+ '│ Apply this change',
28
+ '│ > ',
29
+ ]);
30
+ // Act
31
+ const state = detector.detectState(terminal, 'idle');
32
+ // Assert
33
+ expect(state).toBe('waiting_input');
34
+ });
23
35
  it('should detect waiting_input when "Allow execution?" prompt is present', () => {
24
36
  // Arrange
25
37
  terminal = createMockTerminal([
@@ -32,6 +44,18 @@ describe('GeminiStateDetector', () => {
32
44
  // Assert
33
45
  expect(state).toBe('waiting_input');
34
46
  });
47
+ it('should detect waiting_input when "Allow execution" prompt is present (without ?)', () => {
48
+ // Arrange
49
+ terminal = createMockTerminal([
50
+ 'Command found: npm install',
51
+ '│ Allow execution',
52
+ '│ > ',
53
+ ]);
54
+ // Act
55
+ const state = detector.detectState(terminal, 'idle');
56
+ // Assert
57
+ expect(state).toBe('waiting_input');
58
+ });
35
59
  it('should detect waiting_input when "Do you want to proceed?" prompt is present', () => {
36
60
  // Arrange
37
61
  terminal = createMockTerminal([
@@ -44,6 +68,40 @@ describe('GeminiStateDetector', () => {
44
68
  // Assert
45
69
  expect(state).toBe('waiting_input');
46
70
  });
71
+ it('should detect waiting_input when "Do you want to proceed" prompt is present (without ?)', () => {
72
+ // Arrange
73
+ terminal = createMockTerminal([
74
+ 'Changes detected',
75
+ '│ Do you want to proceed',
76
+ '│ > ',
77
+ ]);
78
+ // Act
79
+ const state = detector.detectState(terminal, 'idle');
80
+ // Assert
81
+ expect(state).toBe('waiting_input');
82
+ });
83
+ it('should detect waiting_input when "Waiting for user confirmation..." is present', () => {
84
+ // Arrange
85
+ terminal = createMockTerminal([
86
+ 'Processing...',
87
+ 'Waiting for user confirmation...',
88
+ ]);
89
+ // Act
90
+ const state = detector.detectState(terminal, 'idle');
91
+ // Assert
92
+ expect(state).toBe('waiting_input');
93
+ });
94
+ it('should prioritize "Waiting for user confirmation" over busy state', () => {
95
+ // Arrange
96
+ terminal = createMockTerminal([
97
+ 'Press ESC to cancel',
98
+ 'Waiting for user confirmation...',
99
+ ]);
100
+ // Act
101
+ const state = detector.detectState(terminal, 'idle');
102
+ // Assert
103
+ expect(state).toBe('waiting_input');
104
+ });
47
105
  it('should detect waiting_input for multiline confirmation ending with "yes"', () => {
48
106
  // Arrange
49
107
  terminal = createMockTerminal([
@@ -19,6 +19,36 @@ describe('GitHubCopilotStateDetector', () => {
19
19
  // Assert
20
20
  expect(state).toBe('waiting_input');
21
21
  });
22
+ it('detects waiting_input when "Confirm with ... Enter" pattern is present', () => {
23
+ // Arrange
24
+ terminal = createMockTerminal(['Some output', 'Confirm with Y Enter']);
25
+ // Act
26
+ const state = detector.detectState(terminal, 'idle');
27
+ // Assert
28
+ expect(state).toBe('waiting_input');
29
+ });
30
+ it('detects waiting_input for "Confirm with" pattern with longer text', () => {
31
+ // Arrange
32
+ terminal = createMockTerminal([
33
+ 'Some output',
34
+ 'Confirm with Shift + Y Enter',
35
+ ]);
36
+ // Act
37
+ const state = detector.detectState(terminal, 'idle');
38
+ // Assert
39
+ expect(state).toBe('waiting_input');
40
+ });
41
+ it('prioritizes "Confirm with ... Enter" over busy state', () => {
42
+ // Arrange
43
+ terminal = createMockTerminal([
44
+ 'Press Esc to cancel',
45
+ 'Confirm with Y Enter',
46
+ ]);
47
+ // Act
48
+ const state = detector.detectState(terminal, 'idle');
49
+ // Assert
50
+ expect(state).toBe('waiting_input');
51
+ });
22
52
  it('detects busy when "Esc to cancel" is present', () => {
23
53
  // Arrange
24
54
  terminal = createMockTerminal([
@@ -63,10 +63,14 @@ export class GeminiStateDetector extends BaseStateDetector {
63
63
  detectState(terminal, _currentState) {
64
64
  const content = this.getTerminalContent(terminal);
65
65
  const lowerContent = content.toLowerCase();
66
+ // Check for explicit user confirmation message - highest priority
67
+ if (lowerContent.includes('waiting for user confirmation')) {
68
+ return 'waiting_input';
69
+ }
66
70
  // Check for waiting prompts with box character
67
- if (content.includes('│ Apply this change?') ||
68
- content.includes('│ Allow execution?') ||
69
- content.includes('│ Do you want to proceed?')) {
71
+ if (content.includes('│ Apply this change') ||
72
+ content.includes('│ Allow execution') ||
73
+ content.includes('│ Do you want to proceed')) {
70
74
  return 'waiting_input';
71
75
  }
72
76
  // Check for multiline confirmation prompts ending with "yes"
@@ -85,6 +89,11 @@ export class CodexStateDetector extends BaseStateDetector {
85
89
  detectState(terminal, _currentState) {
86
90
  const content = this.getTerminalContent(terminal);
87
91
  const lowerContent = content.toLowerCase();
92
+ // Check for confirmation prompt patterns - highest priority
93
+ if (lowerContent.includes('press enter to confirm or esc to cancel') ||
94
+ /confirm with .+ enter/i.test(content)) {
95
+ return 'waiting_input';
96
+ }
88
97
  // Check for waiting prompts
89
98
  if (lowerContent.includes('allow command?') ||
90
99
  lowerContent.includes('[y/n]') ||
@@ -124,15 +133,19 @@ export class GitHubCopilotStateDetector extends BaseStateDetector {
124
133
  detectState(terminal, _currentState) {
125
134
  const content = this.getTerminalContent(terminal);
126
135
  const lowerContent = content.toLowerCase();
127
- // Waiting prompt has priority 1
136
+ // Check for confirmation prompt pattern - highest priority
137
+ if (/confirm with .+ enter/i.test(content)) {
138
+ return 'waiting_input';
139
+ }
140
+ // Waiting prompt has priority 2
128
141
  if (lowerContent.includes('│ do you want')) {
129
142
  return 'waiting_input';
130
143
  }
131
- // Busy state detection has priority 2
144
+ // Busy state detection has priority 3
132
145
  if (lowerContent.includes('esc to cancel')) {
133
146
  return 'busy';
134
147
  }
135
- // Otherwise idle as priority 3
148
+ // Otherwise idle as priority 4
136
149
  return 'idle';
137
150
  }
138
151
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccmanager",
3
- "version": "3.2.4",
3
+ "version": "3.2.5",
4
4
  "description": "TUI application for managing multiple Claude Code sessions across Git worktrees",
5
5
  "license": "MIT",
6
6
  "author": "Kodai Kabasawa",
@@ -41,11 +41,11 @@
41
41
  "bin"
42
42
  ],
43
43
  "optionalDependencies": {
44
- "@kodaikabasawa/ccmanager-darwin-arm64": "3.2.4",
45
- "@kodaikabasawa/ccmanager-darwin-x64": "3.2.4",
46
- "@kodaikabasawa/ccmanager-linux-arm64": "3.2.4",
47
- "@kodaikabasawa/ccmanager-linux-x64": "3.2.4",
48
- "@kodaikabasawa/ccmanager-win32-x64": "3.2.4"
44
+ "@kodaikabasawa/ccmanager-darwin-arm64": "3.2.5",
45
+ "@kodaikabasawa/ccmanager-darwin-x64": "3.2.5",
46
+ "@kodaikabasawa/ccmanager-linux-arm64": "3.2.5",
47
+ "@kodaikabasawa/ccmanager-linux-x64": "3.2.5",
48
+ "@kodaikabasawa/ccmanager-win32-x64": "3.2.5"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@eslint/js": "^9.28.0",