Files
qwen-code/packages/vscode-ide-companion/src/webview/handlers/MessageRouter.ts
易良 65796e2799 Fix/vscode ide companion completion menu content (#1243)
* refactor(vscode-ide-companion/types): move ApprovalModeValue type to dedicated file

feat(vscode-ide-companion/file-context): improve file context handling and search

Enhance file context hook to better handle search queries and reduce redundant requests.
Track last query to optimize when to refetch full file list.
Improve logging for debugging purposes.

* feat(vscode-ide-companion/completion): enhance completion menu performance and refresh logic

Implement item comparison to prevent unnecessary re-renders when completion items
haven't actually changed. Optimize refresh logic to only trigger when workspace
files content changes. Improve completion menu stability and responsiveness.

refactor(vscode-ide-companion/handlers): remove SettingsMessageHandler and consolidate functionality

Move setApprovalMode functionality from SettingsMessageHandler to SessionMessageHandler
to reduce code duplication and simplify message handling architecture. Remove unused
settings-related imports and clean up message router configuration.

chore(vscode-ide-companion/ui): minor UI improvements and code cleanup

Consolidate imports in SessionSelector component.
Remove debug console log statement from FileMessageHandler.
Move getTimeAgo utility function to sessionGrouping file and remove obsolete timeUtils file.
Clean up completion menu CSS classes.

* fix(vscode-ide-companion): resolve all ESLint errors

Fixed unused variable errors in SessionMessageHandler.ts:
- Commented out unused conversation and messages variables

Also includes previous commits:
1. feat(vscode-ide-companion): add upgrade button to CLI version warning
2. fix(vscode-ide-companion): resolve ESLint errors in InputForm component

When the Qwen Code CLI version is below the minimum required version,
the warning message now includes an "Upgrade Now" button that opens
a terminal and runs the npm install command to upgrade the CLI.

Added tests to verify the functionality works correctly.
2025-12-13 17:37:45 +08:00

154 lines
3.9 KiB
TypeScript

/**
* @license
* Copyright 2025 Qwen Team
* SPDX-License-Identifier: Apache-2.0
*/
import type { IMessageHandler } from './BaseMessageHandler.js';
import type { QwenAgentManager } from '../../services/qwenAgentManager.js';
import type { ConversationStore } from '../../services/conversationStore.js';
import { SessionMessageHandler } from './SessionMessageHandler.js';
import { FileMessageHandler } from './FileMessageHandler.js';
import { EditorMessageHandler } from './EditorMessageHandler.js';
import { AuthMessageHandler } from './AuthMessageHandler.js';
/**
* Message Router
* Routes messages to appropriate handlers
*/
export class MessageRouter {
private handlers: IMessageHandler[] = [];
private sessionHandler: SessionMessageHandler;
private authHandler: AuthMessageHandler;
private currentConversationId: string | null = null;
private permissionHandler:
| ((message: { type: string; data: { optionId: string } }) => void)
| null = null;
constructor(
agentManager: QwenAgentManager,
conversationStore: ConversationStore,
currentConversationId: string | null,
sendToWebView: (message: unknown) => void,
) {
this.currentConversationId = currentConversationId;
// Initialize all handlers
this.sessionHandler = new SessionMessageHandler(
agentManager,
conversationStore,
currentConversationId,
sendToWebView,
);
const fileHandler = new FileMessageHandler(
agentManager,
conversationStore,
currentConversationId,
sendToWebView,
);
const editorHandler = new EditorMessageHandler(
agentManager,
conversationStore,
currentConversationId,
sendToWebView,
);
this.authHandler = new AuthMessageHandler(
agentManager,
conversationStore,
currentConversationId,
sendToWebView,
);
// Register handlers in order of priority
this.handlers = [
this.sessionHandler,
fileHandler,
editorHandler,
this.authHandler,
];
}
/**
* Route message to appropriate handler
*/
async route(message: { type: string; data?: unknown }): Promise<void> {
console.log('[MessageRouter] Routing message:', message.type);
// Handle permission response specially
if (message.type === 'permissionResponse') {
if (this.permissionHandler) {
this.permissionHandler(
message as { type: string; data: { optionId: string } },
);
}
return;
}
// Find appropriate handler
const handler = this.handlers.find((h) => h.canHandle(message.type));
if (handler) {
try {
await handler.handle(message);
} catch (error) {
console.error('[MessageRouter] Handler error:', error);
throw error;
}
} else {
console.warn(
'[MessageRouter] No handler found for message type:',
message.type,
);
}
}
/**
* Set current conversation ID
*/
setCurrentConversationId(id: string | null): void {
this.currentConversationId = id;
// Update all handlers
this.handlers.forEach((handler) => {
if ('setCurrentConversationId' in handler) {
(
handler as { setCurrentConversationId: (id: string | null) => void }
).setCurrentConversationId(id);
}
});
}
/**
* Get current conversation ID
*/
getCurrentConversationId(): string | null {
return this.currentConversationId;
}
/**
* Set permission handler
*/
setPermissionHandler(
handler: (message: { type: string; data: { optionId: string } }) => void,
): void {
this.permissionHandler = handler;
}
/**
* Set login handler
*/
setLoginHandler(handler: () => Promise<void>): void {
this.authHandler.setLoginHandler(handler);
this.sessionHandler?.setLoginHandler?.(handler);
}
/**
* Append stream content
*/
appendStreamContent(chunk: string): void {
this.sessionHandler.appendStreamContent(chunk);
}
}