ccmanager 3.1.0 → 3.1.1

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.
@@ -8,30 +8,6 @@ describe('ClaudeStateDetector', () => {
8
8
  detector = new ClaudeStateDetector();
9
9
  });
10
10
  describe('detectState', () => {
11
- it('should detect waiting_input when "Do you want" prompt is present', () => {
12
- // Arrange
13
- terminal = createMockTerminal([
14
- 'Some previous output',
15
- '│ Do you want to continue? (y/n)',
16
- '│ > ',
17
- ]);
18
- // Act
19
- const state = detector.detectState(terminal, 'idle');
20
- // Assert
21
- expect(state).toBe('waiting_input');
22
- });
23
- it('should detect waiting_input when "Would you like" prompt is present', () => {
24
- // Arrange
25
- terminal = createMockTerminal([
26
- 'Some output',
27
- '│ Would you like to save changes?',
28
- '│ > ',
29
- ]);
30
- // Act
31
- const state = detector.detectState(terminal, 'idle');
32
- // Assert
33
- expect(state).toBe('waiting_input');
34
- });
35
11
  it('should detect busy when "ESC to interrupt" is present', () => {
36
12
  // Arrange
37
13
  terminal = createMockTerminal([
@@ -74,37 +50,6 @@ describe('ClaudeStateDetector', () => {
74
50
  // Assert
75
51
  expect(state).toBe('idle');
76
52
  });
77
- it('should only consider last 30 lines', () => {
78
- // Arrange
79
- const lines = [];
80
- // Add more than 30 lines
81
- for (let i = 0; i < 40; i++) {
82
- lines.push(`Line ${i}`);
83
- }
84
- // The "Do you want" should be outside the 30 line window
85
- lines.push('│ Do you want to continue?');
86
- // Add 30 more lines to push it out
87
- for (let i = 0; i < 30; i++) {
88
- lines.push(`Recent line ${i}`);
89
- }
90
- terminal = createMockTerminal(lines);
91
- // Act
92
- const state = detector.detectState(terminal, 'idle');
93
- // Assert
94
- expect(state).toBe('idle'); // Should not detect the old prompt
95
- });
96
- it('should prioritize waiting_input over busy state', () => {
97
- // Arrange
98
- terminal = createMockTerminal([
99
- 'Press ESC to interrupt',
100
- '│ Do you want to continue?',
101
- '│ > ',
102
- ]);
103
- // Act
104
- const state = detector.detectState(terminal, 'idle');
105
- // Assert
106
- expect(state).toBe('waiting_input'); // waiting_input should take precedence
107
- });
108
53
  it('should maintain current state when "ctrl+r to toggle" is present', () => {
109
54
  // Arrange
110
55
  terminal = createMockTerminal([
@@ -222,91 +167,5 @@ describe('ClaudeStateDetector', () => {
222
167
  // Assert
223
168
  expect(state).toBe('waiting_input');
224
169
  });
225
- it('should detect waiting_input when "enter to select" is present', () => {
226
- // Arrange
227
- terminal = createMockTerminal([
228
- 'Select an option:',
229
- '',
230
- '❯ Option 1',
231
- ' Option 2',
232
- '',
233
- 'Enter to select',
234
- ]);
235
- // Act
236
- const state = detector.detectState(terminal, 'idle');
237
- // Assert
238
- expect(state).toBe('waiting_input');
239
- });
240
- it('should detect waiting_input when "tab/arrow keys to navigate" is present', () => {
241
- // Arrange
242
- terminal = createMockTerminal([
243
- 'Choose your action:',
244
- '',
245
- '❯ Continue',
246
- ' Skip',
247
- '',
248
- 'Tab/arrow keys to navigate',
249
- ]);
250
- // Act
251
- const state = detector.detectState(terminal, 'idle');
252
- // Assert
253
- expect(state).toBe('waiting_input');
254
- });
255
- it('should detect waiting_input when "esc to cancel" is present', () => {
256
- // Arrange
257
- terminal = createMockTerminal([
258
- 'Interactive selection:',
259
- '',
260
- '❯ Yes',
261
- ' No',
262
- '',
263
- 'Esc to cancel',
264
- ]);
265
- // Act
266
- const state = detector.detectState(terminal, 'idle');
267
- // Assert
268
- expect(state).toBe('waiting_input');
269
- });
270
- it('should detect waiting_input when "ready to submit your answers?" is present', () => {
271
- // Arrange
272
- terminal = createMockTerminal([
273
- 'Review your selections:',
274
- '',
275
- 'Choice 1: Yes',
276
- 'Choice 2: No',
277
- '',
278
- 'Ready to submit your answers?',
279
- ]);
280
- // Act
281
- const state = detector.detectState(terminal, 'idle');
282
- // Assert
283
- expect(state).toBe('waiting_input');
284
- });
285
- it('should detect waiting_input with mixed case interactive patterns', () => {
286
- // Arrange
287
- terminal = createMockTerminal([
288
- 'Select options:',
289
- '',
290
- 'ENTER TO SELECT',
291
- 'TAB/ARROW KEYS TO NAVIGATE',
292
- ]);
293
- // Act
294
- const state = detector.detectState(terminal, 'idle');
295
- // Assert
296
- expect(state).toBe('waiting_input');
297
- });
298
- it('should prioritize interactive patterns over busy state', () => {
299
- // Arrange
300
- terminal = createMockTerminal([
301
- 'Press ESC to interrupt',
302
- '',
303
- 'Select an option:',
304
- 'Enter to select',
305
- ]);
306
- // Act
307
- const state = detector.detectState(terminal, 'idle');
308
- // Assert
309
- expect(state).toBe('waiting_input'); // Interactive pattern should take precedence
310
- });
311
170
  });
312
171
  });
@@ -127,7 +127,7 @@ describe('SessionManager - State Persistence', () => {
127
127
  vi.advanceTimersByTime(STATE_CHECK_INTERVAL_MS * 2);
128
128
  expect(session.pendingState).toBe('idle');
129
129
  // Simulate output that would trigger waiting_input state
130
- eventEmitter.emit('data', 'Do you want to continue?');
130
+ eventEmitter.emit('data', 'Do you want to continue?\n❯ 1. Yes');
131
131
  // Advance time to trigger another check
132
132
  vi.advanceTimersByTime(STATE_CHECK_INTERVAL_MS);
133
133
  // Pending state should now be waiting_input, not idle
@@ -172,7 +172,7 @@ describe('SessionManager - State Persistence', () => {
172
172
  expect(session.pendingState).toBe('idle');
173
173
  // Now change to a different state before idle persists
174
174
  // Clear terminal first and add waiting prompt
175
- eventEmitter.emit('data', '\x1b[2J\x1b[H│ Do you want to continue?\n');
175
+ eventEmitter.emit('data', '\x1b[2J\x1b[HDo you want to continue?\n❯ 1. Yes');
176
176
  // Advance time to detect new state but still less than persistence duration from first change
177
177
  vi.advanceTimersByTime(STATE_CHECK_INTERVAL_MS); // Another 100ms, total 200ms exactly at threshold
178
178
  // Pending state should have changed to waiting_input
@@ -210,7 +210,7 @@ describe('SessionManager - State Persistence', () => {
210
210
  // Session 1 goes to idle
211
211
  eventEmitter1.emit('data', 'Idle output for session 1');
212
212
  // Session 2 goes to waiting_input
213
- eventEmitter2.emit('data', 'Do you want to continue?');
213
+ eventEmitter2.emit('data', 'Do you want to continue?\n❯ 1. Yes');
214
214
  // Advance time to check but not confirm
215
215
  vi.advanceTimersByTime(STATE_CHECK_INTERVAL_MS * 2);
216
216
  // Both should have pending states but not changed yet
@@ -45,20 +45,6 @@ export class ClaudeStateDetector extends BaseStateDetector {
45
45
  if (lowerContent.includes('ctrl+r to toggle')) {
46
46
  return currentState;
47
47
  }
48
- // Check for interactive selection interface patterns
49
- // These patterns indicate Claude is waiting for user interaction with navigation/selection UI
50
- const hasInteractivePattern = lowerContent.includes('enter to select') ||
51
- lowerContent.includes('tab/arrow keys to navigate') ||
52
- lowerContent.includes('esc to cancel') ||
53
- lowerContent.includes('ready to submit your answers?');
54
- if (hasInteractivePattern) {
55
- return 'waiting_input';
56
- }
57
- // Check for waiting prompts with box character
58
- if (content.includes('│ Do you want') ||
59
- content.includes('│ Would you like')) {
60
- return 'waiting_input';
61
- }
62
48
  // Check for "Do you want" or "Would you like" pattern with options
63
49
  // Handles both simple ("Do you want...\nYes") and complex (numbered options) formats
64
50
  if (/(?:do you want|would you like).+\n+[\s\S]*?(?:yes|❯)/.test(lowerContent)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccmanager",
3
- "version": "3.1.0",
3
+ "version": "3.1.1",
4
4
  "description": "TUI application for managing multiple Claude Code sessions across Git worktrees",
5
5
  "license": "MIT",
6
6
  "author": "Kodai Kabasawa",