@@ -18,6 +18,16 @@ const cacheFolder = path.resolve(
1818) ;
1919
2020class OpenRouterLLM {
21+ /**
22+ * Some openrouter models never send a finish_reason and thus leave the stream open in the UI.
23+ * However, because OR is a middleware it can also wait an inordinately long time between chunks so we need
24+ * to ensure that we dont accidentally close the stream too early. If the time between chunks is greater than this timeout
25+ * we will close the stream and assume it to be complete. This is common for free models or slow providers they can
26+ * possibly delegate to during invocation.
27+ * @type {number }
28+ */
29+ defaultTimeout = 3_000 ;
30+
2131 constructor ( embedder = null , modelPreference = null ) {
2232 if ( ! process . env . OPENROUTER_API_KEY )
2333 throw new Error ( "No OpenRouter API key was set." ) ;
@@ -85,15 +95,16 @@ class OpenRouterLLM {
8595 * OpenRouter has various models that never return `finish_reasons` and thus leave the stream open
8696 * which causes issues in subsequent messages. This timeout value forces us to close the stream after
8797 * x milliseconds. This is a configurable value via the OPENROUTER_TIMEOUT_MS value
88- * @returns {number } The timeout value in milliseconds (default: 500 )
98+ * @returns {number } The timeout value in milliseconds (default: 3_000 )
8999 */
90100 #parseTimeout( ) {
91101 this . log (
92- `OpenRouter timeout is set to ${ process . env . OPENROUTER_TIMEOUT_MS ?? 500 } ms`
102+ `OpenRouter timeout is set to ${ process . env . OPENROUTER_TIMEOUT_MS ?? this . defaultTimeout } ms`
93103 ) ;
94- if ( isNaN ( Number ( process . env . OPENROUTER_TIMEOUT_MS ) ) ) return 500 ;
104+ if ( isNaN ( Number ( process . env . OPENROUTER_TIMEOUT_MS ) ) )
105+ return this . defaultTimeout ;
95106 const setValue = Number ( process . env . OPENROUTER_TIMEOUT_MS ) ;
96- if ( setValue < 500 ) return 500 ;
107+ if ( setValue < 500 ) return 500 ; // 500ms is the minimum timeout
97108 return setValue ;
98109 }
99110
0 commit comments