mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-28 11:41:04 +00:00
Add Interactive Approval Mode Dialog (#1012)
This commit is contained in:
parent
0752a31e1e
commit
160b64523e
16 changed files with 397 additions and 909 deletions
|
|
@ -9,11 +9,8 @@ import { Box, Text } from 'ink';
|
|||
import { theme } from '../semantic-colors.js';
|
||||
import type { LoadedSettings, Settings } from '../../config/settings.js';
|
||||
import { SettingScope } from '../../config/settings.js';
|
||||
import {
|
||||
getScopeItems,
|
||||
getScopeMessageForSetting,
|
||||
} from '../../utils/dialogScopeUtils.js';
|
||||
import { RadioButtonSelect } from './shared/RadioButtonSelect.js';
|
||||
import { getScopeMessageForSetting } from '../../utils/dialogScopeUtils.js';
|
||||
import { ScopeSelector } from './shared/ScopeSelector.js';
|
||||
import {
|
||||
getDialogSettingKeys,
|
||||
setPendingSettingValue,
|
||||
|
|
@ -30,6 +27,7 @@ import {
|
|||
getEffectiveValue,
|
||||
} from '../../utils/settingsUtils.js';
|
||||
import { useVimMode } from '../contexts/VimModeContext.js';
|
||||
import { type Config } from '@qwen-code/qwen-code-core';
|
||||
import { useKeypress } from '../hooks/useKeypress.js';
|
||||
import chalk from 'chalk';
|
||||
import { cpSlice, cpLen, stripUnsafeCharacters } from '../utils/textUtils.js';
|
||||
|
|
@ -43,6 +41,7 @@ interface SettingsDialogProps {
|
|||
onSelect: (settingName: string | undefined, scope: SettingScope) => void;
|
||||
onRestartRequest?: () => void;
|
||||
availableTerminalHeight?: number;
|
||||
config?: Config;
|
||||
}
|
||||
|
||||
const maxItemsToShow = 8;
|
||||
|
|
@ -52,6 +51,7 @@ export function SettingsDialog({
|
|||
onSelect,
|
||||
onRestartRequest,
|
||||
availableTerminalHeight,
|
||||
config,
|
||||
}: SettingsDialogProps): React.JSX.Element {
|
||||
// Get vim mode context to sync vim mode changes
|
||||
const { vimEnabled, toggleVimEnabled } = useVimMode();
|
||||
|
|
@ -184,6 +184,21 @@ export function SettingsDialog({
|
|||
});
|
||||
}
|
||||
|
||||
// Special handling for approval mode to apply to current session
|
||||
if (
|
||||
key === 'tools.approvalMode' &&
|
||||
settings.merged.tools?.approvalMode
|
||||
) {
|
||||
try {
|
||||
config?.setApprovalMode(settings.merged.tools.approvalMode);
|
||||
} catch (error) {
|
||||
console.error(
|
||||
'Failed to apply approval mode to current session:',
|
||||
error,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove from modifiedSettings since it's now saved
|
||||
setModifiedSettings((prev) => {
|
||||
const updated = new Set(prev);
|
||||
|
|
@ -357,12 +372,6 @@ export function SettingsDialog({
|
|||
setEditCursorPos(0);
|
||||
};
|
||||
|
||||
// Scope selector items
|
||||
const scopeItems = getScopeItems().map((item) => ({
|
||||
...item,
|
||||
key: item.value,
|
||||
}));
|
||||
|
||||
const handleScopeHighlight = (scope: SettingScope) => {
|
||||
setSelectedScope(scope);
|
||||
};
|
||||
|
|
@ -616,7 +625,11 @@ export function SettingsDialog({
|
|||
prev,
|
||||
),
|
||||
);
|
||||
} else if (defType === 'number' || defType === 'string') {
|
||||
} else if (
|
||||
defType === 'number' ||
|
||||
defType === 'string' ||
|
||||
defType === 'enum'
|
||||
) {
|
||||
if (
|
||||
typeof defaultValue === 'number' ||
|
||||
typeof defaultValue === 'string'
|
||||
|
|
@ -673,6 +686,21 @@ export function SettingsDialog({
|
|||
selectedScope,
|
||||
);
|
||||
|
||||
// Special handling for approval mode to apply to current session
|
||||
if (
|
||||
currentSetting.value === 'tools.approvalMode' &&
|
||||
settings.merged.tools?.approvalMode
|
||||
) {
|
||||
try {
|
||||
config?.setApprovalMode(settings.merged.tools.approvalMode);
|
||||
} catch (error) {
|
||||
console.error(
|
||||
'Failed to apply approval mode to current session:',
|
||||
error,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove from global pending changes if present
|
||||
setGlobalPendingChanges((prev) => {
|
||||
if (!prev.has(currentSetting.value)) return prev;
|
||||
|
|
@ -876,19 +904,12 @@ export function SettingsDialog({
|
|||
|
||||
{/* Scope Selection - conditionally visible based on height constraints */}
|
||||
{showScopeSelection && (
|
||||
<Box marginTop={1} flexDirection="column">
|
||||
<Text bold={focusSection === 'scope'} wrap="truncate">
|
||||
{focusSection === 'scope' ? '> ' : ' '}Apply To
|
||||
</Text>
|
||||
<RadioButtonSelect
|
||||
items={scopeItems}
|
||||
initialIndex={scopeItems.findIndex(
|
||||
(item) => item.value === selectedScope,
|
||||
)}
|
||||
<Box marginTop={1}>
|
||||
<ScopeSelector
|
||||
onSelect={handleScopeSelect}
|
||||
onHighlight={handleScopeHighlight}
|
||||
isFocused={focusSection === 'scope'}
|
||||
showNumbers={focusSection === 'scope'}
|
||||
initialScope={selectedScope}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue