Skip to content

Commit e3c9df1

Browse files
fix roo-mote suggestions
1 parent e5623b0 commit e3c9df1

File tree

21 files changed

+101
-35
lines changed

21 files changed

+101
-35
lines changed

src/api/providers/watsonx.ts

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { BaseProvider } from "./base-provider"
88
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"
99
import { WatsonXAI } from "@ibm-cloud/watsonx-ai"
1010
import { convertToWatsonxAiMessages } from "../transform/watsonxai-format"
11+
import OpenAI from "openai"
1112

1213
export class WatsonxAIHandler extends BaseProvider implements SingleCompletionHandler {
1314
private options: ApiHandlerOptions
@@ -18,13 +19,13 @@ export class WatsonxAIHandler extends BaseProvider implements SingleCompletionHa
1819
super()
1920
this.options = options
2021

21-
this.projectId = (this.options as any).watsonxProjectId
22+
this.projectId = this.options.watsonxProjectId
2223
if (!this.projectId) {
2324
throw new Error("You must provide a valid IBM watsonx project ID.")
2425
}
2526

26-
const serviceUrl = (this.options as any).watsonxBaseUrl
27-
const platform = (this.options as any).watsonxPlatform
27+
const serviceUrl = this.options.watsonxBaseUrl
28+
const platform = this.options.watsonxPlatform
2829

2930
try {
3031
const serviceOptions: any = {
@@ -41,6 +42,19 @@ export class WatsonxAIHandler extends BaseProvider implements SingleCompletionHa
4142

4243
const authType = this.options.watsonxAuthType
4344

45+
if (!serviceUrl) {
46+
throw new Error("You must provide a valid service URL for IBM Cloud Pak for Data.")
47+
}
48+
49+
try {
50+
const url = new URL(serviceUrl)
51+
if (!url.protocol || !url.hostname) {
52+
throw new Error("Invalid URL format for IBM Cloud Pak for Data.")
53+
}
54+
} catch (error) {
55+
throw new Error(`Invalid base URL for IBM Cloud Pak for Data: ${serviceUrl}`)
56+
}
57+
4458
if (authType === "apiKey") {
4559
const apiKey = this.options.watsonxApiKey
4660
if (!apiKey) {
@@ -141,11 +155,23 @@ export class WatsonxAIHandler extends BaseProvider implements SingleCompletionHa
141155
text: responseText,
142156
}
143157
} catch (error) {
144-
await vscode.window.showErrorMessage(error.message)
158+
// Extract error message and type from the error object
159+
const errorMessage = error?.message || String(error)
160+
const errorType = error?.type || undefined
161+
let detailedMessage = errorMessage
162+
if (errorMessage.includes("401") || errorMessage.includes("Unauthorized")) {
163+
detailedMessage = `Authentication failed: ${errorMessage}. Please check your API key and credentials.`
164+
} else if (errorMessage.includes("404")) {
165+
detailedMessage = `Model or endpoint not found: ${errorMessage}. Please verify the model ID and base URL.`
166+
} else if (errorMessage.includes("timeout") || errorMessage.includes("ECONNREFUSED")) {
167+
detailedMessage = `Connection failed: ${errorMessage}. Please check your network connection and base URL.`
168+
}
169+
170+
await vscode.window.showErrorMessage(detailedMessage)
145171
yield {
146172
type: "error",
147-
error: error.type,
148-
message: error.message,
173+
error: errorType,
174+
message: errorMessage,
149175
}
150176
}
151177
}
@@ -169,7 +195,15 @@ export class WatsonxAIHandler extends BaseProvider implements SingleCompletionHa
169195
}
170196
return response.result.choices[0].message.content
171197
} catch (error) {
172-
throw new Error(`IBM watsonx completion error: ${error.message}`)
198+
const errorMessage = error instanceof Error ? error.message : String(error)
199+
if (errorMessage.includes("401") || errorMessage.includes("Unauthorized")) {
200+
throw new Error(`IBM watsonx authentication failed: ${errorMessage}`)
201+
} else if (errorMessage.includes("404")) {
202+
throw new Error(`IBM watsonx model not found: ${errorMessage}`)
203+
} else if (errorMessage.includes("timeout") || errorMessage.includes("ECONNREFUSED")) {
204+
throw new Error(`IBM watsonx connection failed: ${errorMessage}`)
205+
}
206+
throw new Error(`IBM watsonx completion error: ${errorMessage}`)
173207
}
174208
}
175209

@@ -179,9 +213,16 @@ export class WatsonxAIHandler extends BaseProvider implements SingleCompletionHa
179213
* @returns An object containing the model ID and model information
180214
*/
181215
override getModel(): { id: string; info: ModelInfo } {
216+
const modelId = this.options.watsonxModelId || watsonxAiDefaultModelId
217+
const modelInfo = watsonxAiModels[modelId as WatsonxAIModelId]
182218
return {
183-
id: (this.options as any).watsonxModelId || watsonxAiDefaultModelId,
184-
info: watsonxAiModels[(this.options as any).watsonxModelId as WatsonxAIModelId] || "",
219+
id: modelId,
220+
info: modelInfo || {
221+
maxTokens: 8192,
222+
contextWindow: 131072,
223+
supportsImages: false,
224+
supportsPromptCache: false,
225+
},
185226
}
186227
}
187228
}

src/services/code-index/embedders/watsonx.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,13 @@ export class WatsonxEmbedder implements IEmbedder {
135135
let lastError
136136
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
137137
try {
138-
await delay(1000)
138+
if (attempt > 0) {
139+
const delayMs = INITIAL_DELAY_MS * Math.pow(2, attempt - 1)
140+
await delay(delayMs)
141+
console.warn(
142+
`IBM watsonx API call failed, retrying in ${delayMs}ms (attempt ${attempt + 1}/${MAX_RETRIES})`,
143+
)
144+
}
139145
const response = await this.watsonxClient.embedText({
140146
modelId: modelToUse,
141147
inputs: [text],
@@ -176,13 +182,6 @@ export class WatsonxEmbedder implements IEmbedder {
176182
}
177183
} catch (error) {
178184
lastError = error
179-
180-
if (attempt < MAX_RETRIES - 1) {
181-
const delayMs = INITIAL_DELAY_MS * Math.pow(2, attempt)
182-
console.warn(
183-
`IBM watsonx API call failed, retrying in ${delayMs}ms (attempt ${attempt + 1}/${MAX_RETRIES})`,
184-
)
185-
}
186185
}
187186
}
188187

webview-ui/src/i18n/locales/ca/settings.json

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webview-ui/src/i18n/locales/de/settings.json

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webview-ui/src/i18n/locales/en/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,8 @@
837837
"apiKey": "You must provide a valid API key.",
838838
"projectId": "You must provide a valid project ID.",
839839
"username": "You must provide a valid username.",
840-
"baseUrl": "You must provide a valid IBM Cloud Pak for Data URL.",
840+
"baseUrl": "You must provide IBM Cloud Pak for Data URL.",
841+
"invalidUrl": "You must provide a valid IBM Cloud Pak for Data URL.",
841842
"region": "You must select a region.",
842843
"password": "You must provide a valid password."
843844
}

webview-ui/src/i18n/locales/es/settings.json

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webview-ui/src/i18n/locales/fr/settings.json

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webview-ui/src/i18n/locales/hi/settings.json

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webview-ui/src/i18n/locales/id/settings.json

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webview-ui/src/i18n/locales/it/settings.json

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)