-
Notifications
You must be signed in to change notification settings - Fork 2.6k
feat: add configurable timeout for LM Studio provider #6523
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -15,6 +15,9 @@ import { BaseProvider } from "./base-provider" | |||||||||||||||||
| import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index" | ||||||||||||||||||
| import { getModels, getModelsFromCache } from "./fetchers/modelCache" | ||||||||||||||||||
|
|
||||||||||||||||||
| // Default timeout for LM Studio requests (10 minutes) | ||||||||||||||||||
| const LMSTUDIO_DEFAULT_TIMEOUT_SECONDS = 600 | ||||||||||||||||||
|
|
||||||||||||||||||
| export class LmStudioHandler extends BaseProvider implements SingleCompletionHandler { | ||||||||||||||||||
| protected options: ApiHandlerOptions | ||||||||||||||||||
| private client: OpenAI | ||||||||||||||||||
|
|
@@ -73,7 +76,19 @@ export class LmStudioHandler extends BaseProvider implements SingleCompletionHan | |||||||||||||||||
|
|
||||||||||||||||||
| let assistantText = "" | ||||||||||||||||||
|
|
||||||||||||||||||
| // Create AbortController with configurable timeout | ||||||||||||||||||
| const controller = new AbortController() | ||||||||||||||||||
| let timeoutId: NodeJS.Timeout | undefined | ||||||||||||||||||
|
|
||||||||||||||||||
| // Get timeout from settings or use default (10 minutes) | ||||||||||||||||||
| const timeoutSeconds = this.options.lmStudioTimeoutSeconds ?? LMSTUDIO_DEFAULT_TIMEOUT_SECONDS | ||||||||||||||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this intentional that LM Studio has a configurable timeout while Bedrock has a hardcoded 10-minute timeout? This inconsistency might confuse users who work with both providers. Consider either making Bedrock's timeout configurable too, or documenting why they differ. |
||||||||||||||||||
| const timeoutMs = timeoutSeconds * 1000 | ||||||||||||||||||
|
|
||||||||||||||||||
| try { | ||||||||||||||||||
| timeoutId = setTimeout(() => { | ||||||||||||||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The timeout setup logic is duplicated between
Suggested change
|
||||||||||||||||||
| controller.abort() | ||||||||||||||||||
| }, timeoutMs) | ||||||||||||||||||
|
|
||||||||||||||||||
| const params: OpenAI.Chat.ChatCompletionCreateParamsStreaming & { draft_model?: string } = { | ||||||||||||||||||
| model: this.getModel().id, | ||||||||||||||||||
| messages: openAiMessages, | ||||||||||||||||||
|
|
@@ -85,7 +100,9 @@ export class LmStudioHandler extends BaseProvider implements SingleCompletionHan | |||||||||||||||||
| params.draft_model = this.options.lmStudioDraftModelId | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| const results = await this.client.chat.completions.create(params) | ||||||||||||||||||
| const results = await this.client.chat.completions.create(params, { | ||||||||||||||||||
| signal: controller.signal, | ||||||||||||||||||
| }) | ||||||||||||||||||
|
|
||||||||||||||||||
| const matcher = new XmlMatcher( | ||||||||||||||||||
| "think", | ||||||||||||||||||
|
|
@@ -124,7 +141,20 @@ export class LmStudioHandler extends BaseProvider implements SingleCompletionHan | |||||||||||||||||
| inputTokens, | ||||||||||||||||||
| outputTokens, | ||||||||||||||||||
| } as const | ||||||||||||||||||
| } catch (error) { | ||||||||||||||||||
|
|
||||||||||||||||||
| // Clear timeout after successful completion | ||||||||||||||||||
| clearTimeout(timeoutId) | ||||||||||||||||||
| } catch (error: unknown) { | ||||||||||||||||||
| // Clear timeout on error | ||||||||||||||||||
| clearTimeout(timeoutId) | ||||||||||||||||||
|
|
||||||||||||||||||
| // Check if this is an abort error (timeout) | ||||||||||||||||||
| if (error instanceof Error && error.name === "AbortError") { | ||||||||||||||||||
| throw new Error( | ||||||||||||||||||
| `LM Studio request timed out after ${timeoutSeconds} seconds. This can happen with large models that need more processing time. Try increasing the timeout in LM Studio settings or use a smaller model.`, | ||||||||||||||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When logging timeout errors, could we include the actual timeout value used? This would help with debugging:
Suggested change
|
||||||||||||||||||
| ) | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| throw new Error( | ||||||||||||||||||
| "Please check the LM Studio developer logs to debug what went wrong. You may need to load the model with a larger context length to work with Roo Code's prompts.", | ||||||||||||||||||
| ) | ||||||||||||||||||
|
|
@@ -147,7 +177,19 @@ export class LmStudioHandler extends BaseProvider implements SingleCompletionHan | |||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| async completePrompt(prompt: string): Promise<string> { | ||||||||||||||||||
| // Create AbortController with configurable timeout | ||||||||||||||||||
| const controller = new AbortController() | ||||||||||||||||||
| let timeoutId: NodeJS.Timeout | undefined | ||||||||||||||||||
|
|
||||||||||||||||||
| // Get timeout from settings or use default (10 minutes) | ||||||||||||||||||
| const timeoutSeconds = this.options.lmStudioTimeoutSeconds ?? LMSTUDIO_DEFAULT_TIMEOUT_SECONDS | ||||||||||||||||||
| const timeoutMs = timeoutSeconds * 1000 | ||||||||||||||||||
|
|
||||||||||||||||||
| try { | ||||||||||||||||||
| timeoutId = setTimeout(() => { | ||||||||||||||||||
| controller.abort() | ||||||||||||||||||
| }, timeoutMs) | ||||||||||||||||||
|
|
||||||||||||||||||
| // Create params object with optional draft model | ||||||||||||||||||
| const params: any = { | ||||||||||||||||||
| model: this.getModel().id, | ||||||||||||||||||
|
|
@@ -161,9 +203,25 @@ export class LmStudioHandler extends BaseProvider implements SingleCompletionHan | |||||||||||||||||
| params.draft_model = this.options.lmStudioDraftModelId | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| const response = await this.client.chat.completions.create(params) | ||||||||||||||||||
| const response = await this.client.chat.completions.create(params, { | ||||||||||||||||||
| signal: controller.signal, | ||||||||||||||||||
| }) | ||||||||||||||||||
|
|
||||||||||||||||||
| // Clear timeout after successful completion | ||||||||||||||||||
| clearTimeout(timeoutId) | ||||||||||||||||||
|
|
||||||||||||||||||
| return response.choices[0]?.message.content || "" | ||||||||||||||||||
| } catch (error) { | ||||||||||||||||||
| } catch (error: unknown) { | ||||||||||||||||||
| // Clear timeout on error | ||||||||||||||||||
| clearTimeout(timeoutId) | ||||||||||||||||||
|
|
||||||||||||||||||
| // Check if this is an abort error (timeout) | ||||||||||||||||||
| if (error instanceof Error && error.name === "AbortError") { | ||||||||||||||||||
| throw new Error( | ||||||||||||||||||
| `LM Studio request timed out after ${timeoutSeconds} seconds. This can happen with large models that need more processing time. Try increasing the timeout in LM Studio settings or use a smaller model.`, | ||||||||||||||||||
| ) | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| throw new Error( | ||||||||||||||||||
| "Please check the LM Studio developer logs to debug what went wrong. You may need to load the model with a larger context length to work with Roo Code's prompts.", | ||||||||||||||||||
| ) | ||||||||||||||||||
|
|
||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is 30 seconds a reasonable minimum for very large models? Some models might need more time just to start processing. Consider if 60 seconds would be a safer minimum to prevent user frustration.