mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-04 14:40:45 +00:00
Merge pull request #2656 from QwenLM/fix-issue-qwen-code
fix: resolve /clear command and ESC key lag caused by hooks system
This commit is contained in:
commit
cd935a5896
8 changed files with 297 additions and 25 deletions
|
|
@ -140,6 +140,71 @@ describe('clearCommand', () => {
|
|||
expect(mockContext.ui.clear).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should clear UI before resetChat for immediate responsiveness', async () => {
|
||||
if (!clearCommand.action) {
|
||||
throw new Error('clearCommand must have an action.');
|
||||
}
|
||||
|
||||
const callOrder: string[] = [];
|
||||
(mockContext.ui.clear as ReturnType<typeof vi.fn>).mockImplementation(
|
||||
() => {
|
||||
callOrder.push('ui.clear');
|
||||
},
|
||||
);
|
||||
mockResetChat.mockImplementation(async () => {
|
||||
callOrder.push('resetChat');
|
||||
});
|
||||
|
||||
await clearCommand.action(mockContext, '');
|
||||
|
||||
// ui.clear should be called before resetChat for immediate UI feedback
|
||||
const clearIndex = callOrder.indexOf('ui.clear');
|
||||
const resetIndex = callOrder.indexOf('resetChat');
|
||||
expect(clearIndex).toBeGreaterThanOrEqual(0);
|
||||
expect(resetIndex).toBeGreaterThanOrEqual(0);
|
||||
expect(clearIndex).toBeLessThan(resetIndex);
|
||||
});
|
||||
|
||||
it('should not await hook events (fire-and-forget)', async () => {
|
||||
if (!clearCommand.action) {
|
||||
throw new Error('clearCommand must have an action.');
|
||||
}
|
||||
|
||||
// Make hooks take a long time - they should not block
|
||||
let sessionEndResolved = false;
|
||||
let sessionStartResolved = false;
|
||||
mockFireSessionEndEvent.mockImplementation(
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
sessionEndResolved = true;
|
||||
resolve(undefined);
|
||||
}, 5000);
|
||||
}),
|
||||
);
|
||||
mockFireSessionStartEvent.mockImplementation(
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
sessionStartResolved = true;
|
||||
resolve(undefined);
|
||||
}, 5000);
|
||||
}),
|
||||
);
|
||||
|
||||
await clearCommand.action(mockContext, '');
|
||||
|
||||
// The action should complete immediately without waiting for hooks
|
||||
expect(mockContext.ui.clear).toHaveBeenCalledTimes(1);
|
||||
expect(mockResetChat).toHaveBeenCalledTimes(1);
|
||||
// Hooks should have been called but not necessarily resolved
|
||||
expect(mockFireSessionEndEvent).toHaveBeenCalled();
|
||||
expect(mockFireSessionStartEvent).toHaveBeenCalled();
|
||||
// Hooks should NOT have resolved yet since they have 5s timeouts
|
||||
expect(sessionEndResolved).toBe(false);
|
||||
expect(sessionStartResolved).toBe(false);
|
||||
});
|
||||
|
||||
it('should not attempt to reset chat if config service is not available', async () => {
|
||||
if (!clearCommand.action) {
|
||||
throw new Error('clearCommand must have an action.');
|
||||
|
|
|
|||
|
|
@ -27,14 +27,13 @@ export const clearCommand: SlashCommand = {
|
|||
const { config } = context.services;
|
||||
|
||||
if (config) {
|
||||
// Fire SessionEnd event before clearing (current session ends)
|
||||
try {
|
||||
await config
|
||||
.getHookSystem()
|
||||
?.fireSessionEndEvent(SessionEndReason.Clear);
|
||||
} catch (err) {
|
||||
config.getDebugLogger().warn(`SessionEnd hook failed: ${err}`);
|
||||
}
|
||||
// Fire SessionEnd event (non-blocking to avoid UI lag)
|
||||
config
|
||||
.getHookSystem()
|
||||
?.fireSessionEndEvent(SessionEndReason.Clear)
|
||||
.catch((err) => {
|
||||
config.getDebugLogger().warn(`SessionEnd hook failed: ${err}`);
|
||||
});
|
||||
|
||||
const newSessionId = config.startNewSession();
|
||||
|
||||
|
|
@ -54,6 +53,9 @@ export const clearCommand: SlashCommand = {
|
|||
context.session.startNewSession(newSessionId);
|
||||
}
|
||||
|
||||
// Clear UI first for immediate responsiveness
|
||||
context.ui.clear();
|
||||
|
||||
const geminiClient = config.getGeminiClient();
|
||||
if (geminiClient) {
|
||||
context.ui.setDebugMessage(
|
||||
|
|
@ -66,22 +68,20 @@ export const clearCommand: SlashCommand = {
|
|||
context.ui.setDebugMessage(t('Starting a new session and clearing.'));
|
||||
}
|
||||
|
||||
// Fire SessionStart event after clearing (new session starts)
|
||||
try {
|
||||
await config
|
||||
.getHookSystem()
|
||||
?.fireSessionStartEvent(
|
||||
SessionStartSource.Clear,
|
||||
config.getModel() ?? '',
|
||||
String(config.getApprovalMode()) as PermissionMode,
|
||||
);
|
||||
} catch (err) {
|
||||
config.getDebugLogger().warn(`SessionStart hook failed: ${err}`);
|
||||
}
|
||||
// Fire SessionStart event (non-blocking to avoid UI lag)
|
||||
config
|
||||
.getHookSystem()
|
||||
?.fireSessionStartEvent(
|
||||
SessionStartSource.Clear,
|
||||
config.getModel() ?? '',
|
||||
String(config.getApprovalMode()) as PermissionMode,
|
||||
)
|
||||
.catch((err) => {
|
||||
config.getDebugLogger().warn(`SessionStart hook failed: ${err}`);
|
||||
});
|
||||
} else {
|
||||
context.ui.setDebugMessage(t('Starting a new session and clearing.'));
|
||||
context.ui.clear();
|
||||
}
|
||||
|
||||
context.ui.clear();
|
||||
},
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue