mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-19 09:33:53 +00:00
Merge branch 'main' into feat/subagents
This commit is contained in:
@@ -23,6 +23,9 @@ 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';
|
||||
@@ -42,6 +45,7 @@ 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,
|
||||
@@ -109,8 +113,8 @@ import { SettingsDialog } from './components/SettingsDialog.js';
|
||||
import { setUpdateHandler } from '../utils/handleAutoUpdate.js';
|
||||
import { appEvents, AppEvent } from '../utils/events.js';
|
||||
import { isNarrowWidth } from './utils/isNarrowWidth.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;
|
||||
|
||||
@@ -292,6 +296,9 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
setIsTrustedFolder,
|
||||
);
|
||||
|
||||
const { showQuitConfirmation, handleQuitConfirmationSelect } =
|
||||
useQuitConfirmation();
|
||||
|
||||
const {
|
||||
isAuthDialogOpen,
|
||||
openAuthDialog,
|
||||
@@ -568,6 +575,7 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
commandContext,
|
||||
shellConfirmationRequest,
|
||||
confirmationRequest,
|
||||
quitConfirmationRequest,
|
||||
} = useSlashCommandProcessor(
|
||||
config,
|
||||
settings,
|
||||
@@ -588,6 +596,7 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
toggleVimEnabled,
|
||||
setIsProcessing,
|
||||
setGeminiMdFileCount,
|
||||
showQuitConfirmation,
|
||||
);
|
||||
|
||||
const buffer = useTextBuffer({
|
||||
@@ -628,6 +637,34 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
() => cancelHandlerRef.current(),
|
||||
);
|
||||
|
||||
// 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.selectedAuthType,
|
||||
isEditorDialogOpen,
|
||||
exitEditorDialog,
|
||||
isSettingsDialogOpen,
|
||||
closeSettingsDialog,
|
||||
isFolderTrustDialogOpen,
|
||||
showPrivacyNotice,
|
||||
setShowPrivacyNotice,
|
||||
showWelcomeBackDialog,
|
||||
handleWelcomeBackClose,
|
||||
quitConfirmationRequest,
|
||||
});
|
||||
|
||||
// Message queue for handling input during streaming
|
||||
const { messageQueue, addMessage, clearQueue, getQueuedMessagesText } =
|
||||
useMessageQueue({
|
||||
@@ -699,21 +736,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(
|
||||
@@ -746,9 +814,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) {
|
||||
@@ -780,7 +845,6 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
ctrlDTimerRef,
|
||||
handleSlashCommand,
|
||||
isAuthenticating,
|
||||
cancelOngoingRequest,
|
||||
],
|
||||
);
|
||||
|
||||
@@ -836,7 +900,8 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
(streamingState === StreamingState.Idle ||
|
||||
streamingState === StreamingState.Responding) &&
|
||||
!initError &&
|
||||
!isProcessing;
|
||||
!isProcessing &&
|
||||
!showWelcomeBackDialog;
|
||||
|
||||
const handleClearScreen = useCallback(() => {
|
||||
clearItems();
|
||||
@@ -916,6 +981,8 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
!isEditorDialogOpen &&
|
||||
!isSubagentCreateDialogOpen &&
|
||||
!showPrivacyNotice &&
|
||||
!showWelcomeBackDialog &&
|
||||
welcomeBackChoice !== 'restart' &&
|
||||
geminiClient?.isInitialized?.()
|
||||
) {
|
||||
submitQuery(initialPrompt);
|
||||
@@ -930,6 +997,8 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
isEditorDialogOpen,
|
||||
isSubagentCreateDialogOpen,
|
||||
showPrivacyNotice,
|
||||
showWelcomeBackDialog,
|
||||
welcomeBackChoice,
|
||||
geminiClient,
|
||||
]);
|
||||
|
||||
@@ -1038,6 +1107,13 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
{showWelcomeBackDialog && welcomeBackInfo?.hasHistory && (
|
||||
<WelcomeBackDialog
|
||||
welcomeBackInfo={welcomeBackInfo}
|
||||
onSelect={handleWelcomeBackSelection}
|
||||
onClose={handleWelcomeBackClose}
|
||||
/>
|
||||
)}
|
||||
|
||||
{shouldShowIdePrompt && currentIDE ? (
|
||||
<IdeIntegrationNudge
|
||||
@@ -1046,6 +1122,17 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||
/>
|
||||
) : isFolderTrustDialogOpen ? (
|
||||
<FolderTrustDialog onSelect={handleFolderTrustSelect} />
|
||||
) : 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 ? (
|
||||
@@ -1240,7 +1327,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