ccmanager 3.0.0 → 3.1.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.
- package/dist/components/ConfigureOther.js +26 -0
- package/dist/components/ConfigureTimeout.d.ts +9 -0
- package/dist/components/ConfigureTimeout.js +42 -0
- package/dist/services/autoApprovalVerifier.js +12 -5
- package/dist/services/configurationManager.d.ts +1 -0
- package/dist/services/configurationManager.js +27 -6
- package/dist/types/index.d.ts +1 -0
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@ import SelectInput from 'ink-select-input';
|
|
|
4
4
|
import { configurationManager } from '../services/configurationManager.js';
|
|
5
5
|
import { shortcutManager } from '../services/shortcutManager.js';
|
|
6
6
|
import ConfigureCustomCommand from './ConfigureCustomCommand.js';
|
|
7
|
+
import ConfigureTimeout from './ConfigureTimeout.js';
|
|
7
8
|
import CustomCommandSummary from './CustomCommandSummary.js';
|
|
8
9
|
const ConfigureOther = ({ onComplete }) => {
|
|
9
10
|
const autoApprovalConfig = configurationManager.getAutoApprovalConfig();
|
|
@@ -11,6 +12,8 @@ const ConfigureOther = ({ onComplete }) => {
|
|
|
11
12
|
const [autoApprovalEnabled, setAutoApprovalEnabled] = useState(autoApprovalConfig.enabled);
|
|
12
13
|
const [customCommand, setCustomCommand] = useState(autoApprovalConfig.customCommand ?? '');
|
|
13
14
|
const [customCommandDraft, setCustomCommandDraft] = useState(customCommand);
|
|
15
|
+
const [timeout, setTimeout] = useState(autoApprovalConfig.timeout ?? 30);
|
|
16
|
+
const [timeoutDraft, setTimeoutDraft] = useState(timeout);
|
|
14
17
|
useInput((input, key) => {
|
|
15
18
|
if (shortcutManager.matchesShortcut('cancel', input, key)) {
|
|
16
19
|
if (view === 'customCommand') {
|
|
@@ -18,6 +21,11 @@ const ConfigureOther = ({ onComplete }) => {
|
|
|
18
21
|
setView('main');
|
|
19
22
|
return;
|
|
20
23
|
}
|
|
24
|
+
if (view === 'timeout') {
|
|
25
|
+
setTimeoutDraft(timeout);
|
|
26
|
+
setView('main');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
21
29
|
onComplete();
|
|
22
30
|
}
|
|
23
31
|
});
|
|
@@ -30,6 +38,10 @@ const ConfigureOther = ({ onComplete }) => {
|
|
|
30
38
|
label: '✏️ Edit Custom Command',
|
|
31
39
|
value: 'customCommand',
|
|
32
40
|
},
|
|
41
|
+
{
|
|
42
|
+
label: `⏱️ Set Timeout (${timeout}s)`,
|
|
43
|
+
value: 'timeout',
|
|
44
|
+
},
|
|
33
45
|
{
|
|
34
46
|
label: '💾 Save Changes',
|
|
35
47
|
value: 'save',
|
|
@@ -48,10 +60,15 @@ const ConfigureOther = ({ onComplete }) => {
|
|
|
48
60
|
setCustomCommandDraft(customCommand);
|
|
49
61
|
setView('customCommand');
|
|
50
62
|
break;
|
|
63
|
+
case 'timeout':
|
|
64
|
+
setTimeoutDraft(timeout);
|
|
65
|
+
setView('timeout');
|
|
66
|
+
break;
|
|
51
67
|
case 'save':
|
|
52
68
|
configurationManager.setAutoApprovalConfig({
|
|
53
69
|
enabled: autoApprovalEnabled,
|
|
54
70
|
customCommand: customCommand.trim() || undefined,
|
|
71
|
+
timeout,
|
|
55
72
|
});
|
|
56
73
|
onComplete();
|
|
57
74
|
break;
|
|
@@ -71,6 +88,15 @@ const ConfigureOther = ({ onComplete }) => {
|
|
|
71
88
|
setView('main');
|
|
72
89
|
} }));
|
|
73
90
|
}
|
|
91
|
+
if (view === 'timeout') {
|
|
92
|
+
return (React.createElement(ConfigureTimeout, { value: timeoutDraft, onChange: setTimeoutDraft, onCancel: () => {
|
|
93
|
+
setTimeoutDraft(timeout);
|
|
94
|
+
setView('main');
|
|
95
|
+
}, onSubmit: value => {
|
|
96
|
+
setTimeout(value);
|
|
97
|
+
setView('main');
|
|
98
|
+
} }));
|
|
99
|
+
}
|
|
74
100
|
return (React.createElement(Box, { flexDirection: "column" },
|
|
75
101
|
React.createElement(Box, { marginBottom: 1 },
|
|
76
102
|
React.createElement(Text, { bold: true, color: "green" }, "Other & Experimental Settings")),
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface ConfigureTimeoutProps {
|
|
3
|
+
value: number;
|
|
4
|
+
onChange: (value: number) => void;
|
|
5
|
+
onSubmit: (value: number) => void;
|
|
6
|
+
onCancel: () => void;
|
|
7
|
+
}
|
|
8
|
+
declare const ConfigureTimeout: React.FC<ConfigureTimeoutProps>;
|
|
9
|
+
export default ConfigureTimeout;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Box, Text, useInput } from 'ink';
|
|
3
|
+
import TextInputWrapper from './TextInputWrapper.js';
|
|
4
|
+
import { shortcutManager } from '../services/shortcutManager.js';
|
|
5
|
+
const ConfigureTimeout = ({ value, onChange, onSubmit, onCancel, }) => {
|
|
6
|
+
const [inputValue, setInputValue] = React.useState(String(value));
|
|
7
|
+
const handleChange = (newValue) => {
|
|
8
|
+
// Only allow numeric input
|
|
9
|
+
const filtered = newValue.replace(/[^0-9]/g, '');
|
|
10
|
+
setInputValue(filtered);
|
|
11
|
+
const parsed = parseInt(filtered, 10);
|
|
12
|
+
if (!isNaN(parsed) && parsed > 0) {
|
|
13
|
+
onChange(parsed);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
const handleSubmit = () => {
|
|
17
|
+
const parsed = parseInt(inputValue, 10);
|
|
18
|
+
if (!isNaN(parsed) && parsed > 0) {
|
|
19
|
+
onSubmit(parsed);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
useInput((input, key) => {
|
|
23
|
+
if (shortcutManager.matchesShortcut('cancel', input, key)) {
|
|
24
|
+
onCancel();
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
return (React.createElement(Box, { flexDirection: "column" },
|
|
28
|
+
React.createElement(Box, { marginBottom: 1 },
|
|
29
|
+
React.createElement(Text, { bold: true, color: "green" }, "Auto-Approval Timeout")),
|
|
30
|
+
React.createElement(Box, { marginBottom: 1 },
|
|
31
|
+
React.createElement(Text, null, "Enter timeout in seconds for auto-approval verification:")),
|
|
32
|
+
React.createElement(Box, { marginBottom: 1 },
|
|
33
|
+
React.createElement(TextInputWrapper, { value: inputValue, onChange: handleChange, onSubmit: handleSubmit, placeholder: "e.g. 30", focus: true })),
|
|
34
|
+
React.createElement(Box, { marginBottom: 1 },
|
|
35
|
+
React.createElement(Text, { dimColor: true }, "Must be a positive integer (minimum: 1 second, default: 30 seconds)")),
|
|
36
|
+
React.createElement(Box, null,
|
|
37
|
+
React.createElement(Text, { dimColor: true },
|
|
38
|
+
"Press Enter to save, ",
|
|
39
|
+
shortcutManager.getShortcutDisplay('cancel'),
|
|
40
|
+
" to go back"))));
|
|
41
|
+
};
|
|
42
|
+
export default ConfigureTimeout;
|
|
@@ -3,7 +3,12 @@ import { ProcessError } from '../types/errors.js';
|
|
|
3
3
|
import { configurationManager } from './configurationManager.js';
|
|
4
4
|
import { logger } from '../utils/logger.js';
|
|
5
5
|
import { execFile, spawn, } from 'child_process';
|
|
6
|
-
const
|
|
6
|
+
const DEFAULT_TIMEOUT_SECONDS = 30;
|
|
7
|
+
const getTimeoutMs = () => {
|
|
8
|
+
const config = configurationManager.getAutoApprovalConfig();
|
|
9
|
+
const timeoutSeconds = config.timeout ?? DEFAULT_TIMEOUT_SECONDS;
|
|
10
|
+
return timeoutSeconds * 1000;
|
|
11
|
+
};
|
|
7
12
|
const createAbortError = () => {
|
|
8
13
|
const error = new Error('Auto-approval verification aborted');
|
|
9
14
|
error.name = 'AbortError';
|
|
@@ -80,15 +85,16 @@ export class AutoApprovalVerifier {
|
|
|
80
85
|
return;
|
|
81
86
|
signal.removeEventListener('abort', abortListener);
|
|
82
87
|
};
|
|
88
|
+
const timeoutMs = getTimeoutMs();
|
|
83
89
|
const timeoutId = setTimeout(() => {
|
|
84
90
|
settle(() => {
|
|
85
91
|
logger.warn('Auto-approval verification timed out, terminating helper Claude process');
|
|
86
92
|
if (child?.pid) {
|
|
87
93
|
child.kill('SIGKILL');
|
|
88
94
|
}
|
|
89
|
-
reject(new Error(
|
|
95
|
+
reject(new Error(`Auto-approval verification timed out after ${timeoutMs / 1000}s`));
|
|
90
96
|
});
|
|
91
|
-
},
|
|
97
|
+
}, timeoutMs);
|
|
92
98
|
if (signal) {
|
|
93
99
|
if (signal.aborted) {
|
|
94
100
|
abortListener();
|
|
@@ -166,13 +172,14 @@ export class AutoApprovalVerifier {
|
|
|
166
172
|
const child = spawn(command, [], spawnOptions);
|
|
167
173
|
let stdout = '';
|
|
168
174
|
let stderr = '';
|
|
175
|
+
const timeoutMs = getTimeoutMs();
|
|
169
176
|
timeoutId = setTimeout(() => {
|
|
170
177
|
logger.warn('Auto-approval custom command timed out, terminating process');
|
|
171
178
|
settle(() => {
|
|
172
179
|
child.kill('SIGKILL');
|
|
173
|
-
reject(new Error(
|
|
180
|
+
reject(new Error(`Auto-approval verification custom command timed out after ${timeoutMs / 1000}s`));
|
|
174
181
|
});
|
|
175
|
-
},
|
|
182
|
+
}, timeoutMs);
|
|
176
183
|
if (signal) {
|
|
177
184
|
if (signal.aborted) {
|
|
178
185
|
abortListener();
|
|
@@ -24,6 +24,7 @@ export declare class ConfigurationManager {
|
|
|
24
24
|
getAutoApprovalConfig(): NonNullable<ConfigurationData['autoApproval']>;
|
|
25
25
|
setAutoApprovalConfig(autoApproval: NonNullable<ConfigurationData['autoApproval']>): void;
|
|
26
26
|
setAutoApprovalEnabled(enabled: boolean): void;
|
|
27
|
+
setAutoApprovalTimeout(timeout: number): void;
|
|
27
28
|
getCommandConfig(): CommandConfig;
|
|
28
29
|
setCommandConfig(commandConfig: CommandConfig): void;
|
|
29
30
|
private migrateLegacyCommandToPresets;
|
|
@@ -102,10 +102,16 @@ export class ConfigurationManager {
|
|
|
102
102
|
if (!this.config.autoApproval) {
|
|
103
103
|
this.config.autoApproval = {
|
|
104
104
|
enabled: false,
|
|
105
|
+
timeout: 30,
|
|
105
106
|
};
|
|
106
107
|
}
|
|
107
|
-
else
|
|
108
|
-
this.config.autoApproval
|
|
108
|
+
else {
|
|
109
|
+
if (!Object.prototype.hasOwnProperty.call(this.config.autoApproval, 'enabled')) {
|
|
110
|
+
this.config.autoApproval.enabled = false;
|
|
111
|
+
}
|
|
112
|
+
if (!Object.prototype.hasOwnProperty.call(this.config.autoApproval, 'timeout')) {
|
|
113
|
+
this.config.autoApproval.timeout = 30;
|
|
114
|
+
}
|
|
109
115
|
}
|
|
110
116
|
// Migrate legacy command config to presets if needed
|
|
111
117
|
this.migrateLegacyCommandToPresets();
|
|
@@ -174,9 +180,14 @@ export class ConfigurationManager {
|
|
|
174
180
|
this.saveConfig();
|
|
175
181
|
}
|
|
176
182
|
getAutoApprovalConfig() {
|
|
177
|
-
|
|
183
|
+
const config = this.config.autoApproval || {
|
|
178
184
|
enabled: false,
|
|
179
|
-
}
|
|
185
|
+
};
|
|
186
|
+
// Default timeout to 30 seconds if not set
|
|
187
|
+
return {
|
|
188
|
+
...config,
|
|
189
|
+
timeout: config.timeout ?? 30,
|
|
190
|
+
};
|
|
180
191
|
}
|
|
181
192
|
setAutoApprovalConfig(autoApproval) {
|
|
182
193
|
this.config.autoApproval = autoApproval;
|
|
@@ -186,6 +197,10 @@ export class ConfigurationManager {
|
|
|
186
197
|
const currentConfig = this.getAutoApprovalConfig();
|
|
187
198
|
this.setAutoApprovalConfig({ ...currentConfig, enabled });
|
|
188
199
|
}
|
|
200
|
+
setAutoApprovalTimeout(timeout) {
|
|
201
|
+
const currentConfig = this.getAutoApprovalConfig();
|
|
202
|
+
this.setAutoApprovalConfig({ ...currentConfig, timeout });
|
|
203
|
+
}
|
|
189
204
|
getCommandConfig() {
|
|
190
205
|
// For backward compatibility, return the default preset as CommandConfig
|
|
191
206
|
const defaultPreset = this.getDefaultPreset();
|
|
@@ -535,10 +550,16 @@ export class ConfigurationManager {
|
|
|
535
550
|
if (!config.autoApproval) {
|
|
536
551
|
config.autoApproval = {
|
|
537
552
|
enabled: false,
|
|
553
|
+
timeout: 30,
|
|
538
554
|
};
|
|
539
555
|
}
|
|
540
|
-
else
|
|
541
|
-
config.autoApproval
|
|
556
|
+
else {
|
|
557
|
+
if (!Object.prototype.hasOwnProperty.call(config.autoApproval, 'enabled')) {
|
|
558
|
+
config.autoApproval.enabled = false;
|
|
559
|
+
}
|
|
560
|
+
if (!Object.prototype.hasOwnProperty.call(config.autoApproval, 'timeout')) {
|
|
561
|
+
config.autoApproval.timeout = 30;
|
|
562
|
+
}
|
|
542
563
|
}
|
|
543
564
|
return config;
|
|
544
565
|
}
|
package/dist/types/index.d.ts
CHANGED