cc-reviewer 1.0.4 → 1.0.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.
- package/dist/cli/codex.js +32 -11
- package/dist/cli/gemini.js +32 -11
- package/package.json +1 -1
package/dist/cli/codex.js
CHANGED
|
@@ -8,7 +8,9 @@ import { spawn } from 'child_process';
|
|
|
8
8
|
import { existsSync } from 'fs';
|
|
9
9
|
import { build7SectionPrompt, buildDeveloperInstructions, buildRetryPrompt, isValidFeedbackOutput } from '../prompt.js';
|
|
10
10
|
import { createTimeoutError, createCliNotFoundError, getSuggestion } from '../errors.js';
|
|
11
|
-
|
|
11
|
+
// Activity-based timeout: reset on output, kill on silence
|
|
12
|
+
const INACTIVITY_TIMEOUT_MS = 120000; // 2 min of no output = timeout
|
|
13
|
+
const MAX_TIMEOUT_MS = 3600000; // 60 min absolute max (edge case safety)
|
|
12
14
|
const MAX_RETRIES = 2;
|
|
13
15
|
const MAX_BUFFER_SIZE = 1024 * 1024; // 1MB max buffer to prevent memory issues
|
|
14
16
|
/**
|
|
@@ -136,11 +138,15 @@ async function runWithRetry(request, attempt, previousError, previousOutput) {
|
|
|
136
138
|
model: 'codex'
|
|
137
139
|
};
|
|
138
140
|
}
|
|
139
|
-
if (err.message === 'TIMEOUT') {
|
|
141
|
+
if (err.message === 'TIMEOUT' || err.message === 'MAX_TIMEOUT') {
|
|
142
|
+
const isMaxTimeout = err.message === 'MAX_TIMEOUT';
|
|
143
|
+
const timeoutMs = isMaxTimeout ? MAX_TIMEOUT_MS : INACTIVITY_TIMEOUT_MS;
|
|
140
144
|
return {
|
|
141
145
|
success: false,
|
|
142
|
-
error: createTimeoutError('codex',
|
|
143
|
-
suggestion:
|
|
146
|
+
error: createTimeoutError('codex', timeoutMs),
|
|
147
|
+
suggestion: isMaxTimeout
|
|
148
|
+
? 'Task exceeded 60 minute maximum. Try a smaller scope.'
|
|
149
|
+
: 'No output for 2 minutes. Process may be hung. Try a smaller scope or use --focus.',
|
|
144
150
|
model: 'codex'
|
|
145
151
|
};
|
|
146
152
|
}
|
|
@@ -185,7 +191,24 @@ function runCodexCli(prompt, workingDir, reasoningEffort = 'high') {
|
|
|
185
191
|
let stdout = '';
|
|
186
192
|
let stderr = '';
|
|
187
193
|
let truncated = false;
|
|
194
|
+
let inactivityTimer;
|
|
195
|
+
// Max timeout - absolute cap (60 min)
|
|
196
|
+
const maxTimer = setTimeout(() => {
|
|
197
|
+
proc.kill('SIGTERM');
|
|
198
|
+
reject(new Error('MAX_TIMEOUT'));
|
|
199
|
+
}, MAX_TIMEOUT_MS);
|
|
200
|
+
// Activity-based timeout - reset on any output
|
|
201
|
+
const resetInactivityTimer = () => {
|
|
202
|
+
clearTimeout(inactivityTimer);
|
|
203
|
+
inactivityTimer = setTimeout(() => {
|
|
204
|
+
proc.kill('SIGTERM');
|
|
205
|
+
reject(new Error('TIMEOUT'));
|
|
206
|
+
}, INACTIVITY_TIMEOUT_MS);
|
|
207
|
+
};
|
|
208
|
+
// Start inactivity timer
|
|
209
|
+
resetInactivityTimer();
|
|
188
210
|
proc.stdout.on('data', (data) => {
|
|
211
|
+
resetInactivityTimer(); // Still streaming = reset timer
|
|
189
212
|
if (stdout.length < MAX_BUFFER_SIZE) {
|
|
190
213
|
stdout += data.toString();
|
|
191
214
|
if (stdout.length > MAX_BUFFER_SIZE) {
|
|
@@ -195,6 +218,7 @@ function runCodexCli(prompt, workingDir, reasoningEffort = 'high') {
|
|
|
195
218
|
}
|
|
196
219
|
});
|
|
197
220
|
proc.stderr.on('data', (data) => {
|
|
221
|
+
resetInactivityTimer(); // Still streaming = reset timer
|
|
198
222
|
if (stderr.length < MAX_BUFFER_SIZE) {
|
|
199
223
|
stderr += data.toString();
|
|
200
224
|
if (stderr.length > MAX_BUFFER_SIZE) {
|
|
@@ -202,13 +226,9 @@ function runCodexCli(prompt, workingDir, reasoningEffort = 'high') {
|
|
|
202
226
|
}
|
|
203
227
|
}
|
|
204
228
|
});
|
|
205
|
-
// Timeout handling
|
|
206
|
-
const timeout = setTimeout(() => {
|
|
207
|
-
proc.kill('SIGTERM');
|
|
208
|
-
reject(new Error('TIMEOUT'));
|
|
209
|
-
}, TIMEOUT_MS);
|
|
210
229
|
proc.on('close', (code) => {
|
|
211
|
-
clearTimeout(
|
|
230
|
+
clearTimeout(inactivityTimer);
|
|
231
|
+
clearTimeout(maxTimer);
|
|
212
232
|
resolve({
|
|
213
233
|
stdout,
|
|
214
234
|
stderr,
|
|
@@ -217,7 +237,8 @@ function runCodexCli(prompt, workingDir, reasoningEffort = 'high') {
|
|
|
217
237
|
});
|
|
218
238
|
});
|
|
219
239
|
proc.on('error', (err) => {
|
|
220
|
-
clearTimeout(
|
|
240
|
+
clearTimeout(inactivityTimer);
|
|
241
|
+
clearTimeout(maxTimer);
|
|
221
242
|
reject(err);
|
|
222
243
|
});
|
|
223
244
|
});
|
package/dist/cli/gemini.js
CHANGED
|
@@ -9,7 +9,9 @@ import { spawn } from 'child_process';
|
|
|
9
9
|
import { existsSync } from 'fs';
|
|
10
10
|
import { build7SectionPrompt, buildDeveloperInstructions, buildRetryPrompt, isValidFeedbackOutput } from '../prompt.js';
|
|
11
11
|
import { createTimeoutError, createCliNotFoundError, getSuggestion } from '../errors.js';
|
|
12
|
-
|
|
12
|
+
// Activity-based timeout: reset on output, kill on silence
|
|
13
|
+
const INACTIVITY_TIMEOUT_MS = 120000; // 2 min of no output = timeout
|
|
14
|
+
const MAX_TIMEOUT_MS = 3600000; // 60 min absolute max (edge case safety)
|
|
13
15
|
const MAX_RETRIES = 2;
|
|
14
16
|
const MAX_BUFFER_SIZE = 1024 * 1024; // 1MB max buffer to prevent memory issues
|
|
15
17
|
/**
|
|
@@ -139,11 +141,15 @@ async function runWithRetry(request, attempt, previousError, previousOutput) {
|
|
|
139
141
|
model: 'gemini'
|
|
140
142
|
};
|
|
141
143
|
}
|
|
142
|
-
if (err.message === 'TIMEOUT') {
|
|
144
|
+
if (err.message === 'TIMEOUT' || err.message === 'MAX_TIMEOUT') {
|
|
145
|
+
const isMaxTimeout = err.message === 'MAX_TIMEOUT';
|
|
146
|
+
const timeoutMs = isMaxTimeout ? MAX_TIMEOUT_MS : INACTIVITY_TIMEOUT_MS;
|
|
143
147
|
return {
|
|
144
148
|
success: false,
|
|
145
|
-
error: createTimeoutError('gemini',
|
|
146
|
-
suggestion:
|
|
149
|
+
error: createTimeoutError('gemini', timeoutMs),
|
|
150
|
+
suggestion: isMaxTimeout
|
|
151
|
+
? 'Task exceeded 60 minute maximum. Try a smaller scope.'
|
|
152
|
+
: 'No output for 2 minutes. Process may be hung. Try a smaller scope or use --focus.',
|
|
147
153
|
model: 'gemini'
|
|
148
154
|
};
|
|
149
155
|
}
|
|
@@ -182,7 +188,24 @@ function runGeminiCli(prompt, workingDir) {
|
|
|
182
188
|
let stdout = '';
|
|
183
189
|
let stderr = '';
|
|
184
190
|
let truncated = false;
|
|
191
|
+
let inactivityTimer;
|
|
192
|
+
// Max timeout - absolute cap (60 min)
|
|
193
|
+
const maxTimer = setTimeout(() => {
|
|
194
|
+
proc.kill('SIGTERM');
|
|
195
|
+
reject(new Error('MAX_TIMEOUT'));
|
|
196
|
+
}, MAX_TIMEOUT_MS);
|
|
197
|
+
// Activity-based timeout - reset on any output
|
|
198
|
+
const resetInactivityTimer = () => {
|
|
199
|
+
clearTimeout(inactivityTimer);
|
|
200
|
+
inactivityTimer = setTimeout(() => {
|
|
201
|
+
proc.kill('SIGTERM');
|
|
202
|
+
reject(new Error('TIMEOUT'));
|
|
203
|
+
}, INACTIVITY_TIMEOUT_MS);
|
|
204
|
+
};
|
|
205
|
+
// Start inactivity timer
|
|
206
|
+
resetInactivityTimer();
|
|
185
207
|
proc.stdout.on('data', (data) => {
|
|
208
|
+
resetInactivityTimer(); // Still streaming = reset timer
|
|
186
209
|
if (stdout.length < MAX_BUFFER_SIZE) {
|
|
187
210
|
stdout += data.toString();
|
|
188
211
|
if (stdout.length > MAX_BUFFER_SIZE) {
|
|
@@ -192,6 +215,7 @@ function runGeminiCli(prompt, workingDir) {
|
|
|
192
215
|
}
|
|
193
216
|
});
|
|
194
217
|
proc.stderr.on('data', (data) => {
|
|
218
|
+
resetInactivityTimer(); // Still streaming = reset timer
|
|
195
219
|
if (stderr.length < MAX_BUFFER_SIZE) {
|
|
196
220
|
stderr += data.toString();
|
|
197
221
|
if (stderr.length > MAX_BUFFER_SIZE) {
|
|
@@ -199,13 +223,9 @@ function runGeminiCli(prompt, workingDir) {
|
|
|
199
223
|
}
|
|
200
224
|
}
|
|
201
225
|
});
|
|
202
|
-
// Timeout handling
|
|
203
|
-
const timeout = setTimeout(() => {
|
|
204
|
-
proc.kill('SIGTERM');
|
|
205
|
-
reject(new Error('TIMEOUT'));
|
|
206
|
-
}, TIMEOUT_MS);
|
|
207
226
|
proc.on('close', (code) => {
|
|
208
|
-
clearTimeout(
|
|
227
|
+
clearTimeout(inactivityTimer);
|
|
228
|
+
clearTimeout(maxTimer);
|
|
209
229
|
resolve({
|
|
210
230
|
stdout,
|
|
211
231
|
stderr,
|
|
@@ -214,7 +234,8 @@ function runGeminiCli(prompt, workingDir) {
|
|
|
214
234
|
});
|
|
215
235
|
});
|
|
216
236
|
proc.on('error', (err) => {
|
|
217
|
-
clearTimeout(
|
|
237
|
+
clearTimeout(inactivityTimer);
|
|
238
|
+
clearTimeout(maxTimer);
|
|
218
239
|
reject(err);
|
|
219
240
|
});
|
|
220
241
|
});
|