mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-19 09:33:53 +00:00
Merge branch 'main' into chore/sync-gemini-cli-v0.3.4
This commit is contained in:
@@ -29,7 +29,12 @@ import { useAuthCommand } from './hooks/useAuthCommand.js';
|
||||
import { useQwenAuth } from './hooks/useQwenAuth.js';
|
||||
import { useFolderTrust } from './hooks/useFolderTrust.js';
|
||||
import { useEditorSettings } from './hooks/useEditorSettings.js';
|
||||
import { useQuitConfirmation } from './hooks/useQuitConfirmation.js';
|
||||
import { useWelcomeBack } from './hooks/useWelcomeBack.js';
|
||||
import { useDialogClose } from './hooks/useDialogClose.js';
|
||||
import { useSlashCommandProcessor } from './hooks/slashCommandProcessor.js';
|
||||
import { useSubagentCreateDialog } from './hooks/useSubagentCreateDialog.js';
|
||||
import { useAgentsManagerDialog } from './hooks/useAgentsManagerDialog.js';
|
||||
import { useAutoAcceptIndicator } from './hooks/useAutoAcceptIndicator.js';
|
||||
import { useMessageQueue } from './hooks/useMessageQueue.js';
|
||||
import { useConsoleMessages } from './hooks/useConsoleMessages.js';
|
||||
@@ -46,7 +51,12 @@ import { QwenOAuthProgress } from './components/QwenOAuthProgress.js';
|
||||
import { EditorSettingsDialog } from './components/EditorSettingsDialog.js';
|
||||
import { FolderTrustDialog } from './components/FolderTrustDialog.js';
|
||||
import { ShellConfirmationDialog } from './components/ShellConfirmationDialog.js';
|
||||
import { QuitConfirmationDialog } from './components/QuitConfirmationDialog.js';
|
||||
import { RadioButtonSelect } from './components/shared/RadioButtonSelect.js';
|
||||
import {
|
||||
AgentCreationWizard,
|
||||
AgentsManagerDialog,
|
||||
} from './components/subagents/index.js';
|
||||
import { Colors } from './colors.js';
|
||||
import { loadHierarchicalGeminiMemory } from '../config/config.js';
|
||||
import type { LoadedSettings } from '../config/settings.js';
|
||||
@@ -107,8 +117,8 @@ import { appEvents, AppEvent } from '../utils/events.js';
|
||||
import { isNarrowWidth } from './utils/isNarrowWidth.js';
|
||||
import { useWorkspaceMigration } from './hooks/useWorkspaceMigration.js';
|
||||
import { WorkspaceMigrationDialog } from './components/WorkspaceMigrationDialog.js';
|
||||
import { WelcomeBackDialog } from './components/WelcomeBackDialog.js';
|
||||
|
||||
const CTRL_EXIT_PROMPT_DURATION_MS = 1000;
|
||||
// Maximum number of queued messages to display in UI to prevent performance issues
|
||||
const MAX_DISPLAYED_QUEUED_MESSAGES = 3;
|
||||
|
||||
@@ -293,9 +303,24 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
const { isSettingsDialogOpen, openSettingsDialog, closeSettingsDialog } =
|
||||
useSettingsCommand();
|
||||
|
||||
const {
|
||||
isSubagentCreateDialogOpen,
|
||||
openSubagentCreateDialog,
|
||||
closeSubagentCreateDialog,
|
||||
} = useSubagentCreateDialog();
|
||||
|
||||
const {
|
||||
isAgentsManagerDialogOpen,
|
||||
openAgentsManagerDialog,
|
||||
closeAgentsManagerDialog,
|
||||
} = useAgentsManagerDialog();
|
||||
|
||||
const { isFolderTrustDialogOpen, handleFolderTrustSelect, isRestarting } =
|
||||
useFolderTrust(settings, setIsTrustedFolder);
|
||||
|
||||
const { showQuitConfirmation, handleQuitConfirmationSelect } =
|
||||
useQuitConfirmation();
|
||||
|
||||
const {
|
||||
isAuthDialogOpen,
|
||||
openAuthDialog,
|
||||
@@ -577,6 +602,7 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
commandContext,
|
||||
shellConfirmationRequest,
|
||||
confirmationRequest,
|
||||
quitConfirmationRequest,
|
||||
} = useSlashCommandProcessor(
|
||||
config,
|
||||
settings,
|
||||
@@ -592,9 +618,12 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
setQuittingMessages,
|
||||
openPrivacyNotice,
|
||||
openSettingsDialog,
|
||||
openSubagentCreateDialog,
|
||||
openAgentsManagerDialog,
|
||||
toggleVimEnabled,
|
||||
setIsProcessing,
|
||||
setGeminiMdFileCount,
|
||||
showQuitConfirmation,
|
||||
);
|
||||
|
||||
const buffer = useTextBuffer({
|
||||
@@ -640,6 +669,34 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
[pendingSlashCommandHistoryItems, pendingGeminiHistoryItems],
|
||||
);
|
||||
|
||||
// Welcome back functionality
|
||||
const {
|
||||
welcomeBackInfo,
|
||||
showWelcomeBackDialog,
|
||||
welcomeBackChoice,
|
||||
handleWelcomeBackSelection,
|
||||
handleWelcomeBackClose,
|
||||
} = useWelcomeBack(config, submitQuery, buffer, settings.merged);
|
||||
|
||||
// Dialog close functionality
|
||||
const { closeAnyOpenDialog } = useDialogClose({
|
||||
isThemeDialogOpen,
|
||||
handleThemeSelect,
|
||||
isAuthDialogOpen,
|
||||
handleAuthSelect,
|
||||
selectedAuthType: settings.merged.security?.auth?.selectedType,
|
||||
isEditorDialogOpen,
|
||||
exitEditorDialog,
|
||||
isSettingsDialogOpen,
|
||||
closeSettingsDialog,
|
||||
isFolderTrustDialogOpen,
|
||||
showPrivacyNotice,
|
||||
setShowPrivacyNotice,
|
||||
showWelcomeBackDialog,
|
||||
handleWelcomeBackClose,
|
||||
quitConfirmationRequest,
|
||||
});
|
||||
|
||||
// Message queue for handling input during streaming
|
||||
const { messageQueue, addMessage, clearQueue, getQueuedMessagesText } =
|
||||
useMessageQueue({
|
||||
@@ -720,21 +777,52 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
setPressedOnce: (value: boolean) => void,
|
||||
timerRef: ReturnType<typeof useRef<NodeJS.Timeout | null>>,
|
||||
) => {
|
||||
// Fast double-press: Direct quit (preserve user habit)
|
||||
if (pressedOnce) {
|
||||
if (timerRef.current) {
|
||||
clearTimeout(timerRef.current);
|
||||
}
|
||||
// Directly invoke the central command handler.
|
||||
// Exit directly without showing confirmation dialog
|
||||
handleSlashCommand('/quit');
|
||||
} else {
|
||||
setPressedOnce(true);
|
||||
timerRef.current = setTimeout(() => {
|
||||
setPressedOnce(false);
|
||||
timerRef.current = null;
|
||||
}, CTRL_EXIT_PROMPT_DURATION_MS);
|
||||
return;
|
||||
}
|
||||
|
||||
// First press: Prioritize cleanup tasks
|
||||
|
||||
// Special case: If quit-confirm dialog is open, Ctrl+C means "quit immediately"
|
||||
if (quitConfirmationRequest) {
|
||||
handleSlashCommand('/quit');
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. Close other dialogs (highest priority)
|
||||
if (closeAnyOpenDialog()) {
|
||||
return; // Dialog closed, end processing
|
||||
}
|
||||
|
||||
// 2. Cancel ongoing requests
|
||||
if (streamingState === StreamingState.Responding) {
|
||||
cancelOngoingRequest?.();
|
||||
return; // Request cancelled, end processing
|
||||
}
|
||||
|
||||
// 3. Clear input buffer (if has content)
|
||||
if (buffer.text.length > 0) {
|
||||
buffer.setText('');
|
||||
return; // Input cleared, end processing
|
||||
}
|
||||
|
||||
// All cleanup tasks completed, show quit confirmation dialog
|
||||
handleSlashCommand('/quit-confirm');
|
||||
},
|
||||
[handleSlashCommand],
|
||||
[
|
||||
handleSlashCommand,
|
||||
quitConfirmationRequest,
|
||||
closeAnyOpenDialog,
|
||||
streamingState,
|
||||
cancelOngoingRequest,
|
||||
buffer,
|
||||
],
|
||||
);
|
||||
|
||||
const handleGlobalKeypress = useCallback(
|
||||
@@ -772,9 +860,6 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
if (isAuthenticating) {
|
||||
return;
|
||||
}
|
||||
if (!ctrlCPressedOnce) {
|
||||
cancelOngoingRequest?.();
|
||||
}
|
||||
handleExit(ctrlCPressedOnce, setCtrlCPressedOnce, ctrlCTimerRef);
|
||||
} else if (keyMatchers[Command.EXIT](key)) {
|
||||
if (buffer.text.length > 0) {
|
||||
@@ -863,7 +948,8 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
(streamingState === StreamingState.Idle ||
|
||||
streamingState === StreamingState.Responding) &&
|
||||
!initError &&
|
||||
!isProcessing;
|
||||
!isProcessing &&
|
||||
!showWelcomeBackDialog;
|
||||
|
||||
const handleClearScreen = useCallback(() => {
|
||||
clearItems();
|
||||
@@ -941,7 +1027,10 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
!isAuthDialogOpen &&
|
||||
!isThemeDialogOpen &&
|
||||
!isEditorDialogOpen &&
|
||||
!isSubagentCreateDialogOpen &&
|
||||
!showPrivacyNotice &&
|
||||
!showWelcomeBackDialog &&
|
||||
welcomeBackChoice !== 'restart' &&
|
||||
geminiClient?.isInitialized?.()
|
||||
) {
|
||||
submitQuery(initialPrompt);
|
||||
@@ -954,7 +1043,10 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
isAuthDialogOpen,
|
||||
isThemeDialogOpen,
|
||||
isEditorDialogOpen,
|
||||
isSubagentCreateDialogOpen,
|
||||
showPrivacyNotice,
|
||||
showWelcomeBackDialog,
|
||||
welcomeBackChoice,
|
||||
geminiClient,
|
||||
]);
|
||||
|
||||
@@ -1065,6 +1157,13 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
{showWelcomeBackDialog && welcomeBackInfo?.hasHistory && (
|
||||
<WelcomeBackDialog
|
||||
welcomeBackInfo={welcomeBackInfo}
|
||||
onSelect={handleWelcomeBackSelection}
|
||||
onClose={handleWelcomeBackClose}
|
||||
/>
|
||||
)}
|
||||
{showWorkspaceMigrationDialog ? (
|
||||
<WorkspaceMigrationDialog
|
||||
workspaceExtensions={workspaceExtensions}
|
||||
@@ -1081,6 +1180,17 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
onSelect={handleFolderTrustSelect}
|
||||
isRestarting={isRestarting}
|
||||
/>
|
||||
) : quitConfirmationRequest ? (
|
||||
<QuitConfirmationDialog
|
||||
onSelect={(choice) => {
|
||||
const result = handleQuitConfirmationSelect(choice);
|
||||
if (result?.shouldQuit) {
|
||||
quitConfirmationRequest.onConfirm(true, result.action);
|
||||
} else {
|
||||
quitConfirmationRequest.onConfirm(false);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
) : shellConfirmationRequest ? (
|
||||
<ShellConfirmationDialog request={shellConfirmationRequest} />
|
||||
) : confirmationRequest ? (
|
||||
@@ -1126,6 +1236,20 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
onRestartRequest={() => process.exit(0)}
|
||||
/>
|
||||
</Box>
|
||||
) : isSubagentCreateDialogOpen ? (
|
||||
<Box flexDirection="column">
|
||||
<AgentCreationWizard
|
||||
onClose={closeSubagentCreateDialog}
|
||||
config={config}
|
||||
/>
|
||||
</Box>
|
||||
) : isAgentsManagerDialogOpen ? (
|
||||
<Box flexDirection="column">
|
||||
<AgentsManagerDialog
|
||||
onClose={closeAgentsManagerDialog}
|
||||
config={config}
|
||||
/>
|
||||
</Box>
|
||||
) : isAuthenticating ? (
|
||||
<>
|
||||
{isQwenAuth && isQwenAuthenticating ? (
|
||||
@@ -1262,7 +1386,7 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
)}
|
||||
{ctrlCPressedOnce ? (
|
||||
<Text color={Colors.AccentYellow}>
|
||||
Press Ctrl+C again to exit.
|
||||
Press Ctrl+C again to confirm exit.
|
||||
</Text>
|
||||
) : ctrlDPressedOnce ? (
|
||||
<Text color={Colors.AccentYellow}>
|
||||
|
||||
Reference in New Issue
Block a user