fix code indexing and remove duplicates

This commit is contained in:
Prasang Prajapati 2025-09-18 12:30:41 -04:00
parent 24f0d45afd
commit 91706f4d3d
13 changed files with 33 additions and 78 deletions

View file

@ -199,9 +199,6 @@ export const SECRET_STATE_KEYS = [
"codebaseIndexMistralApiKey",
"codebaseIndexVercelAiGatewayApiKey",
"huggingFaceApiKey",
"watsonxApiKey",
"codebaseIndexWatsonxApiKey",
"codebaseIndexWatsonxProjectId",
"sambaNovaApiKey",
"zaiApiKey",
"fireworksApiKey",

View file

@ -139,7 +139,6 @@ export const providerNames = [
"vertex",
"xai",
"zai",
"watsonx",
] as const
export const providerNamesSchema = z.enum(providerNames)
@ -457,7 +456,6 @@ export const providerSettingsSchemaDiscriminated = z.discriminatedUnion("apiProv
huggingFaceSchema.merge(z.object({ apiProvider: z.literal("huggingface") })),
chutesSchema.merge(z.object({ apiProvider: z.literal("chutes") })),
litellmSchema.merge(z.object({ apiProvider: z.literal("litellm") })),
watsonxSchema.merge(z.object({ apiProvider: z.literal("watsonx") })),
cerebrasSchema.merge(z.object({ apiProvider: z.literal("cerebras") })),
sambaNovaSchema.merge(z.object({ apiProvider: z.literal("sambanova") })),
zaiSchema.merge(z.object({ apiProvider: z.literal("zai") })),

View file

@ -5,21 +5,15 @@ export const watsonxAiDefaultModelId = ""
// Common model properties
export const baseModelInfo: ModelInfo = {
maxTokens: 131072,
maxTokens: 8192,
contextWindow: 131072,
supportsImages: false,
supportsPromptCache: false,
supportsReasoningEffort: true,
supportsReasoningBudget: false,
requiredReasoningBudget: false,
inputPrice: 5.22,
outputPrice: 5.22,
}
export const watsonxAiModels = {
// IBM Granite model
"ibm/granite-3-3-8b-instruct": {
...baseModelInfo,
description: "",
},
} as const satisfies Record<string, ModelInfo>

21
pnpm-lock.yaml generated
View file

@ -618,8 +618,8 @@ importers:
specifier: ^1.0.0
version: 1.3.0(@modelcontextprotocol/sdk@1.12.0)
'@ibm-cloud/watsonx-ai':
specifier: ^1.6.8
version: 1.6.10
specifier: ^1.6.13
version: 1.6.13
'@lmstudio/sdk':
specifier: ^1.1.1
version: 1.2.0
@ -855,6 +855,9 @@ importers:
'@types/lodash':
specifier: ^4.14.201
version: 4.17.17
'@types/lodash.debounce':
specifier: ^4.0.9
version: 4.0.9
'@types/mocha':
specifier: ^10.0.10
version: 10.0.10
@ -1919,8 +1922,8 @@ packages:
resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
engines: {node: '>=18.18'}
'@ibm-cloud/watsonx-ai@1.6.10':
resolution: {integrity: sha512-aZV50/s8VZc7w0t/qcaBw3RLT3WDsAeZUJlP8EbG/csZJF3a8F7alihbGOM4lJFM7R4Z81Lucz3nfHi2KR7J4Q==}
'@ibm-cloud/watsonx-ai@1.6.13':
resolution: {integrity: sha512-INaaD7EKpycwQg/tsLm3QM5uvDF5mWLPQCj6GTk44gEZhgx1depvVG5bxwjfqkx1tbJMFuozz2p6VHOE21S+8g==}
engines: {node: '>=18.0.0'}
'@iconify/types@2.0.0':
@ -4028,6 +4031,9 @@ packages:
'@types/katex@0.16.7':
resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==}
'@types/lodash.debounce@4.0.9':
resolution: {integrity: sha512-Ma5JcgTREwpLRwMM+XwBR7DaWe96nC38uCBDFKZWbNKD+osjVzdpnUSwBcqCptrp16sSOLBAUb50Car5I0TCsQ==}
'@types/lodash@4.17.17':
resolution: {integrity: sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==}
@ -11400,10 +11406,11 @@ snapshots:
'@humanwhocodes/retry@0.4.3': {}
'@ibm-cloud/watsonx-ai@1.6.10':
'@ibm-cloud/watsonx-ai@1.6.13':
dependencies:
'@types/node': 18.19.100
extend: 3.0.2
form-data: 4.0.4
ibm-cloud-sdk-core: 5.4.3
transitivePeerDependencies:
- supports-color
@ -13639,6 +13646,10 @@ snapshots:
'@types/katex@0.16.7': {}
'@types/lodash.debounce@4.0.9':
dependencies:
'@types/lodash': 4.17.17
'@types/lodash@4.17.17': {}
'@types/mdast@3.0.15':

View file

@ -68,8 +68,8 @@ export async function getWatsonxModels(
if (Array.isArray(modelsList) && modelsList.length > 0) {
for (const model of modelsList) {
const modelId = model.id || model.name || model.model_id
const contextWindow = model.context_length || model.max_input_tokens || 8192
const maxTokens = model.max_output_tokens || Math.floor(contextWindow / 2)
const contextWindow = model.model_limits.max_sequence_length || 131072
const maxTokens = model.model_limits.max_output_tokens || Math.floor(contextWindow / 2)
let description = ""
if (model.long_description) {
@ -77,19 +77,10 @@ export async function getWatsonxModels(
} else if (model.short_description) {
description = model.short_description
}
const supportsImages = model.modality === "multimodal" || model.modality === "vision" || false
const inputPrice = model.pricing?.input_price || 0
const outputPrice = model.pricing?.output_price || 0
knownModels[modelId] = {
contextWindow,
maxTokens,
supportsPromptCache: false,
supportsImages,
supportsReasoningEffort: false,
supportsReasoningBudget: false,
requiredReasoningBudget: false,
inputPrice,
outputPrice,
description,
}
}

View file

@ -8,7 +8,6 @@ import { BaseProvider } from "./base-provider"
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"
import { WatsonXAI } from "@ibm-cloud/watsonx-ai"
import { convertToWatsonxAiMessages } from "../transform/watsonxai-format"
import { calculateApiCostOpenAI } from "../../shared/cost"
export class WatsonxAIHandler extends BaseProvider implements SingleCompletionHandler {
private options: ApiHandlerOptions
@ -127,7 +126,6 @@ export class WatsonxAIHandler extends BaseProvider implements SingleCompletionHa
const params = this.createTextChatParams(this.projectId!, modelId, watsonxMessages)
let responseText = ""
let usageInfo: any = null
// Call the IBM watsonx API using textChat (non-streaming); can be changed to streaming..
const response = await this.service.textChat(params)
@ -142,20 +140,6 @@ export class WatsonxAIHandler extends BaseProvider implements SingleCompletionHa
type: "text",
text: responseText,
}
usageInfo = response.result.usage || {}
const outputTokens = usageInfo.completion_tokens
const inputTokens = usageInfo?.prompt_tokens || 0
const modelInfo = this.getModel().info
const totalCost = calculateApiCostOpenAI(modelInfo, inputTokens, outputTokens)
yield {
type: "usage",
inputTokens: inputTokens,
outputTokens,
totalCost: totalCost,
}
} catch (error) {
await vscode.window.showErrorMessage(error.message)
yield {

View file

@ -2530,12 +2530,6 @@ export const webviewMessageHandler = async (
settings.codebaseIndexMistralApiKey,
)
}
if (settings.codebaseIndexVercelAiGatewayApiKey !== undefined) {
await provider.contextProxy.storeSecret(
"codebaseIndexVercelAiGatewayApiKey",
settings.codebaseIndexVercelAiGatewayApiKey,
)
}
if (settings.codebaseIndexWatsonxApiKey !== undefined) {
await provider.contextProxy.storeSecret(
"codebaseIndexWatsonxApiKey",
@ -2548,6 +2542,12 @@ export const webviewMessageHandler = async (
settings.codebaseIndexWatsonxProjectId,
)
}
if (settings.codebaseIndexVercelAiGatewayApiKey !== undefined) {
await provider.contextProxy.storeSecret(
"codebaseIndexVercelAiGatewayApiKey",
settings.codebaseIndexVercelAiGatewayApiKey,
)
}
// Send success response first - settings are saved regardless of validation
await provider.postMessageToWebview({
type: "codeIndexSettingsSaved",

View file

@ -442,7 +442,7 @@
"@aws-sdk/client-bedrock-runtime": "^3.848.0",
"@aws-sdk/credential-providers": "^3.848.0",
"@google/genai": "^1.0.0",
"@ibm-cloud/watsonx-ai": "^1.6.8",
"@ibm-cloud/watsonx-ai": "^1.6.13",
"@lmstudio/sdk": "^1.1.1",
"@mistralai/mistralai": "^1.9.18",
"@modelcontextprotocol/sdk": "1.12.0",
@ -522,6 +522,7 @@
"@types/diff": "^5.2.1",
"@types/diff-match-patch": "^1.0.36",
"@types/glob": "^8.1.0",
"@types/lodash.debounce": "^4.0.9",
"@types/lodash": "^4.14.201",
"@types/mocha": "^10.0.10",
"@types/node": "20.x",

View file

@ -285,6 +285,7 @@ export interface WebviewMessage {
| "gemini"
| "mistral"
| "vercel-ai-gateway"
| "watsonx"
codebaseIndexEmbedderBaseUrl?: string
codebaseIndexEmbedderModelId: string
codebaseIndexEmbedderModelDimension?: number // Generic dimension for all providers

View file

@ -408,17 +408,14 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
if (!prev.codebaseIndexMistralApiKey || prev.codebaseIndexMistralApiKey === SECRET_PLACEHOLDER) {
updated.codebaseIndexMistralApiKey = secretStatus.hasMistralApiKey ? SECRET_PLACEHOLDER : ""
}
if (!prev.codebaseIndexWatsonxApiKey || prev.codebaseIndexWatsonxApiKey === SECRET_PLACEHOLDER) {
updated.codebaseIndexWatsonxApiKey = secretStatus.hasWatsonxApiKey ? SECRET_PLACEHOLDER : ""
}
if (
!prev.codebaseIndexVercelAiGatewayApiKey ||
prev.codebaseIndexVercelAiGatewayApiKey === SECRET_PLACEHOLDER
) {
updated.codebaseIndexVercelAiGatewayApiKey = secretStatus.hasVercelAiGatewayApiKey
? SECRET_PLACEHOLDER
: ""
}
if (!prev.codebaseIndexWatsonxApiKey || prev.codebaseIndexWatsonxApiKey === SECRET_PLACEHOLDER) {
updated.codebaseIndexWatsonxApiKey = secretStatus.hasWatsonxApiKey ? SECRET_PLACEHOLDER : ""
}
@ -430,16 +427,6 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
? SECRET_PLACEHOLDER
: ""
}
if (
!prev.codebaseIndexWatsonxProjectId ||
prev.codebaseIndexWatsonxProjectId === SECRET_PLACEHOLDER
) {
updated.codebaseIndexWatsonxProjectId = secretStatus.hasWatsonxProjectId
? SECRET_PLACEHOLDER
: ""
}
return updated
}

View file

@ -621,15 +621,6 @@ const ApiOptions = ({
/>
)}
{selectedProvider === "watsonx" && (
<WatsonxAI
apiConfiguration={apiConfiguration}
setApiConfigurationField={setApiConfigurationField}
organizationAllowList={organizationAllowList}
modelValidationError={modelValidationError}
/>
)}
{selectedProvider === "sambanova" && (
<SambaNova apiConfiguration={apiConfiguration} setApiConfigurationField={setApiConfigurationField} />
)}

View file

@ -1,6 +1,6 @@
import { useCallback, useState, useEffect, useRef } from "react"
import { VSCodeLink, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
import { ModelInfo, OrganizationAllowList, watsonxAiDefaultModelId, type ProviderSettings } from "@roo-code/types"
import { ModelInfo, watsonxAiDefaultModelId, type OrganizationAllowList, type ProviderSettings } from "@roo-code/types"
import { useAppTranslation } from "@src/i18n/TranslationContext"
import { vscode } from "@src/utils/vscode"

View file

@ -352,11 +352,11 @@ function getSelectedModel({
return { id, info }
}
case "watsonx": {
const id = apiConfiguration.apiModelId ?? watsonxAiDefaultModelId
const id = apiConfiguration.watsonxModelId ?? watsonxAiDefaultModelId
const info = watsonxAiModels[id as keyof typeof watsonxAiModels]
return {
id,
info: info || undefined,
info: info,
}
}
// case "anthropic":