create-claude-workspace 1.1.103 → 1.1.104
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.
|
@@ -148,7 +148,7 @@ Options:
|
|
|
148
148
|
--max-turns <n> Max turns per Claude invocation (default: 50)
|
|
149
149
|
--delay <ms> Pause between tasks (default: 5000)
|
|
150
150
|
--cooldown <ms> Wait after error (default: 60000)
|
|
151
|
-
--process-timeout <ms> Max wall-clock time per invocation (default:
|
|
151
|
+
--process-timeout <ms> Max wall-clock time per invocation (default: 14400000 = 4h)
|
|
152
152
|
--activity-timeout <ms> Max silence before kill (default: 900000 = 15min)
|
|
153
153
|
--post-result-timeout <ms> Max wait after result (default: 30000 = 30s)
|
|
154
154
|
--project-dir <path> Project directory (default: cwd)
|
|
@@ -21,21 +21,22 @@ export function classifyError(signals) {
|
|
|
21
21
|
return 'auth_expired';
|
|
22
22
|
if (signals.isAuthServerError)
|
|
23
23
|
return 'auth_server_error';
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (signals.isRateLimit)
|
|
28
|
-
return 'rate_limited';
|
|
24
|
+
// Timeouts take priority over rate limit — timeout is the actual kill reason,
|
|
25
|
+
// rate limit is just a transient event that may have occurred during a 2h+ run.
|
|
26
|
+
// Without this, a normal process_timeout gets misclassified as rate_limited.
|
|
29
27
|
if (signals.timedOut) {
|
|
30
|
-
// Double-check stderr for auth errors (may not have been caught by stream events)
|
|
31
28
|
if (/authentication_error|failed to authenticate|api error: 401|oauth token has expired/i.test(signals.stderr)) {
|
|
32
29
|
return 'auth_expired';
|
|
33
30
|
}
|
|
34
31
|
return 'process_timeout';
|
|
35
32
|
}
|
|
36
|
-
// Activity timeout after result = success (process just hung after finishing)
|
|
37
33
|
if (signals.activityTimedOut)
|
|
38
34
|
return signals.hasResult ? 'none' : 'activity_timeout';
|
|
35
|
+
// Usage limit (account quota) takes priority over rate limit — it's hours, not seconds
|
|
36
|
+
if (signals.isUsageLimit)
|
|
37
|
+
return 'usage_limit';
|
|
38
|
+
if (signals.isRateLimit)
|
|
39
|
+
return 'rate_limited';
|
|
39
40
|
// Clean exit
|
|
40
41
|
if (signals.code === 0)
|
|
41
42
|
return 'none';
|
|
@@ -78,9 +78,15 @@ describe('classifyError', () => {
|
|
|
78
78
|
it('flag priority: auth flag wins over stderr patterns', () => {
|
|
79
79
|
expect(classifyError({ ...base, isAuthError: true, stderr: 'rate limit' })).toBe('auth_expired');
|
|
80
80
|
});
|
|
81
|
-
it('flag priority: rate limit flag
|
|
81
|
+
it('flag priority: rate limit flag detected when not timed out', () => {
|
|
82
82
|
expect(classifyError({ ...base, isRateLimit: true, timedOut: false })).toBe('rate_limited');
|
|
83
83
|
});
|
|
84
|
+
it('flag priority: timeout wins over rate limit (rate limit is transient during long run)', () => {
|
|
85
|
+
expect(classifyError({ ...base, isRateLimit: true, timedOut: true })).toBe('process_timeout');
|
|
86
|
+
});
|
|
87
|
+
it('flag priority: activity timeout wins over rate limit', () => {
|
|
88
|
+
expect(classifyError({ ...base, isRateLimit: true, activityTimedOut: true })).toBe('activity_timeout');
|
|
89
|
+
});
|
|
84
90
|
it('returns none when clean exit with result despite transient rate limit', () => {
|
|
85
91
|
expect(classifyError({ ...base, code: 0, hasResult: true, isRateLimit: true })).toBe('none');
|
|
86
92
|
});
|
|
@@ -659,8 +659,8 @@ describe('Loop integration: classifyError → getErrorAction → checkpoint', ()
|
|
|
659
659
|
it('auth error beats auth server error', () => {
|
|
660
660
|
expect(classifyError({ ...base, isAuthError: true, isAuthServerError: true })).toBe('auth_expired');
|
|
661
661
|
});
|
|
662
|
-
it('
|
|
663
|
-
expect(classifyError({ ...base, code: 1, isRateLimit: true, timedOut: true })).toBe('
|
|
662
|
+
it('process timeout beats rate limit (timeout is actual kill reason, rate limit is transient)', () => {
|
|
663
|
+
expect(classifyError({ ...base, code: 1, isRateLimit: true, timedOut: true })).toBe('process_timeout');
|
|
664
664
|
});
|
|
665
665
|
it('process timeout beats activity timeout', () => {
|
|
666
666
|
expect(classifyError({ ...base, timedOut: true, activityTimedOut: true })).toBe('process_timeout');
|
|
@@ -7,7 +7,7 @@ export const DEFAULTS = {
|
|
|
7
7
|
projectDir: process.cwd(),
|
|
8
8
|
skipPermissions: false,
|
|
9
9
|
resumeSession: null,
|
|
10
|
-
processTimeout:
|
|
10
|
+
processTimeout: 4 * 60 * 60_000,
|
|
11
11
|
activityTimeout: 15 * 60_000,
|
|
12
12
|
postResultTimeout: 30_000,
|
|
13
13
|
logFile: '.claude/autonomous.log',
|