This commit is contained in:
yiliang114
2025-11-18 14:25:05 +08:00
parent 247c237647
commit 39426be9a1
3 changed files with 78 additions and 30 deletions

View File

@@ -459,6 +459,17 @@ export class WebViewProvider {
</html>`; </html>`;
} }
/**
* Reset agent initialization state
* Call this when auth cache is cleared to force re-authentication
*/
resetAgentState(): void {
console.log('[WebViewProvider] Resetting agent state');
this.agentInitialized = false;
// Disconnect existing connection
this.agentManager.disconnect();
}
dispose(): void { dispose(): void {
this.panel?.dispose(); this.panel?.dispose();
this.agentManager.disconnect(); this.agentManager.disconnect();

View File

@@ -62,6 +62,12 @@ export class QwenAgentManager {
workingDir: string, workingDir: string,
authStateManager?: AuthStateManager, authStateManager?: AuthStateManager,
): Promise<void> { ): Promise<void> {
const connectId = Date.now();
console.log(`\n========================================`);
console.log(`[QwenAgentManager] 🚀 CONNECT() CALLED - ID: ${connectId}`);
console.log(`[QwenAgentManager] Call stack:\n${new Error().stack}`);
console.log(`========================================\n`);
this.currentWorkingDir = workingDir; this.currentWorkingDir = workingDir;
const config = vscode.workspace.getConfiguration('qwenCode'); const config = vscode.workspace.getConfiguration('qwenCode');
const cliPath = config.get<string>('qwen.cliPath', 'qwen'); const cliPath = config.get<string>('qwen.cliPath', 'qwen');
@@ -156,43 +162,54 @@ export class QwenAgentManager {
// Create new session if we couldn't restore one // Create new session if we couldn't restore one
if (!sessionRestored) { if (!sessionRestored) {
console.log('[QwenAgentManager] Creating new session...'); console.log('[QwenAgentManager] Creating new session...');
console.log(
`[QwenAgentManager] ⚠️ WORKAROUND: Skipping explicit authenticate() call`,
);
console.log(
`[QwenAgentManager] ⚠️ Reason: newSession() internally calls refreshAuth(), which triggers device flow`,
);
console.log(
`[QwenAgentManager] ⚠️ Calling authenticate() first causes double authentication`,
);
// Authenticate only if needed (not cached or session restore failed) // WORKAROUND: Skip explicit authenticate() call
if (needsAuth) { // The newSession() method will internally call config.refreshAuth(),
await this.authenticateWithRetry(authMethod, 3); // which will trigger device flow if no valid token exists.
// Save successful auth to cache // Calling authenticate() first causes a duplicate OAuth flow due to a bug in Qwen CLI
if (authStateManager) { // where authenticate() doesn't properly save refresh token for newSession() to use.
await authStateManager.saveAuthState(workingDir, authMethod);
}
}
// Try to create session // Try to create session (which will trigger auth internally if needed)
try { try {
console.log(
`\n🔐 [AUTO AUTH] newSession will handle authentication automatically\n`,
);
await this.newSessionWithRetry(workingDir, 3); await this.newSessionWithRetry(workingDir, 3);
console.log('[QwenAgentManager] New session created successfully'); console.log('[QwenAgentManager] New session created successfully');
} catch (sessionError) {
// If we used cached auth but session creation failed,
// the cached auth might be invalid (token expired on server)
// Clear cache and retry with fresh authentication
if (!needsAuth && authStateManager) {
console.log(
'[QwenAgentManager] Session creation failed with cached auth, clearing cache and re-authenticating...',
);
await authStateManager.clearAuthState();
// Retry with fresh authentication // Save auth state after successful session creation
await this.authenticateWithRetry(authMethod, 3); if (authStateManager) {
await authStateManager.saveAuthState(workingDir, authMethod);
await this.newSessionWithRetry(workingDir, 3);
console.log( console.log(
'[QwenAgentManager] Successfully authenticated and created session after cache invalidation', '[QwenAgentManager] Saving auth state after successful session creation',
); );
} else { await authStateManager.saveAuthState(workingDir, authMethod);
// If we already tried with fresh auth, or no auth manager, just throw }
} catch (sessionError) {
console.log(`\n⚠ [SESSION FAILED] newSessionWithRetry threw error\n`);
console.log(`[QwenAgentManager] Error details:`, sessionError);
// If session creation failed, clear cache and let user retry
if (authStateManager) {
console.log('[QwenAgentManager] Clearing auth cache due to failure');
await authStateManager.clearAuthState();
}
throw sessionError; throw sessionError;
} }
} }
}
console.log(`\n========================================`);
console.log(`[QwenAgentManager] ✅ CONNECT() COMPLETED SUCCESSFULLY`);
console.log(`========================================\n`);
} }
/** /**
@@ -202,19 +219,31 @@ export class QwenAgentManager {
authMethod: string, authMethod: string,
maxRetries: number, maxRetries: number,
): Promise<void> { ): Promise<void> {
const timestamp = new Date().toISOString();
const callStack = new Error().stack;
console.log(
`[QwenAgentManager] 🔐 AUTHENTICATION CALL STARTED at ${timestamp}`,
);
console.log(
`[QwenAgentManager] Auth method: ${authMethod}, Max retries: ${maxRetries}`,
);
console.log(`[QwenAgentManager] Call stack:\n${callStack}`);
for (let attempt = 1; attempt <= maxRetries; attempt++) { for (let attempt = 1; attempt <= maxRetries; attempt++) {
try { try {
console.log( console.log(
`[QwenAgentManager] Authenticating (attempt ${attempt}/${maxRetries})...`, `[QwenAgentManager] 📝 Authenticating (attempt ${attempt}/${maxRetries})...`,
); );
await this.connection.authenticate(authMethod); await this.connection.authenticate(authMethod);
console.log('[QwenAgentManager] Authentication successful'); console.log(
`[QwenAgentManager] ✅ Authentication successful on attempt ${attempt}`,
);
return; return;
} catch (error) { } catch (error) {
const errorMessage = const errorMessage =
error instanceof Error ? error.message : String(error); error instanceof Error ? error.message : String(error);
console.error( console.error(
`[QwenAgentManager] Authentication attempt ${attempt} failed:`, `[QwenAgentManager] Authentication attempt ${attempt} failed:`,
errorMessage, errorMessage,
); );
@@ -226,7 +255,9 @@ export class QwenAgentManager {
// Wait before retrying (exponential backoff) // Wait before retrying (exponential backoff)
const delay = Math.min(1000 * Math.pow(2, attempt - 1), 5000); const delay = Math.min(1000 * Math.pow(2, attempt - 1), 5000);
console.log(`[QwenAgentManager] Retrying in ${delay}ms...`); console.log(
`[QwenAgentManager] ⏳ Retrying in ${delay}ms... (${maxRetries - attempt} retries remaining)`,
);
await new Promise((resolve) => setTimeout(resolve, delay)); await new Promise((resolve) => setTimeout(resolve, delay));
} }
} }

View File

@@ -147,6 +147,12 @@ export async function activate(context: vscode.ExtensionContext) {
}), }),
vscode.commands.registerCommand('qwenCode.clearAuthCache', async () => { vscode.commands.registerCommand('qwenCode.clearAuthCache', async () => {
await authStateManager.clearAuthState(); await authStateManager.clearAuthState();
// Reset WebView agent state to force re-authentication
if (webViewProvider) {
webViewProvider.resetAgentState();
}
vscode.window.showInformationMessage( vscode.window.showInformationMessage(
'Qwen Code authentication cache cleared. You will need to login again on next connection.', 'Qwen Code authentication cache cleared. You will need to login again on next connection.',
); );