mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-19 09:33:53 +00:00
fix: proper SIGINT handler and output in nonInteractive mode
This commit is contained in:
@@ -5,7 +5,6 @@ export default {
|
|||||||
commands: 'Commands',
|
commands: 'Commands',
|
||||||
configuration: 'Configuration',
|
configuration: 'Configuration',
|
||||||
'configuration-v1': 'Configuration (v1)',
|
'configuration-v1': 'Configuration (v1)',
|
||||||
'structured-output': 'Structured Output',
|
|
||||||
themes: 'Themes',
|
themes: 'Themes',
|
||||||
tutorials: 'Tutorials',
|
tutorials: 'Tutorials',
|
||||||
'keyboard-shortcuts': 'Keyboard Shortcuts',
|
'keyboard-shortcuts': 'Keyboard Shortcuts',
|
||||||
|
|||||||
@@ -220,12 +220,6 @@ export async function main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isDebugMode = cliConfig.isDebugMode(argv);
|
const isDebugMode = cliConfig.isDebugMode(argv);
|
||||||
const consolePatcher = new ConsolePatcher({
|
|
||||||
stderr: true,
|
|
||||||
debugMode: isDebugMode,
|
|
||||||
});
|
|
||||||
consolePatcher.patch();
|
|
||||||
registerCleanup(consolePatcher.cleanup);
|
|
||||||
|
|
||||||
dns.setDefaultResultOrder(
|
dns.setDefaultResultOrder(
|
||||||
validateDnsResolutionOrder(settings.merged.advanced?.dnsResolutionOrder),
|
validateDnsResolutionOrder(settings.merged.advanced?.dnsResolutionOrder),
|
||||||
@@ -350,6 +344,15 @@ export async function main() {
|
|||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup unified ConsolePatcher based on interactive mode
|
||||||
|
const isInteractive = config.isInteractive();
|
||||||
|
const consolePatcher = new ConsolePatcher({
|
||||||
|
stderr: isInteractive,
|
||||||
|
debugMode: isDebugMode,
|
||||||
|
});
|
||||||
|
consolePatcher.patch();
|
||||||
|
registerCleanup(consolePatcher.cleanup);
|
||||||
|
|
||||||
const wasRaw = process.stdin.isRaw;
|
const wasRaw = process.stdin.isRaw;
|
||||||
let kittyProtocolDetectionComplete: Promise<boolean> | undefined;
|
let kittyProtocolDetectionComplete: Promise<boolean> | undefined;
|
||||||
if (config.isInteractive() && !wasRaw && process.stdin.isTTY) {
|
if (config.isInteractive() && !wasRaw && process.stdin.isTTY) {
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Config } from '@qwen-code/qwen-code-core';
|
import type { Config } from '@qwen-code/qwen-code-core';
|
||||||
import { ConsolePatcher } from '../ui/utils/ConsolePatcher.js';
|
|
||||||
import { StreamJsonInputReader } from './io/StreamJsonInputReader.js';
|
import { StreamJsonInputReader } from './io/StreamJsonInputReader.js';
|
||||||
import { StreamJsonOutputAdapter } from './io/StreamJsonOutputAdapter.js';
|
import { StreamJsonOutputAdapter } from './io/StreamJsonOutputAdapter.js';
|
||||||
import { ControlContext } from './control/ControlContext.js';
|
import { ControlContext } from './control/ControlContext.js';
|
||||||
@@ -96,7 +95,6 @@ class SessionManager {
|
|||||||
private dispatcher: ControlDispatcher | null = null;
|
private dispatcher: ControlDispatcher | null = null;
|
||||||
private controlService: ControlService | null = null;
|
private controlService: ControlService | null = null;
|
||||||
private controlSystemEnabled: boolean | null = null;
|
private controlSystemEnabled: boolean | null = null;
|
||||||
private consolePatcher: ConsolePatcher;
|
|
||||||
private debugMode: boolean;
|
private debugMode: boolean;
|
||||||
private shutdownHandler: (() => void) | null = null;
|
private shutdownHandler: (() => void) | null = null;
|
||||||
private initialPrompt: CLIUserMessage | null = null;
|
private initialPrompt: CLIUserMessage | null = null;
|
||||||
@@ -113,11 +111,6 @@ class SessionManager {
|
|||||||
this.abortController = new AbortController();
|
this.abortController = new AbortController();
|
||||||
this.initialPrompt = initialPrompt ?? null;
|
this.initialPrompt = initialPrompt ?? null;
|
||||||
|
|
||||||
this.consolePatcher = new ConsolePatcher({
|
|
||||||
stderr: true,
|
|
||||||
debugMode: this.debugMode,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.inputReader = new StreamJsonInputReader();
|
this.inputReader = new StreamJsonInputReader();
|
||||||
this.outputAdapter = new StreamJsonOutputAdapter(
|
this.outputAdapter = new StreamJsonOutputAdapter(
|
||||||
config,
|
config,
|
||||||
@@ -232,8 +225,6 @@ class SessionManager {
|
|||||||
*/
|
*/
|
||||||
async run(): Promise<void> {
|
async run(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
this.consolePatcher.patch();
|
|
||||||
|
|
||||||
if (this.debugMode) {
|
if (this.debugMode) {
|
||||||
console.error('[SessionManager] Starting session', this.sessionId);
|
console.error('[SessionManager] Starting session', this.sessionId);
|
||||||
}
|
}
|
||||||
@@ -264,7 +255,6 @@ class SessionManager {
|
|||||||
await this.shutdown();
|
await this.shutdown();
|
||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
this.consolePatcher.cleanup();
|
|
||||||
// Ensure signal handlers are always cleaned up even if shutdown wasn't called
|
// Ensure signal handlers are always cleaned up even if shutdown wasn't called
|
||||||
this.cleanupSignalHandlers();
|
this.cleanupSignalHandlers();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import { StreamJsonOutputAdapter } from './nonInteractive/io/StreamJsonOutputAda
|
|||||||
import type { ControlService } from './nonInteractive/control/ControlService.js';
|
import type { ControlService } from './nonInteractive/control/ControlService.js';
|
||||||
|
|
||||||
import { handleSlashCommand } from './nonInteractiveCliCommands.js';
|
import { handleSlashCommand } from './nonInteractiveCliCommands.js';
|
||||||
import { ConsolePatcher } from './ui/utils/ConsolePatcher.js';
|
|
||||||
import { handleAtCommand } from './ui/hooks/atCommandProcessor.js';
|
import { handleAtCommand } from './ui/hooks/atCommandProcessor.js';
|
||||||
import {
|
import {
|
||||||
handleError,
|
handleError,
|
||||||
@@ -67,11 +66,6 @@ export async function runNonInteractive(
|
|||||||
options: RunNonInteractiveOptions = {},
|
options: RunNonInteractiveOptions = {},
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return promptIdContext.run(prompt_id, async () => {
|
return promptIdContext.run(prompt_id, async () => {
|
||||||
const consolePatcher = new ConsolePatcher({
|
|
||||||
stderr: true,
|
|
||||||
debugMode: config.getDebugMode(),
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create output adapter based on format
|
// Create output adapter based on format
|
||||||
let adapter: JsonOutputAdapterInterface | undefined;
|
let adapter: JsonOutputAdapterInterface | undefined;
|
||||||
const outputFormat = config.getOutputFormat();
|
const outputFormat = config.getOutputFormat();
|
||||||
@@ -102,12 +96,22 @@ export async function runNonInteractive(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const geminiClient = config.getGeminiClient();
|
||||||
|
const abortController = options.abortController ?? new AbortController();
|
||||||
|
|
||||||
|
// Setup signal handlers for graceful shutdown
|
||||||
|
const shutdownHandler = () => {
|
||||||
|
if (config.getDebugMode()) {
|
||||||
|
console.error('[runNonInteractive] Shutdown signal received');
|
||||||
|
}
|
||||||
|
abortController.abort();
|
||||||
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
consolePatcher.patch();
|
|
||||||
process.stdout.on('error', stdoutErrorHandler);
|
process.stdout.on('error', stdoutErrorHandler);
|
||||||
|
|
||||||
const geminiClient = config.getGeminiClient();
|
process.on('SIGINT', shutdownHandler);
|
||||||
const abortController = options.abortController ?? new AbortController();
|
process.on('SIGTERM', shutdownHandler);
|
||||||
|
|
||||||
let initialPartList: PartListUnion | null = extractPartsFromUserMessage(
|
let initialPartList: PartListUnion | null = extractPartsFromUserMessage(
|
||||||
options.userMessage,
|
options.userMessage,
|
||||||
@@ -362,7 +366,9 @@ export async function runNonInteractive(
|
|||||||
handleError(error, config);
|
handleError(error, config);
|
||||||
} finally {
|
} finally {
|
||||||
process.stdout.removeListener('error', stdoutErrorHandler);
|
process.stdout.removeListener('error', stdoutErrorHandler);
|
||||||
consolePatcher.cleanup();
|
// Cleanup signal handlers
|
||||||
|
process.removeListener('SIGINT', shutdownHandler);
|
||||||
|
process.removeListener('SIGTERM', shutdownHandler);
|
||||||
if (isTelemetrySdkInitialized()) {
|
if (isTelemetrySdkInitialized()) {
|
||||||
await shutdownTelemetry(config);
|
await shutdownTelemetry(config);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user