Skip to content

Commit 15a21d0

Browse files
committed
feat: add AWS Bedrock support for codebase indexing
- Add bedrock as a new EmbedderProvider type - Add AWS Bedrock embedding model profiles (titan-embed-text models) - Create BedrockEmbedder class with support for Titan and Cohere models - Add Bedrock configuration support to config manager and interfaces - Update service factory to create BedrockEmbedder instances - Add comprehensive tests for BedrockEmbedder - Add localization strings for Bedrock support Closes #8658
1 parent 6b8c21f commit 15a21d0

File tree

9 files changed

+899
-5
lines changed

9 files changed

+899
-5
lines changed

src/i18n/locales/en/embeddings.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717
"modelNotEmbeddingCapable": "Ollama model is not embedding capable: {{modelId}}",
1818
"hostNotFound": "Ollama host not found: {{baseUrl}}"
1919
},
20+
"bedrock": {
21+
"invalidResponseFormat": "Invalid response format from AWS Bedrock",
22+
"invalidCredentials": "Invalid AWS credentials. Please check your AWS configuration.",
23+
"accessDenied": "Access denied to AWS Bedrock service. Please check your IAM permissions.",
24+
"modelNotFound": "Model {{model}} not found in AWS Bedrock"
25+
},
2026
"scanner": {
2127
"unknownErrorProcessingFile": "Unknown error processing file {{filePath}}",
2228
"unknownErrorDeletingPoints": "Unknown error deleting points for {{filePath}}",
@@ -48,6 +54,7 @@
4854
"geminiConfigMissing": "Gemini configuration missing for embedder creation",
4955
"mistralConfigMissing": "Mistral configuration missing for embedder creation",
5056
"vercelAiGatewayConfigMissing": "Vercel AI Gateway configuration missing for embedder creation",
57+
"bedrockConfigMissing": "AWS Bedrock configuration missing for embedder creation",
5158
"invalidEmbedderType": "Invalid embedder type configured: {{embedderProvider}}",
5259
"vectorDimensionNotDeterminedOpenAiCompatible": "Could not determine vector dimension for model '{{modelId}}' with provider '{{provider}}'. Please ensure the 'Embedding Dimension' is correctly set in the OpenAI-Compatible provider settings.",
5360
"vectorDimensionNotDetermined": "Could not determine vector dimension for model '{{modelId}}' with provider '{{provider}}'. Check model profiles or configuration.",

src/services/code-index/config-manager.ts

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export class CodeIndexConfigManager {
2020
private geminiOptions?: { apiKey: string }
2121
private mistralOptions?: { apiKey: string }
2222
private vercelAiGatewayOptions?: { apiKey: string }
23+
private bedrockOptions?: { region: string; profile?: string }
2324
private qdrantUrl?: string = "http://localhost:6333"
2425
private qdrantApiKey?: string
2526
private searchMinScore?: number
@@ -49,8 +50,13 @@ export class CodeIndexConfigManager {
4950
codebaseIndexEmbedderProvider: "openai",
5051
codebaseIndexEmbedderBaseUrl: "",
5152
codebaseIndexEmbedderModelId: "",
53+
codebaseIndexEmbedderModelDimension: undefined,
5254
codebaseIndexSearchMinScore: undefined,
5355
codebaseIndexSearchMaxResults: undefined,
56+
codebaseIndexOpenAiCompatibleBaseUrl: "",
57+
codebaseIndexOpenAiCompatibleModelDimension: undefined,
58+
codebaseIndexBedrockRegion: "us-east-1",
59+
codebaseIndexBedrockProfile: "",
5460
}
5561

5662
const {
@@ -66,11 +72,13 @@ export class CodeIndexConfigManager {
6672
const openAiKey = this.contextProxy?.getSecret("codeIndexOpenAiKey") ?? ""
6773
const qdrantApiKey = this.contextProxy?.getSecret("codeIndexQdrantApiKey") ?? ""
6874
// Fix: Read OpenAI Compatible settings from the correct location within codebaseIndexConfig
69-
const openAiCompatibleBaseUrl = codebaseIndexConfig.codebaseIndexOpenAiCompatibleBaseUrl ?? ""
75+
const openAiCompatibleBaseUrl = (codebaseIndexConfig as any).codebaseIndexOpenAiCompatibleBaseUrl ?? ""
7076
const openAiCompatibleApiKey = this.contextProxy?.getSecret("codebaseIndexOpenAiCompatibleApiKey") ?? ""
7177
const geminiApiKey = this.contextProxy?.getSecret("codebaseIndexGeminiApiKey") ?? ""
7278
const mistralApiKey = this.contextProxy?.getSecret("codebaseIndexMistralApiKey") ?? ""
7379
const vercelAiGatewayApiKey = this.contextProxy?.getSecret("codebaseIndexVercelAiGatewayApiKey") ?? ""
80+
const bedrockRegion = (codebaseIndexConfig as any).codebaseIndexBedrockRegion ?? "us-east-1"
81+
const bedrockProfile = (codebaseIndexConfig as any).codebaseIndexBedrockProfile ?? ""
7482

7583
// Update instance variables with configuration
7684
this.codebaseIndexEnabled = codebaseIndexEnabled ?? true
@@ -80,7 +88,7 @@ export class CodeIndexConfigManager {
8088
this.searchMaxResults = codebaseIndexSearchMaxResults
8189

8290
// Validate and set model dimension
83-
const rawDimension = codebaseIndexConfig.codebaseIndexEmbedderModelDimension
91+
const rawDimension = (codebaseIndexConfig as any).codebaseIndexEmbedderModelDimension
8492
if (rawDimension !== undefined && rawDimension !== null) {
8593
const dimension = Number(rawDimension)
8694
if (!isNaN(dimension) && dimension > 0) {
@@ -108,6 +116,8 @@ export class CodeIndexConfigManager {
108116
this.embedderProvider = "mistral"
109117
} else if (codebaseIndexEmbedderProvider === "vercel-ai-gateway") {
110118
this.embedderProvider = "vercel-ai-gateway"
119+
} else if ((codebaseIndexEmbedderProvider as string) === "bedrock") {
120+
this.embedderProvider = "bedrock"
111121
} else {
112122
this.embedderProvider = "openai"
113123
}
@@ -129,6 +139,9 @@ export class CodeIndexConfigManager {
129139
this.geminiOptions = geminiApiKey ? { apiKey: geminiApiKey } : undefined
130140
this.mistralOptions = mistralApiKey ? { apiKey: mistralApiKey } : undefined
131141
this.vercelAiGatewayOptions = vercelAiGatewayApiKey ? { apiKey: vercelAiGatewayApiKey } : undefined
142+
this.bedrockOptions = bedrockRegion
143+
? { region: bedrockRegion, profile: bedrockProfile || undefined }
144+
: undefined
132145
}
133146

134147
/**
@@ -167,6 +180,8 @@ export class CodeIndexConfigManager {
167180
geminiApiKey: this.geminiOptions?.apiKey ?? "",
168181
mistralApiKey: this.mistralOptions?.apiKey ?? "",
169182
vercelAiGatewayApiKey: this.vercelAiGatewayOptions?.apiKey ?? "",
183+
bedrockRegion: this.bedrockOptions?.region ?? "",
184+
bedrockProfile: this.bedrockOptions?.profile ?? "",
170185
qdrantUrl: this.qdrantUrl ?? "",
171186
qdrantApiKey: this.qdrantApiKey ?? "",
172187
}
@@ -192,6 +207,7 @@ export class CodeIndexConfigManager {
192207
geminiOptions: this.geminiOptions,
193208
mistralOptions: this.mistralOptions,
194209
vercelAiGatewayOptions: this.vercelAiGatewayOptions,
210+
bedrockOptions: this.bedrockOptions,
195211
qdrantUrl: this.qdrantUrl,
196212
qdrantApiKey: this.qdrantApiKey,
197213
searchMinScore: this.currentSearchMinScore,
@@ -234,6 +250,11 @@ export class CodeIndexConfigManager {
234250
const qdrantUrl = this.qdrantUrl
235251
const isConfigured = !!(apiKey && qdrantUrl)
236252
return isConfigured
253+
} else if (this.embedderProvider === "bedrock") {
254+
const region = this.bedrockOptions?.region
255+
const qdrantUrl = this.qdrantUrl
256+
const isConfigured = !!(region && qdrantUrl)
257+
return isConfigured
237258
}
238259
return false // Should not happen if embedderProvider is always set correctly
239260
}
@@ -269,6 +290,8 @@ export class CodeIndexConfigManager {
269290
const prevGeminiApiKey = prev?.geminiApiKey ?? ""
270291
const prevMistralApiKey = prev?.mistralApiKey ?? ""
271292
const prevVercelAiGatewayApiKey = prev?.vercelAiGatewayApiKey ?? ""
293+
const prevBedrockRegion = prev?.bedrockRegion ?? ""
294+
const prevBedrockProfile = prev?.bedrockProfile ?? ""
272295
const prevQdrantUrl = prev?.qdrantUrl ?? ""
273296
const prevQdrantApiKey = prev?.qdrantApiKey ?? ""
274297

@@ -307,6 +330,8 @@ export class CodeIndexConfigManager {
307330
const currentGeminiApiKey = this.geminiOptions?.apiKey ?? ""
308331
const currentMistralApiKey = this.mistralOptions?.apiKey ?? ""
309332
const currentVercelAiGatewayApiKey = this.vercelAiGatewayOptions?.apiKey ?? ""
333+
const currentBedrockRegion = this.bedrockOptions?.region ?? ""
334+
const currentBedrockProfile = this.bedrockOptions?.profile ?? ""
310335
const currentQdrantUrl = this.qdrantUrl ?? ""
311336
const currentQdrantApiKey = this.qdrantApiKey ?? ""
312337

@@ -337,6 +362,10 @@ export class CodeIndexConfigManager {
337362
return true
338363
}
339364

365+
if (prevBedrockRegion !== currentBedrockRegion || prevBedrockProfile !== currentBedrockProfile) {
366+
return true
367+
}
368+
340369
// Check for model dimension changes (generic for all providers)
341370
if (prevModelDimension !== currentModelDimension) {
342371
return true
@@ -395,6 +424,7 @@ export class CodeIndexConfigManager {
395424
geminiOptions: this.geminiOptions,
396425
mistralOptions: this.mistralOptions,
397426
vercelAiGatewayOptions: this.vercelAiGatewayOptions,
427+
bedrockOptions: this.bedrockOptions,
398428
qdrantUrl: this.qdrantUrl,
399429
qdrantApiKey: this.qdrantApiKey,
400430
searchMinScore: this.currentSearchMinScore,

0 commit comments

Comments
 (0)