import pRetry, { AbortError } from 'p-retry'; import pTimeout from 'p-timeout'; // Global reference to reset qwen client let qwenClientResetter: (() => Promise) | null = null; export function setQwenClientResetter(resetFn: () => Promise) { qwenClientResetter = resetFn; } export async function withQwenTimeout( fn: () => Promise, { totalTimeout = 70_000, retries = 2 } = {} ): Promise { return pRetry( async () => { try { return await pTimeout(fn(), { milliseconds: totalTimeout }); } catch (error) { // Check if this is a session/connection error that requires client reset const errorMessage = (error as any)?.message || error?.toString() || ''; const isSessionError = errorMessage.includes('Session not found') || errorMessage.includes('network error') || errorMessage.includes('ERR_HTTP2_PROTOCOL_ERROR') || errorMessage.includes('Connection errored out'); if (isSessionError && qwenClientResetter) { console.log('🔄 Qwen client session error detected, resetting client...'); try { await qwenClientResetter(); console.log('✅ Qwen client reset successfully'); } catch (resetError) { console.error('❌ Failed to reset qwen client:', resetError); } } // Convert non-Error objects to proper Error objects for p-retry if (error && typeof error === 'object' && !(error instanceof Error)) { const errorMessage = (error as any).message || error.toString() || 'Network connection error'; throw new Error(errorMessage); } throw error; } }, { retries, onFailedAttempt: (error) => { console.error(`qwen3 attempt #${error.attemptNumber} failed: ${error.message}`); if (error.retriesLeft === 0) { console.error('qwen3 max retries reached, giving up'); } } } ); }