snow-ai 0.3.22 → 0.3.24
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/api/gemini.d.ts +5 -1
- package/dist/api/gemini.js +30 -5
- package/dist/api/responses.js +18 -3
- package/dist/hooks/useConversation.d.ts +0 -5
- package/dist/hooks/useConversation.js +109 -56
- package/dist/hooks/useFilePicker.d.ts +1 -1
- package/dist/hooks/useFilePicker.js +13 -7
- package/dist/hooks/useHistoryNavigation.js +14 -7
- package/dist/hooks/useInputBuffer.d.ts +1 -1
- package/dist/hooks/useInputBuffer.js +22 -6
- package/dist/hooks/useStreamingState.js +2 -2
- package/dist/hooks/useVSCodeState.js +23 -6
- package/dist/mcp/filesystem.js +1 -1
- package/dist/ui/components/ChatInput.js +17 -11
- package/dist/ui/components/MessageList.d.ts +0 -1
- package/dist/ui/components/MessageList.js +1 -2
- package/dist/ui/components/SessionListPanel.js +12 -8
- package/dist/ui/components/SessionListScreen.js +2 -1
- package/dist/ui/components/ToolConfirmation.d.ts +1 -1
- package/dist/ui/components/ToolConfirmation.js +63 -22
- package/dist/ui/components/ToolResultPreview.js +33 -6
- package/dist/ui/pages/ChatScreen.js +21 -17
- package/dist/ui/pages/ConfigScreen.js +167 -16
- package/dist/ui/pages/HeadlessModeScreen.js +0 -1
- package/dist/ui/pages/ProxyConfigScreen.d.ts +1 -1
- package/dist/ui/pages/ProxyConfigScreen.js +6 -6
- package/dist/ui/pages/SensitiveCommandConfigScreen.d.ts +7 -0
- package/dist/ui/pages/SensitiveCommandConfigScreen.js +262 -0
- package/dist/ui/pages/SubAgentConfigScreen.js +1 -1
- package/dist/ui/pages/WelcomeScreen.js +14 -3
- package/dist/utils/apiConfig.d.ts +10 -0
- package/dist/utils/sensitiveCommandManager.d.ts +53 -0
- package/dist/utils/sensitiveCommandManager.js +308 -0
- package/dist/utils/sessionConverter.js +16 -11
- package/package.json +4 -2
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import React, { useState, useCallback, useEffect } from 'react';
|
|
2
|
+
import { Box, Text, useInput } from 'ink';
|
|
3
|
+
import TextInput from 'ink-text-input';
|
|
4
|
+
import { Alert } from '@inkjs/ui';
|
|
5
|
+
import { getAllSensitiveCommands, toggleSensitiveCommand, addSensitiveCommand, removeSensitiveCommand, resetToDefaults, } from '../../utils/sensitiveCommandManager.js';
|
|
6
|
+
// Focus event handling
|
|
7
|
+
const focusEventTokenRegex = /(?:\x1b)?\[[0-9;]*[IO]/g;
|
|
8
|
+
const isFocusEventInput = (value) => {
|
|
9
|
+
if (!value)
|
|
10
|
+
return false;
|
|
11
|
+
if (value === '\x1b[I' ||
|
|
12
|
+
value === '\x1b[O' ||
|
|
13
|
+
value === '[I' ||
|
|
14
|
+
value === '[O') {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
const trimmed = value.trim();
|
|
18
|
+
if (!trimmed)
|
|
19
|
+
return false;
|
|
20
|
+
const tokens = trimmed.match(focusEventTokenRegex);
|
|
21
|
+
if (!tokens)
|
|
22
|
+
return false;
|
|
23
|
+
const normalized = trimmed.replace(/\s+/g, '');
|
|
24
|
+
const tokensCombined = tokens.join('');
|
|
25
|
+
return tokensCombined === normalized;
|
|
26
|
+
};
|
|
27
|
+
const stripFocusArtifacts = (value) => {
|
|
28
|
+
if (!value)
|
|
29
|
+
return '';
|
|
30
|
+
return value
|
|
31
|
+
.replace(/\x1b\[[0-9;]*[IO]/g, '')
|
|
32
|
+
.replace(/\[[0-9;]*[IO]/g, '')
|
|
33
|
+
.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '');
|
|
34
|
+
};
|
|
35
|
+
export default function SensitiveCommandConfigScreen({ onBack, inlineMode = false, }) {
|
|
36
|
+
const [commands, setCommands] = useState([]);
|
|
37
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
38
|
+
const [viewMode, setViewMode] = useState('list');
|
|
39
|
+
const [showSuccess, setShowSuccess] = useState(false);
|
|
40
|
+
const [successMessage, setSuccessMessage] = useState('');
|
|
41
|
+
// Confirmation states
|
|
42
|
+
const [confirmDelete, setConfirmDelete] = useState(false);
|
|
43
|
+
const [confirmReset, setConfirmReset] = useState(false);
|
|
44
|
+
// Add custom command fields
|
|
45
|
+
const [customPattern, setCustomPattern] = useState('');
|
|
46
|
+
const [customDescription, setCustomDescription] = useState('');
|
|
47
|
+
const [addField, setAddField] = useState('pattern');
|
|
48
|
+
// Load commands
|
|
49
|
+
const loadCommands = useCallback(() => {
|
|
50
|
+
const allCommands = getAllSensitiveCommands();
|
|
51
|
+
setCommands(allCommands);
|
|
52
|
+
}, []);
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
loadCommands();
|
|
55
|
+
}, [loadCommands]);
|
|
56
|
+
// Handle list view input
|
|
57
|
+
const handleListInput = useCallback((input, key) => {
|
|
58
|
+
if (key.escape) {
|
|
59
|
+
// Cancel any pending confirmations
|
|
60
|
+
if (confirmDelete || confirmReset) {
|
|
61
|
+
setConfirmDelete(false);
|
|
62
|
+
setConfirmReset(false);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
onBack();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (key.upArrow) {
|
|
69
|
+
setSelectedIndex(prev => Math.max(0, prev - 1));
|
|
70
|
+
// Clear confirmations when navigating
|
|
71
|
+
setConfirmDelete(false);
|
|
72
|
+
setConfirmReset(false);
|
|
73
|
+
}
|
|
74
|
+
else if (key.downArrow) {
|
|
75
|
+
setSelectedIndex(prev => Math.min(commands.length - 1, prev + 1));
|
|
76
|
+
// Clear confirmations when navigating
|
|
77
|
+
setConfirmDelete(false);
|
|
78
|
+
setConfirmReset(false);
|
|
79
|
+
}
|
|
80
|
+
else if (input === ' ') {
|
|
81
|
+
// Toggle command
|
|
82
|
+
const cmd = commands[selectedIndex];
|
|
83
|
+
if (cmd) {
|
|
84
|
+
toggleSensitiveCommand(cmd.id);
|
|
85
|
+
loadCommands();
|
|
86
|
+
setSuccessMessage(cmd.enabled
|
|
87
|
+
? `Disabled: ${cmd.pattern}`
|
|
88
|
+
: `Enabled: ${cmd.pattern}`);
|
|
89
|
+
setShowSuccess(true);
|
|
90
|
+
setTimeout(() => setShowSuccess(false), 2000);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else if (input === 'a' || input === 'A') {
|
|
94
|
+
// Add custom command
|
|
95
|
+
setViewMode('add');
|
|
96
|
+
setCustomPattern('');
|
|
97
|
+
setCustomDescription('');
|
|
98
|
+
setAddField('pattern');
|
|
99
|
+
}
|
|
100
|
+
else if (input === 'd' || input === 'D') {
|
|
101
|
+
// Delete custom command - requires confirmation
|
|
102
|
+
const cmd = commands[selectedIndex];
|
|
103
|
+
if (cmd && !cmd.isPreset) {
|
|
104
|
+
if (!confirmDelete) {
|
|
105
|
+
// First press - ask for confirmation
|
|
106
|
+
setConfirmDelete(true);
|
|
107
|
+
setConfirmReset(false);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
// Second press - execute delete
|
|
111
|
+
removeSensitiveCommand(cmd.id);
|
|
112
|
+
loadCommands();
|
|
113
|
+
setSelectedIndex(prev => Math.min(prev, commands.length - 2));
|
|
114
|
+
setSuccessMessage(`Deleted: ${cmd.pattern}`);
|
|
115
|
+
setShowSuccess(true);
|
|
116
|
+
setTimeout(() => setShowSuccess(false), 2000);
|
|
117
|
+
setConfirmDelete(false);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else if (input === 'r' || input === 'R') {
|
|
122
|
+
// Reset to defaults - requires confirmation
|
|
123
|
+
if (!confirmReset) {
|
|
124
|
+
// First press - ask for confirmation
|
|
125
|
+
setConfirmReset(true);
|
|
126
|
+
setConfirmDelete(false);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
// Second press - execute reset
|
|
130
|
+
resetToDefaults();
|
|
131
|
+
loadCommands();
|
|
132
|
+
setSelectedIndex(0);
|
|
133
|
+
setSuccessMessage('Reset to default commands');
|
|
134
|
+
setShowSuccess(true);
|
|
135
|
+
setTimeout(() => setShowSuccess(false), 2000);
|
|
136
|
+
setConfirmReset(false);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}, [
|
|
140
|
+
commands,
|
|
141
|
+
selectedIndex,
|
|
142
|
+
onBack,
|
|
143
|
+
loadCommands,
|
|
144
|
+
confirmDelete,
|
|
145
|
+
confirmReset,
|
|
146
|
+
]);
|
|
147
|
+
// Handle add view input
|
|
148
|
+
const handleAddInput = useCallback((_input, key) => {
|
|
149
|
+
if (key.escape) {
|
|
150
|
+
setViewMode('list');
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if (key.tab) {
|
|
154
|
+
setAddField(prev => (prev === 'pattern' ? 'description' : 'pattern'));
|
|
155
|
+
}
|
|
156
|
+
}, []);
|
|
157
|
+
// Use input hook
|
|
158
|
+
useInput((input, key) => {
|
|
159
|
+
if (viewMode === 'list') {
|
|
160
|
+
handleListInput(input, key);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
handleAddInput(input, key);
|
|
164
|
+
}
|
|
165
|
+
}, { isActive: true });
|
|
166
|
+
// Handle pattern input change
|
|
167
|
+
const handlePatternChange = useCallback((value) => {
|
|
168
|
+
if (!isFocusEventInput(value)) {
|
|
169
|
+
setCustomPattern(stripFocusArtifacts(value));
|
|
170
|
+
}
|
|
171
|
+
}, []);
|
|
172
|
+
// Handle description input change
|
|
173
|
+
const handleDescriptionChange = useCallback((value) => {
|
|
174
|
+
if (!isFocusEventInput(value)) {
|
|
175
|
+
setCustomDescription(stripFocusArtifacts(value));
|
|
176
|
+
}
|
|
177
|
+
}, []);
|
|
178
|
+
// Handle add submit
|
|
179
|
+
const handleAddSubmit = useCallback(() => {
|
|
180
|
+
if (addField === 'pattern') {
|
|
181
|
+
setAddField('description');
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
// Submit
|
|
185
|
+
if (customPattern.trim() && customDescription.trim()) {
|
|
186
|
+
try {
|
|
187
|
+
addSensitiveCommand(customPattern.trim(), customDescription.trim());
|
|
188
|
+
loadCommands();
|
|
189
|
+
setViewMode('list');
|
|
190
|
+
setSuccessMessage(`Added: ${customPattern}`);
|
|
191
|
+
setShowSuccess(true);
|
|
192
|
+
setTimeout(() => setShowSuccess(false), 2000);
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
// Handle error
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}, [addField, customPattern, customDescription, loadCommands]);
|
|
200
|
+
if (viewMode === 'add') {
|
|
201
|
+
return (React.createElement(Box, { flexDirection: "column", paddingX: inlineMode ? 0 : 2, paddingY: 1 },
|
|
202
|
+
React.createElement(Text, { bold: true, color: "cyan" }, "Add Custom Sensitive Command"),
|
|
203
|
+
React.createElement(Box, { marginTop: 1 }),
|
|
204
|
+
React.createElement(Text, { dimColor: true }, "Pattern (supports wildcards, e.g., \"rm*\"):"),
|
|
205
|
+
React.createElement(Box, null,
|
|
206
|
+
React.createElement(Text, { color: addField === 'pattern' ? 'cyan' : 'gray' }, "\u276F "),
|
|
207
|
+
React.createElement(TextInput, { value: customPattern, onChange: handlePatternChange, onSubmit: handleAddSubmit, focus: addField === 'pattern' })),
|
|
208
|
+
React.createElement(Box, { marginTop: 1 }),
|
|
209
|
+
React.createElement(Text, { dimColor: true }, "Description:"),
|
|
210
|
+
React.createElement(Box, null,
|
|
211
|
+
React.createElement(Text, { color: addField === 'description' ? 'cyan' : 'gray' }, "\u276F "),
|
|
212
|
+
React.createElement(TextInput, { value: customDescription, onChange: handleDescriptionChange, onSubmit: handleAddSubmit, focus: addField === 'description' })),
|
|
213
|
+
React.createElement(Box, { marginTop: 1 }),
|
|
214
|
+
React.createElement(Text, { dimColor: true }, "Tab: Switch \u2022 Enter: Submit \u2022 Esc: Cancel")));
|
|
215
|
+
}
|
|
216
|
+
// Calculate visible range for scrolling
|
|
217
|
+
const viewportHeight = 13;
|
|
218
|
+
const startIndex = Math.max(0, selectedIndex - Math.floor(viewportHeight / 2));
|
|
219
|
+
const endIndex = Math.min(commands.length, startIndex + viewportHeight);
|
|
220
|
+
const adjustedStart = Math.max(0, endIndex - viewportHeight);
|
|
221
|
+
const selectedCmd = commands[selectedIndex];
|
|
222
|
+
return (React.createElement(Box, { flexDirection: "column", paddingX: inlineMode ? 0 : 2, paddingY: 1 },
|
|
223
|
+
React.createElement(Text, { bold: true, color: "cyan" }, "Sensitive Command Protection"),
|
|
224
|
+
React.createElement(Text, { dimColor: true }, "Configure commands that require confirmation even in YOLO/Always-Approved mode"),
|
|
225
|
+
showSuccess && (React.createElement(Box, { marginTop: 1 },
|
|
226
|
+
React.createElement(Alert, { variant: "success" }, successMessage))),
|
|
227
|
+
React.createElement(Box, { marginTop: 1 }),
|
|
228
|
+
commands.length === 0 ? (React.createElement(Text, { dimColor: true }, "No commands configured")) : (commands.map((cmd, index) => {
|
|
229
|
+
// Only render items in the visible viewport
|
|
230
|
+
if (index < adjustedStart || index >= endIndex) {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
return (React.createElement(Text, { key: cmd.id, color: selectedIndex === index
|
|
234
|
+
? 'cyan'
|
|
235
|
+
: cmd.enabled
|
|
236
|
+
? 'white'
|
|
237
|
+
: 'gray', bold: selectedIndex === index, dimColor: !cmd.enabled },
|
|
238
|
+
selectedIndex === index ? '❯ ' : ' ',
|
|
239
|
+
"[",
|
|
240
|
+
cmd.enabled ? '✓' : ' ',
|
|
241
|
+
"]",
|
|
242
|
+
' ',
|
|
243
|
+
cmd.pattern,
|
|
244
|
+
!cmd.isPreset && React.createElement(Text, { color: "yellow" }, " (custom)")));
|
|
245
|
+
})),
|
|
246
|
+
React.createElement(Box, { marginTop: 1 }),
|
|
247
|
+
selectedCmd && !confirmDelete && !confirmReset && (React.createElement(Text, { dimColor: true },
|
|
248
|
+
selectedCmd.description,
|
|
249
|
+
" (",
|
|
250
|
+
selectedCmd.enabled ? 'Enabled' : 'Disabled',
|
|
251
|
+
")",
|
|
252
|
+
!selectedCmd.isPreset && ' [Custom]')),
|
|
253
|
+
confirmDelete && selectedCmd && (React.createElement(Text, { bold: true, color: "yellow" },
|
|
254
|
+
"\u26A0\uFE0F Press D again to confirm deletion of \"",
|
|
255
|
+
selectedCmd.pattern,
|
|
256
|
+
"\"")),
|
|
257
|
+
confirmReset && (React.createElement(Text, { bold: true, color: "yellow" }, "\u26A0\uFE0F Press R again to confirm reset to default commands")),
|
|
258
|
+
React.createElement(Box, { marginTop: 1 }),
|
|
259
|
+
React.createElement(Text, { dimColor: true }, confirmDelete || confirmReset
|
|
260
|
+
? 'Press the same key again to confirm • Esc: Cancel'
|
|
261
|
+
: '↑↓: Navigate • Space: Toggle • A: Add • D: Delete • R: Reset • Esc: Back')));
|
|
262
|
+
}
|
|
@@ -353,7 +353,7 @@ export default function SubAgentConfigScreen({ onBack, onSave, inlineMode = fals
|
|
|
353
353
|
return (React.createElement(Box, { key: tool },
|
|
354
354
|
React.createElement(Text, { color: isCurrentTool ? 'cyan' : 'white', bold: isCurrentTool },
|
|
355
355
|
isCurrentTool ? '❯ ' : ' ',
|
|
356
|
-
selectedTools.has(tool) ? '
|
|
356
|
+
selectedTools.has(tool) ? '[✓]' : '[ ]',
|
|
357
357
|
" ",
|
|
358
358
|
tool)));
|
|
359
359
|
})))));
|
|
@@ -9,6 +9,7 @@ import ConfigScreen from './ConfigScreen.js';
|
|
|
9
9
|
import ProxyConfigScreen from './ProxyConfigScreen.js';
|
|
10
10
|
import SubAgentConfigScreen from './SubAgentConfigScreen.js';
|
|
11
11
|
import SubAgentListScreen from './SubAgentListScreen.js';
|
|
12
|
+
import SensitiveCommandConfigScreen from './SensitiveCommandConfigScreen.js';
|
|
12
13
|
export default function WelcomeScreen({ version = '1.0.0', onMenuSelect, }) {
|
|
13
14
|
const [infoText, setInfoText] = useState('Start a new chat conversation');
|
|
14
15
|
const [inlineView, setInlineView] = useState('menu');
|
|
@@ -54,6 +55,11 @@ export default function WelcomeScreen({ version = '1.0.0', onMenuSelect, }) {
|
|
|
54
55
|
value: 'subagent',
|
|
55
56
|
infoText: 'Configure sub-agents with custom tool permissions',
|
|
56
57
|
},
|
|
58
|
+
{
|
|
59
|
+
label: 'Sensitive Commands',
|
|
60
|
+
value: 'sensitive-commands',
|
|
61
|
+
infoText: 'Configure commands that require confirmation even in YOLO mode',
|
|
62
|
+
},
|
|
57
63
|
{
|
|
58
64
|
label: 'Exit',
|
|
59
65
|
value: 'exit',
|
|
@@ -75,6 +81,9 @@ export default function WelcomeScreen({ version = '1.0.0', onMenuSelect, }) {
|
|
|
75
81
|
else if (value === 'subagent') {
|
|
76
82
|
setInlineView('subagent-list');
|
|
77
83
|
}
|
|
84
|
+
else if (value === 'sensitive-commands') {
|
|
85
|
+
setInlineView('sensitive-commands');
|
|
86
|
+
}
|
|
78
87
|
else {
|
|
79
88
|
// Pass through to parent for other actions (chat, exit, etc.)
|
|
80
89
|
onMenuSelect?.(value);
|
|
@@ -107,11 +116,11 @@ export default function WelcomeScreen({ version = '1.0.0', onMenuSelect, }) {
|
|
|
107
116
|
const handler = setTimeout(() => {
|
|
108
117
|
stdout.write(ansiEscapes.clearTerminal);
|
|
109
118
|
setRemountKey(prev => prev + 1); // Force re-render
|
|
110
|
-
},
|
|
119
|
+
}, 200); // Add debounce delay to avoid rapid re-renders
|
|
111
120
|
return () => {
|
|
112
121
|
clearTimeout(handler);
|
|
113
122
|
};
|
|
114
|
-
}, [terminalWidth
|
|
123
|
+
}, [terminalWidth]); // Remove stdout from dependencies to avoid loops
|
|
115
124
|
return (React.createElement(Box, { flexDirection: "column", width: terminalWidth },
|
|
116
125
|
React.createElement(Static, { key: remountKey, items: [
|
|
117
126
|
React.createElement(Box, { key: "welcome-header", flexDirection: "row", paddingLeft: 2, paddingTop: 1, paddingBottom: 0, width: terminalWidth },
|
|
@@ -137,5 +146,7 @@ export default function WelcomeScreen({ version = '1.0.0', onMenuSelect, }) {
|
|
|
137
146
|
inlineView === 'subagent-add' && (React.createElement(Box, { paddingX: 1 },
|
|
138
147
|
React.createElement(SubAgentConfigScreen, { onBack: () => setInlineView('subagent-list'), onSave: handleSubAgentSave, inlineMode: true }))),
|
|
139
148
|
inlineView === 'subagent-edit' && (React.createElement(Box, { paddingX: 1 },
|
|
140
|
-
React.createElement(SubAgentConfigScreen, { onBack: () => setInlineView('subagent-list'), onSave: handleSubAgentSave, agentId: editingAgentId, inlineMode: true })))
|
|
149
|
+
React.createElement(SubAgentConfigScreen, { onBack: () => setInlineView('subagent-list'), onSave: handleSubAgentSave, agentId: editingAgentId, inlineMode: true }))),
|
|
150
|
+
inlineView === 'sensitive-commands' && (React.createElement(Box, { paddingX: 1 },
|
|
151
|
+
React.createElement(SensitiveCommandConfigScreen, { onBack: handleBackToMenu, inlineMode: true })))));
|
|
141
152
|
}
|
|
@@ -6,6 +6,14 @@ export interface ThinkingConfig {
|
|
|
6
6
|
type: 'enabled';
|
|
7
7
|
budget_tokens: number;
|
|
8
8
|
}
|
|
9
|
+
export interface GeminiThinkingConfig {
|
|
10
|
+
enabled: boolean;
|
|
11
|
+
budget: number;
|
|
12
|
+
}
|
|
13
|
+
export interface ResponsesReasoningConfig {
|
|
14
|
+
enabled: boolean;
|
|
15
|
+
effort: 'low' | 'medium' | 'high';
|
|
16
|
+
}
|
|
9
17
|
export interface ApiConfig {
|
|
10
18
|
baseUrl: string;
|
|
11
19
|
apiKey: string;
|
|
@@ -17,6 +25,8 @@ export interface ApiConfig {
|
|
|
17
25
|
compactModel?: CompactModelConfig;
|
|
18
26
|
anthropicBeta?: boolean;
|
|
19
27
|
thinking?: ThinkingConfig;
|
|
28
|
+
geminiThinking?: GeminiThinkingConfig;
|
|
29
|
+
responsesReasoning?: ResponsesReasoningConfig;
|
|
20
30
|
}
|
|
21
31
|
export interface MCPServer {
|
|
22
32
|
url?: string;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export interface SensitiveCommand {
|
|
2
|
+
id: string;
|
|
3
|
+
pattern: string;
|
|
4
|
+
description: string;
|
|
5
|
+
enabled: boolean;
|
|
6
|
+
isPreset: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface SensitiveCommandsConfig {
|
|
9
|
+
commands: SensitiveCommand[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* 预设的常见敏感指令
|
|
13
|
+
*/
|
|
14
|
+
export declare const PRESET_SENSITIVE_COMMANDS: SensitiveCommand[];
|
|
15
|
+
/**
|
|
16
|
+
* Load sensitive commands configuration
|
|
17
|
+
*/
|
|
18
|
+
export declare function loadSensitiveCommands(): SensitiveCommandsConfig;
|
|
19
|
+
/**
|
|
20
|
+
* Save sensitive commands configuration
|
|
21
|
+
*/
|
|
22
|
+
export declare function saveSensitiveCommands(config: SensitiveCommandsConfig): void;
|
|
23
|
+
/**
|
|
24
|
+
* Add a custom sensitive command
|
|
25
|
+
*/
|
|
26
|
+
export declare function addSensitiveCommand(pattern: string, description: string): void;
|
|
27
|
+
/**
|
|
28
|
+
* Remove a sensitive command
|
|
29
|
+
*/
|
|
30
|
+
export declare function removeSensitiveCommand(id: string): void;
|
|
31
|
+
/**
|
|
32
|
+
* Update a sensitive command
|
|
33
|
+
*/
|
|
34
|
+
export declare function updateSensitiveCommand(id: string, updates: Partial<Omit<SensitiveCommand, 'id' | 'isPreset'>>): void;
|
|
35
|
+
/**
|
|
36
|
+
* Toggle a sensitive command enabled state
|
|
37
|
+
*/
|
|
38
|
+
export declare function toggleSensitiveCommand(id: string): void;
|
|
39
|
+
/**
|
|
40
|
+
* Check if a command matches any enabled sensitive pattern
|
|
41
|
+
*/
|
|
42
|
+
export declare function isSensitiveCommand(command: string): {
|
|
43
|
+
isSensitive: boolean;
|
|
44
|
+
matchedCommand?: SensitiveCommand;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Get all sensitive commands
|
|
48
|
+
*/
|
|
49
|
+
export declare function getAllSensitiveCommands(): SensitiveCommand[];
|
|
50
|
+
/**
|
|
51
|
+
* Reset to default preset commands
|
|
52
|
+
*/
|
|
53
|
+
export declare function resetToDefaults(): void;
|