mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-05 15:31:27 +00:00
refactor(debug): replace ConsolePatcher with debugLogger and update error reporting
- Replace ConsolePatcher with centralized debugLogger utility - Refactor errorReporting to use debugLogger instead of file-based reporting - Remove user-facing console message components: - Delete ConsolePatcher.ts, useConsoleMessages.ts/hook - Delete ConsoleSummaryDisplay.tsx, DetailedMessagesDisplay.tsx - Update all tests in packages/core and packages/cli: - Mock debugLogger where needed - Remove assertions for console output on non-critical errors - Keep debugLogger assertions for fatal/network errors - Use HOME directory mocking for hermetic file system tests Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
parent
135df54f27
commit
89e3c2cd7a
64 changed files with 1240 additions and 2416 deletions
|
|
@ -457,9 +457,6 @@ describe('ControlDispatcher', () => {
|
|||
|
||||
it('should handle response for non-existent request in debug mode', () => {
|
||||
const context = createMockContext(true);
|
||||
const consoleSpy = vi
|
||||
.spyOn(console, 'error')
|
||||
.mockImplementation(() => {});
|
||||
|
||||
const dispatcherWithDebug = new ControlDispatcher(context);
|
||||
const response: CLIControlResponse = {
|
||||
|
|
@ -471,15 +468,10 @@ describe('ControlDispatcher', () => {
|
|||
},
|
||||
};
|
||||
|
||||
dispatcherWithDebug.handleControlResponse(response);
|
||||
|
||||
expect(consoleSpy).toHaveBeenCalledWith(
|
||||
expect.stringContaining(
|
||||
'[ControlDispatcher] No pending outgoing request for: non-existent',
|
||||
),
|
||||
);
|
||||
|
||||
consoleSpy.mockRestore();
|
||||
// Should not throw in debug mode
|
||||
expect(() =>
|
||||
dispatcherWithDebug.handleControlResponse(response),
|
||||
).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -599,11 +591,8 @@ describe('ControlDispatcher', () => {
|
|||
expect(() => dispatcher.handleCancel('non-existent')).not.toThrow();
|
||||
});
|
||||
|
||||
it('should log cancellation in debug mode', () => {
|
||||
it('should cancel request in debug mode without throwing', () => {
|
||||
const context = createMockContext(true);
|
||||
const consoleSpy = vi
|
||||
.spyOn(console, 'error')
|
||||
.mockImplementation(() => {});
|
||||
|
||||
const dispatcherWithDebug = new ControlDispatcher(context);
|
||||
const requestId = 'cancel-req-debug';
|
||||
|
|
@ -626,15 +615,7 @@ describe('ControlDispatcher', () => {
|
|||
timeoutId,
|
||||
);
|
||||
|
||||
dispatcherWithDebug.handleCancel(requestId);
|
||||
|
||||
expect(consoleSpy).toHaveBeenCalledWith(
|
||||
expect.stringContaining(
|
||||
'[ControlDispatcher] Cancelled incoming request: cancel-req-debug',
|
||||
),
|
||||
);
|
||||
|
||||
consoleSpy.mockRestore();
|
||||
expect(() => dispatcherWithDebug.handleCancel(requestId)).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -720,11 +701,8 @@ describe('ControlDispatcher', () => {
|
|||
expect(secondRejectCount).toBe(firstRejectCount);
|
||||
});
|
||||
|
||||
it('should log input closure in debug mode', () => {
|
||||
it('should mark input closed in debug mode without throwing', () => {
|
||||
const context = createMockContext(true);
|
||||
const consoleSpy = vi
|
||||
.spyOn(console, 'error')
|
||||
.mockImplementation(() => {});
|
||||
|
||||
const dispatcherWithDebug = new ControlDispatcher(context);
|
||||
const requestId = 'reject-req-debug';
|
||||
|
|
@ -750,15 +728,7 @@ describe('ControlDispatcher', () => {
|
|||
timeoutId,
|
||||
);
|
||||
|
||||
dispatcherWithDebug.markInputClosed();
|
||||
|
||||
expect(consoleSpy).toHaveBeenCalledWith(
|
||||
expect.stringContaining(
|
||||
'[ControlDispatcher] Input closed, rejecting 1 pending outgoing requests',
|
||||
),
|
||||
);
|
||||
|
||||
consoleSpy.mockRestore();
|
||||
expect(() => dispatcherWithDebug.markInputClosed()).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -848,21 +818,12 @@ describe('ControlDispatcher', () => {
|
|||
expect(mockSystemController.cleanup).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should log shutdown in debug mode', () => {
|
||||
it('should shutdown in debug mode without throwing', () => {
|
||||
const context = createMockContext(true);
|
||||
const consoleSpy = vi
|
||||
.spyOn(console, 'error')
|
||||
.mockImplementation(() => {});
|
||||
|
||||
const dispatcherWithDebug = new ControlDispatcher(context);
|
||||
|
||||
dispatcherWithDebug.shutdown();
|
||||
|
||||
expect(consoleSpy).toHaveBeenCalledWith(
|
||||
'[ControlDispatcher] Shutting down',
|
||||
);
|
||||
|
||||
consoleSpy.mockRestore();
|
||||
expect(() => dispatcherWithDebug.shutdown()).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ export class ControlDispatcher implements IPendingRequestRegistry {
|
|||
const requestIds = Array.from(this.pendingOutgoingRequests.keys());
|
||||
|
||||
if (this.context.debugMode) {
|
||||
console.error(
|
||||
debugLogger.debug(
|
||||
`[ControlDispatcher] Input closed, rejecting ${requestIds.length} pending outgoing requests`,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import { StreamJsonOutputAdapter } from './io/StreamJsonOutputAdapter.js';
|
|||
import { ControlDispatcher } from './control/ControlDispatcher.js';
|
||||
import { ControlContext } from './control/ControlContext.js';
|
||||
import { ControlService } from './control/ControlService.js';
|
||||
import { ConsolePatcher } from '../ui/utils/ConsolePatcher.js';
|
||||
|
||||
const runNonInteractiveMock = vi.fn();
|
||||
|
||||
|
|
@ -47,10 +46,6 @@ vi.mock('./control/ControlService.js', () => ({
|
|||
ControlService: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('../ui/utils/ConsolePatcher.js', () => ({
|
||||
ConsolePatcher: vi.fn(),
|
||||
}));
|
||||
|
||||
interface ConfigOverrides {
|
||||
getSessionId?: () => string;
|
||||
getModel?: () => string;
|
||||
|
|
@ -160,24 +155,11 @@ describe('runNonInteractiveStreamJson', () => {
|
|||
createSendSdkMcpMessage: ReturnType<typeof vi.fn>;
|
||||
};
|
||||
};
|
||||
let mockConsolePatcher: {
|
||||
patch: ReturnType<typeof vi.fn>;
|
||||
cleanup: ReturnType<typeof vi.fn>;
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
config = createConfig();
|
||||
runNonInteractiveMock.mockReset();
|
||||
|
||||
// Setup mocks
|
||||
mockConsolePatcher = {
|
||||
patch: vi.fn(),
|
||||
cleanup: vi.fn(),
|
||||
};
|
||||
(ConsolePatcher as unknown as ReturnType<typeof vi.fn>).mockImplementation(
|
||||
() => mockConsolePatcher,
|
||||
);
|
||||
|
||||
mockOutputAdapter = {
|
||||
emitResult: vi.fn(),
|
||||
} as {
|
||||
|
|
@ -236,9 +218,7 @@ describe('runNonInteractiveStreamJson', () => {
|
|||
|
||||
await runNonInteractiveStreamJson(config, '');
|
||||
|
||||
expect(mockConsolePatcher.patch).toHaveBeenCalledTimes(1);
|
||||
expect(mockDispatcher.dispatch).toHaveBeenCalledWith(initRequest);
|
||||
expect(mockConsolePatcher.cleanup).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('processes user message when received as first message', async () => {
|
||||
|
|
@ -489,8 +469,6 @@ describe('runNonInteractiveStreamJson', () => {
|
|||
await expect(runNonInteractiveStreamJson(config, '')).rejects.toThrow(
|
||||
'Stream error',
|
||||
);
|
||||
|
||||
expect(mockConsolePatcher.cleanup).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('stops processing when abort signal is triggered', async () => {
|
||||
|
|
@ -567,9 +545,6 @@ describe('runNonInteractiveStreamJson', () => {
|
|||
};
|
||||
|
||||
await runNonInteractiveStreamJson(config, '');
|
||||
|
||||
expect(mockConsolePatcher.patch).toHaveBeenCalledTimes(1);
|
||||
expect(mockConsolePatcher.cleanup).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('cleans up output adapter on completion', async () => {
|
||||
|
|
@ -598,7 +573,5 @@ describe('runNonInteractiveStreamJson', () => {
|
|||
};
|
||||
|
||||
await runNonInteractiveStreamJson(config, '');
|
||||
|
||||
expect(mockConsolePatcher.cleanup).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ import {
|
|||
} from './types.js';
|
||||
import { createMinimalSettings } from '../config/settings.js';
|
||||
import { runNonInteractive } from '../nonInteractiveCli.js';
|
||||
import { ConsolePatcher } from '../ui/utils/ConsolePatcher.js';
|
||||
|
||||
const debugLogger = createDebugLogger('NON_INTERACTIVE_SESSION');
|
||||
|
||||
|
|
@ -607,29 +606,20 @@ export async function runNonInteractiveStreamJson(
|
|||
config: Config,
|
||||
input: string,
|
||||
): Promise<void> {
|
||||
const consolePatcher = new ConsolePatcher({
|
||||
debugMode: config.getDebugMode(),
|
||||
});
|
||||
consolePatcher.patch();
|
||||
|
||||
try {
|
||||
let initialPrompt: CLIUserMessage | undefined = undefined;
|
||||
if (input && input.trim().length > 0) {
|
||||
const sessionId = config.getSessionId();
|
||||
initialPrompt = {
|
||||
type: 'user',
|
||||
session_id: sessionId,
|
||||
message: {
|
||||
role: 'user',
|
||||
content: input.trim(),
|
||||
},
|
||||
parent_tool_use_id: null,
|
||||
};
|
||||
}
|
||||
|
||||
const manager = new Session(config, initialPrompt);
|
||||
await manager.run();
|
||||
} finally {
|
||||
consolePatcher.cleanup();
|
||||
let initialPrompt: CLIUserMessage | undefined = undefined;
|
||||
if (input && input.trim().length > 0) {
|
||||
const sessionId = config.getSessionId();
|
||||
initialPrompt = {
|
||||
type: 'user',
|
||||
session_id: sessionId,
|
||||
message: {
|
||||
role: 'user',
|
||||
content: input.trim(),
|
||||
},
|
||||
parent_tool_use_id: null,
|
||||
};
|
||||
}
|
||||
|
||||
const manager = new Session(config, initialPrompt);
|
||||
await manager.run();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue