From 15a21d02da070f8b7a64d8dd002f1224522ee88b Mon Sep 17 00:00:00 2001 From: Roo Code Date: Tue, 14 Oct 2025 16:38:52 +0000 Subject: [PATCH 01/17] 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 --- src/i18n/locales/en/embeddings.json | 7 + src/services/code-index/config-manager.ts | 34 +- .../embedders/__tests__/bedrock.spec.ts | 521 ++++++++++++++++++ src/services/code-index/embedders/bedrock.ts | 294 ++++++++++ src/services/code-index/interfaces/config.ts | 3 + .../code-index/interfaces/embedder.ts | 9 +- src/services/code-index/interfaces/manager.ts | 9 +- src/services/code-index/service-factory.ts | 6 + src/shared/embeddingModels.ts | 21 +- 9 files changed, 899 insertions(+), 5 deletions(-) create mode 100644 src/services/code-index/embedders/__tests__/bedrock.spec.ts create mode 100644 src/services/code-index/embedders/bedrock.ts diff --git a/src/i18n/locales/en/embeddings.json b/src/i18n/locales/en/embeddings.json index fc902cadc16..210f6219fb3 100644 --- a/src/i18n/locales/en/embeddings.json +++ b/src/i18n/locales/en/embeddings.json @@ -17,6 +17,12 @@ "modelNotEmbeddingCapable": "Ollama model is not embedding capable: {{modelId}}", "hostNotFound": "Ollama host not found: {{baseUrl}}" }, + "bedrock": { + "invalidResponseFormat": "Invalid response format from AWS Bedrock", + "invalidCredentials": "Invalid AWS credentials. Please check your AWS configuration.", + "accessDenied": "Access denied to AWS Bedrock service. Please check your IAM permissions.", + "modelNotFound": "Model {{model}} not found in AWS Bedrock" + }, "scanner": { "unknownErrorProcessingFile": "Unknown error processing file {{filePath}}", "unknownErrorDeletingPoints": "Unknown error deleting points for {{filePath}}", @@ -48,6 +54,7 @@ "geminiConfigMissing": "Gemini configuration missing for embedder creation", "mistralConfigMissing": "Mistral configuration missing for embedder creation", "vercelAiGatewayConfigMissing": "Vercel AI Gateway configuration missing for embedder creation", + "bedrockConfigMissing": "AWS Bedrock configuration missing for embedder creation", "invalidEmbedderType": "Invalid embedder type configured: {{embedderProvider}}", "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.", "vectorDimensionNotDetermined": "Could not determine vector dimension for model '{{modelId}}' with provider '{{provider}}'. Check model profiles or configuration.", diff --git a/src/services/code-index/config-manager.ts b/src/services/code-index/config-manager.ts index 2c0e8bb5c9e..d61f7541bea 100644 --- a/src/services/code-index/config-manager.ts +++ b/src/services/code-index/config-manager.ts @@ -20,6 +20,7 @@ export class CodeIndexConfigManager { private geminiOptions?: { apiKey: string } private mistralOptions?: { apiKey: string } private vercelAiGatewayOptions?: { apiKey: string } + private bedrockOptions?: { region: string; profile?: string } private qdrantUrl?: string = "http://localhost:6333" private qdrantApiKey?: string private searchMinScore?: number @@ -49,8 +50,13 @@ export class CodeIndexConfigManager { codebaseIndexEmbedderProvider: "openai", codebaseIndexEmbedderBaseUrl: "", codebaseIndexEmbedderModelId: "", + codebaseIndexEmbedderModelDimension: undefined, codebaseIndexSearchMinScore: undefined, codebaseIndexSearchMaxResults: undefined, + codebaseIndexOpenAiCompatibleBaseUrl: "", + codebaseIndexOpenAiCompatibleModelDimension: undefined, + codebaseIndexBedrockRegion: "us-east-1", + codebaseIndexBedrockProfile: "", } const { @@ -66,11 +72,13 @@ export class CodeIndexConfigManager { const openAiKey = this.contextProxy?.getSecret("codeIndexOpenAiKey") ?? "" const qdrantApiKey = this.contextProxy?.getSecret("codeIndexQdrantApiKey") ?? "" // Fix: Read OpenAI Compatible settings from the correct location within codebaseIndexConfig - const openAiCompatibleBaseUrl = codebaseIndexConfig.codebaseIndexOpenAiCompatibleBaseUrl ?? "" + const openAiCompatibleBaseUrl = (codebaseIndexConfig as any).codebaseIndexOpenAiCompatibleBaseUrl ?? "" const openAiCompatibleApiKey = this.contextProxy?.getSecret("codebaseIndexOpenAiCompatibleApiKey") ?? "" const geminiApiKey = this.contextProxy?.getSecret("codebaseIndexGeminiApiKey") ?? "" const mistralApiKey = this.contextProxy?.getSecret("codebaseIndexMistralApiKey") ?? "" const vercelAiGatewayApiKey = this.contextProxy?.getSecret("codebaseIndexVercelAiGatewayApiKey") ?? "" + const bedrockRegion = (codebaseIndexConfig as any).codebaseIndexBedrockRegion ?? "us-east-1" + const bedrockProfile = (codebaseIndexConfig as any).codebaseIndexBedrockProfile ?? "" // Update instance variables with configuration this.codebaseIndexEnabled = codebaseIndexEnabled ?? true @@ -80,7 +88,7 @@ export class CodeIndexConfigManager { this.searchMaxResults = codebaseIndexSearchMaxResults // Validate and set model dimension - const rawDimension = codebaseIndexConfig.codebaseIndexEmbedderModelDimension + const rawDimension = (codebaseIndexConfig as any).codebaseIndexEmbedderModelDimension if (rawDimension !== undefined && rawDimension !== null) { const dimension = Number(rawDimension) if (!isNaN(dimension) && dimension > 0) { @@ -108,6 +116,8 @@ export class CodeIndexConfigManager { this.embedderProvider = "mistral" } else if (codebaseIndexEmbedderProvider === "vercel-ai-gateway") { this.embedderProvider = "vercel-ai-gateway" + } else if ((codebaseIndexEmbedderProvider as string) === "bedrock") { + this.embedderProvider = "bedrock" } else { this.embedderProvider = "openai" } @@ -129,6 +139,9 @@ export class CodeIndexConfigManager { this.geminiOptions = geminiApiKey ? { apiKey: geminiApiKey } : undefined this.mistralOptions = mistralApiKey ? { apiKey: mistralApiKey } : undefined this.vercelAiGatewayOptions = vercelAiGatewayApiKey ? { apiKey: vercelAiGatewayApiKey } : undefined + this.bedrockOptions = bedrockRegion + ? { region: bedrockRegion, profile: bedrockProfile || undefined } + : undefined } /** @@ -167,6 +180,8 @@ export class CodeIndexConfigManager { geminiApiKey: this.geminiOptions?.apiKey ?? "", mistralApiKey: this.mistralOptions?.apiKey ?? "", vercelAiGatewayApiKey: this.vercelAiGatewayOptions?.apiKey ?? "", + bedrockRegion: this.bedrockOptions?.region ?? "", + bedrockProfile: this.bedrockOptions?.profile ?? "", qdrantUrl: this.qdrantUrl ?? "", qdrantApiKey: this.qdrantApiKey ?? "", } @@ -192,6 +207,7 @@ export class CodeIndexConfigManager { geminiOptions: this.geminiOptions, mistralOptions: this.mistralOptions, vercelAiGatewayOptions: this.vercelAiGatewayOptions, + bedrockOptions: this.bedrockOptions, qdrantUrl: this.qdrantUrl, qdrantApiKey: this.qdrantApiKey, searchMinScore: this.currentSearchMinScore, @@ -234,6 +250,11 @@ export class CodeIndexConfigManager { const qdrantUrl = this.qdrantUrl const isConfigured = !!(apiKey && qdrantUrl) return isConfigured + } else if (this.embedderProvider === "bedrock") { + const region = this.bedrockOptions?.region + const qdrantUrl = this.qdrantUrl + const isConfigured = !!(region && qdrantUrl) + return isConfigured } return false // Should not happen if embedderProvider is always set correctly } @@ -269,6 +290,8 @@ export class CodeIndexConfigManager { const prevGeminiApiKey = prev?.geminiApiKey ?? "" const prevMistralApiKey = prev?.mistralApiKey ?? "" const prevVercelAiGatewayApiKey = prev?.vercelAiGatewayApiKey ?? "" + const prevBedrockRegion = prev?.bedrockRegion ?? "" + const prevBedrockProfile = prev?.bedrockProfile ?? "" const prevQdrantUrl = prev?.qdrantUrl ?? "" const prevQdrantApiKey = prev?.qdrantApiKey ?? "" @@ -307,6 +330,8 @@ export class CodeIndexConfigManager { const currentGeminiApiKey = this.geminiOptions?.apiKey ?? "" const currentMistralApiKey = this.mistralOptions?.apiKey ?? "" const currentVercelAiGatewayApiKey = this.vercelAiGatewayOptions?.apiKey ?? "" + const currentBedrockRegion = this.bedrockOptions?.region ?? "" + const currentBedrockProfile = this.bedrockOptions?.profile ?? "" const currentQdrantUrl = this.qdrantUrl ?? "" const currentQdrantApiKey = this.qdrantApiKey ?? "" @@ -337,6 +362,10 @@ export class CodeIndexConfigManager { return true } + if (prevBedrockRegion !== currentBedrockRegion || prevBedrockProfile !== currentBedrockProfile) { + return true + } + // Check for model dimension changes (generic for all providers) if (prevModelDimension !== currentModelDimension) { return true @@ -395,6 +424,7 @@ export class CodeIndexConfigManager { geminiOptions: this.geminiOptions, mistralOptions: this.mistralOptions, vercelAiGatewayOptions: this.vercelAiGatewayOptions, + bedrockOptions: this.bedrockOptions, qdrantUrl: this.qdrantUrl, qdrantApiKey: this.qdrantApiKey, searchMinScore: this.currentSearchMinScore, diff --git a/src/services/code-index/embedders/__tests__/bedrock.spec.ts b/src/services/code-index/embedders/__tests__/bedrock.spec.ts new file mode 100644 index 00000000000..b88ce786fdd --- /dev/null +++ b/src/services/code-index/embedders/__tests__/bedrock.spec.ts @@ -0,0 +1,521 @@ +import type { MockedFunction } from "vitest" +import { BedrockRuntimeClient, InvokeModelCommand } from "@aws-sdk/client-bedrock-runtime" + +import { BedrockEmbedder } from "../bedrock" +import { MAX_ITEM_TOKENS, INITIAL_RETRY_DELAY_MS } from "../../constants" + +// Mock the AWS SDK +vitest.mock("@aws-sdk/client-bedrock-runtime", () => { + return { + BedrockRuntimeClient: vitest.fn().mockImplementation(() => ({ + send: vitest.fn(), + })), + InvokeModelCommand: vitest.fn().mockImplementation((input) => ({ + input, + })), + } +}) +vitest.mock("@aws-sdk/credential-providers", () => ({ + fromEnv: vitest.fn().mockReturnValue(Promise.resolve({})), + fromIni: vitest.fn().mockReturnValue(Promise.resolve({})), +})) + +// Mock TelemetryService +vitest.mock("@roo-code/telemetry", () => ({ + TelemetryService: { + instance: { + captureEvent: vitest.fn(), + }, + }, +})) + +// Mock i18n +vitest.mock("../../../../i18n", () => ({ + t: (key: string, params?: Record) => { + const translations: Record = { + "embeddings:authenticationFailed": + "Failed to create embeddings: Authentication failed. Please check your AWS credentials.", + "embeddings:failedWithStatus": `Failed to create embeddings after ${params?.attempts} attempts: HTTP ${params?.statusCode} - ${params?.errorMessage}`, + "embeddings:failedWithError": `Failed to create embeddings after ${params?.attempts} attempts: ${params?.errorMessage}`, + "embeddings:failedMaxAttempts": `Failed to create embeddings after ${params?.attempts} attempts`, + "embeddings:textExceedsTokenLimit": `Text at index ${params?.index} exceeds maximum token limit (${params?.itemTokens} > ${params?.maxTokens}). Skipping.`, + "embeddings:rateLimitRetry": `Rate limit hit, retrying in ${params?.delayMs}ms (attempt ${params?.attempt}/${params?.maxRetries})`, + "embeddings:bedrock.invalidResponseFormat": "Invalid response format from Bedrock", + "embeddings:bedrock.invalidCredentials": "Invalid AWS credentials", + "embeddings:bedrock.accessDenied": "Access denied to Bedrock service", + "embeddings:bedrock.modelNotFound": `Model ${params?.model} not found`, + "embeddings:validation.authenticationFailed": "Authentication failed", + "embeddings:validation.connectionFailed": "Connection failed", + "embeddings:validation.serviceUnavailable": "Service unavailable", + "embeddings:validation.configurationError": "Configuration error", + } + return translations[key] || key + }, +})) + +// Mock console methods +const consoleMocks = { + error: vitest.spyOn(console, "error").mockImplementation(() => {}), + warn: vitest.spyOn(console, "warn").mockImplementation(() => {}), +} + +describe("BedrockEmbedder", () => { + let embedder: BedrockEmbedder + let mockSend: MockedFunction + + beforeEach(() => { + vitest.clearAllMocks() + consoleMocks.error.mockClear() + consoleMocks.warn.mockClear() + + mockSend = vitest.fn() + + // Set up the mock implementation + const MockedBedrockRuntimeClient = BedrockRuntimeClient as any + MockedBedrockRuntimeClient.mockImplementation(() => ({ + send: mockSend, + })) + + embedder = new BedrockEmbedder("us-east-1", "amazon.titan-embed-text-v2:0") + }) + + afterEach(() => { + vitest.clearAllMocks() + }) + + describe("constructor", () => { + it("should initialize with provided region and model", () => { + expect(embedder.embedderInfo.name).toBe("bedrock") + }) + + it("should use default region if not provided", () => { + const defaultEmbedder = new BedrockEmbedder() + expect(defaultEmbedder).toBeDefined() + }) + + it("should use profile if provided", () => { + const profileEmbedder = new BedrockEmbedder("us-west-2", undefined, "dev-profile") + expect(profileEmbedder).toBeDefined() + }) + }) + + describe("createEmbeddings", () => { + const testModelId = "amazon.titan-embed-text-v2:0" + + it("should create embeddings for a single text with Titan model", async () => { + const testTexts = ["Hello world"] + const mockResponse = { + body: new TextEncoder().encode( + JSON.stringify({ + embedding: [0.1, 0.2, 0.3], + inputTextTokenCount: 2, + }), + ), + } + mockSend.mockResolvedValue(mockResponse) + + const result = await embedder.createEmbeddings(testTexts) + + expect(mockSend).toHaveBeenCalled() + const command = mockSend.mock.calls[0][0] as any + expect(command.input.modelId).toBe(testModelId) + const bodyStr = + typeof command.input.body === "string" + ? command.input.body + : new TextDecoder().decode(command.input.body as Uint8Array) + expect(JSON.parse(bodyStr || "{}")).toEqual({ + inputText: "Hello world", + }) + + expect(result).toEqual({ + embeddings: [[0.1, 0.2, 0.3]], + usage: { promptTokens: 2, totalTokens: 2 }, + }) + }) + + it("should create embeddings for multiple texts", async () => { + const testTexts = ["Hello world", "Another text"] + const mockResponses = [ + { + body: new TextEncoder().encode( + JSON.stringify({ + embedding: [0.1, 0.2, 0.3], + inputTextTokenCount: 2, + }), + ), + }, + { + body: new TextEncoder().encode( + JSON.stringify({ + embedding: [0.4, 0.5, 0.6], + inputTextTokenCount: 3, + }), + ), + }, + ] + + mockSend.mockResolvedValueOnce(mockResponses[0]).mockResolvedValueOnce(mockResponses[1]) + + const result = await embedder.createEmbeddings(testTexts) + + expect(mockSend).toHaveBeenCalledTimes(2) + expect(result).toEqual({ + embeddings: [ + [0.1, 0.2, 0.3], + [0.4, 0.5, 0.6], + ], + usage: { promptTokens: 5, totalTokens: 5 }, + }) + }) + + it("should handle Cohere model format", async () => { + const cohereEmbedder = new BedrockEmbedder("us-east-1", "cohere.embed-english-v3") + const testTexts = ["Hello world"] + const mockResponse = { + body: new TextEncoder().encode( + JSON.stringify({ + embeddings: [[0.1, 0.2, 0.3]], + }), + ), + } + mockSend.mockResolvedValue(mockResponse) + + const result = await cohereEmbedder.createEmbeddings(testTexts) + + const command = mockSend.mock.calls[0][0] as InvokeModelCommand + const bodyStr = + typeof command.input.body === "string" + ? command.input.body + : new TextDecoder().decode(command.input.body as Uint8Array) + expect(JSON.parse(bodyStr || "{}")).toEqual({ + texts: ["Hello world"], + input_type: "search_document", + }) + + expect(result).toEqual({ + embeddings: [[0.1, 0.2, 0.3]], + usage: { promptTokens: 0, totalTokens: 0 }, + }) + }) + + it("should use custom model when provided", async () => { + const testTexts = ["Hello world"] + const customModel = "amazon.titan-embed-text-v1" + const mockResponse = { + body: new TextEncoder().encode( + JSON.stringify({ + embedding: [0.1, 0.2, 0.3], + inputTextTokenCount: 2, + }), + ), + } + mockSend.mockResolvedValue(mockResponse) + + await embedder.createEmbeddings(testTexts, customModel) + + const command = mockSend.mock.calls[0][0] as InvokeModelCommand + expect(command.input.modelId).toBe(customModel) + }) + + it("should handle missing token count data gracefully", async () => { + const testTexts = ["Hello world"] + const mockResponse = { + body: new TextEncoder().encode( + JSON.stringify({ + embedding: [0.1, 0.2, 0.3], + }), + ), + } + mockSend.mockResolvedValue(mockResponse) + + const result = await embedder.createEmbeddings(testTexts) + + expect(result).toEqual({ + embeddings: [[0.1, 0.2, 0.3]], + usage: { promptTokens: 0, totalTokens: 0 }, + }) + }) + + /** + * Test batching logic when texts exceed token limits + */ + describe("batching logic", () => { + it("should warn and skip texts exceeding maximum token limit", async () => { + // Create a text that exceeds MAX_ITEM_TOKENS (4 characters ≈ 1 token) + const oversizedText = "a".repeat(MAX_ITEM_TOKENS * 4 + 100) + const normalText = "normal text" + const testTexts = [normalText, oversizedText, "another normal"] + + const mockResponses = [ + { + body: new TextEncoder().encode( + JSON.stringify({ + embedding: [0.1, 0.2, 0.3], + inputTextTokenCount: 3, + }), + ), + }, + { + body: new TextEncoder().encode( + JSON.stringify({ + embedding: [0.4, 0.5, 0.6], + inputTextTokenCount: 3, + }), + ), + }, + ] + + mockSend.mockResolvedValueOnce(mockResponses[0]).mockResolvedValueOnce(mockResponses[1]) + + const result = await embedder.createEmbeddings(testTexts) + + // Verify warning was logged + expect(console.warn).toHaveBeenCalledWith(expect.stringContaining("exceeds maximum token limit")) + + // Verify only normal texts were processed + expect(mockSend).toHaveBeenCalledTimes(2) + expect(result.embeddings).toHaveLength(2) + }) + + it("should handle all texts being skipped due to size", async () => { + const oversizedText = "a".repeat(MAX_ITEM_TOKENS * 4 + 100) + const testTexts = [oversizedText, oversizedText] + + const result = await embedder.createEmbeddings(testTexts) + + expect(console.warn).toHaveBeenCalledTimes(2) + expect(mockSend).not.toHaveBeenCalled() + expect(result).toEqual({ + embeddings: [], + usage: { promptTokens: 0, totalTokens: 0 }, + }) + }) + }) + + /** + * Test retry logic for rate limiting and other errors + */ + describe("retry logic", () => { + beforeEach(() => { + vitest.useFakeTimers() + }) + + afterEach(() => { + vitest.useRealTimers() + }) + + it("should retry on throttling errors with exponential backoff", async () => { + const testTexts = ["Hello world"] + const throttlingError = new Error("Rate limit exceeded") + throttlingError.name = "ThrottlingException" + + mockSend + .mockRejectedValueOnce(throttlingError) + .mockRejectedValueOnce(throttlingError) + .mockResolvedValueOnce({ + body: new TextEncoder().encode( + JSON.stringify({ + embedding: [0.1, 0.2, 0.3], + inputTextTokenCount: 2, + }), + ), + }) + + const resultPromise = embedder.createEmbeddings(testTexts) + + // Fast-forward through the delays + await vitest.advanceTimersByTimeAsync(INITIAL_RETRY_DELAY_MS) // First retry delay + await vitest.advanceTimersByTimeAsync(INITIAL_RETRY_DELAY_MS * 2) // Second retry delay + + const result = await resultPromise + + expect(mockSend).toHaveBeenCalledTimes(3) + expect(console.warn).toHaveBeenCalledWith(expect.stringContaining("Rate limit hit, retrying in")) + expect(result).toEqual({ + embeddings: [[0.1, 0.2, 0.3]], + usage: { promptTokens: 2, totalTokens: 2 }, + }) + }) + + it("should not retry on non-throttling errors", async () => { + const testTexts = ["Hello world"] + const authError = new Error("Unauthorized") + authError.name = "UnrecognizedClientException" + + mockSend.mockRejectedValue(authError) + + await expect(embedder.createEmbeddings(testTexts)).rejects.toThrow( + "Failed to create embeddings after 3 attempts: Unauthorized", + ) + + expect(mockSend).toHaveBeenCalledTimes(1) + expect(console.warn).not.toHaveBeenCalledWith(expect.stringContaining("Rate limit hit")) + }) + }) + + /** + * Test error handling scenarios + */ + describe("error handling", () => { + it("should handle API errors gracefully", async () => { + const testTexts = ["Hello world"] + const apiError = new Error("API connection failed") + + mockSend.mockRejectedValue(apiError) + + await expect(embedder.createEmbeddings(testTexts)).rejects.toThrow( + "Failed to create embeddings after 3 attempts: API connection failed", + ) + + expect(console.error).toHaveBeenCalledWith( + expect.stringContaining("Bedrock embedder error"), + expect.any(Error), + ) + }) + + it("should handle empty text arrays", async () => { + const testTexts: string[] = [] + + const result = await embedder.createEmbeddings(testTexts) + + expect(result).toEqual({ + embeddings: [], + usage: { promptTokens: 0, totalTokens: 0 }, + }) + expect(mockSend).not.toHaveBeenCalled() + }) + + it("should handle malformed API responses", async () => { + const testTexts = ["Hello world"] + const malformedResponse = { + body: new TextEncoder().encode("not json"), + } + + mockSend.mockResolvedValue(malformedResponse) + + await expect(embedder.createEmbeddings(testTexts)).rejects.toThrow() + }) + + it("should handle AWS-specific errors", async () => { + const testTexts = ["Hello world"] + + // Test UnrecognizedClientException + const authError = new Error("Invalid credentials") + authError.name = "UnrecognizedClientException" + mockSend.mockRejectedValueOnce(authError) + + await expect(embedder.createEmbeddings(testTexts)).rejects.toThrow( + "Failed to create embeddings after 3 attempts: Invalid credentials", + ) + + // Test AccessDeniedException + const accessError = new Error("Access denied") + accessError.name = "AccessDeniedException" + mockSend.mockRejectedValueOnce(accessError) + + await expect(embedder.createEmbeddings(testTexts)).rejects.toThrow( + "Failed to create embeddings after 3 attempts: Access denied", + ) + + // Test ResourceNotFoundException + const notFoundError = new Error("Model not found") + notFoundError.name = "ResourceNotFoundException" + mockSend.mockRejectedValueOnce(notFoundError) + + await expect(embedder.createEmbeddings(testTexts)).rejects.toThrow( + "Failed to create embeddings after 3 attempts: Model not found", + ) + }) + }) + }) + + describe("validateConfiguration", () => { + it("should validate successfully with valid configuration", async () => { + const mockResponse = { + body: new TextEncoder().encode( + JSON.stringify({ + embedding: [0.1, 0.2, 0.3], + inputTextTokenCount: 1, + }), + ), + } + mockSend.mockResolvedValue(mockResponse) + + const result = await embedder.validateConfiguration() + + expect(result.valid).toBe(true) + expect(result.error).toBeUndefined() + expect(mockSend).toHaveBeenCalled() + }) + + it("should fail validation with authentication error", async () => { + const authError = new Error("Invalid credentials") + authError.name = "UnrecognizedClientException" + mockSend.mockRejectedValue(authError) + + const result = await embedder.validateConfiguration() + + expect(result.valid).toBe(false) + expect(result.error).toBe("Invalid AWS credentials") + }) + + it("should fail validation with access denied error", async () => { + const accessError = new Error("Access denied") + accessError.name = "AccessDeniedException" + mockSend.mockRejectedValue(accessError) + + const result = await embedder.validateConfiguration() + + expect(result.valid).toBe(false) + expect(result.error).toBe("Access denied to Bedrock service") + }) + + it("should fail validation with model not found error", async () => { + const notFoundError = new Error("Model not found") + notFoundError.name = "ResourceNotFoundException" + mockSend.mockRejectedValue(notFoundError) + + const result = await embedder.validateConfiguration() + + expect(result.valid).toBe(false) + expect(result.error).toContain("not found") + }) + + it("should fail validation with invalid response", async () => { + const mockResponse = { + body: new TextEncoder().encode( + JSON.stringify({ + // Missing embedding field + inputTextTokenCount: 1, + }), + ), + } + mockSend.mockResolvedValue(mockResponse) + + const result = await embedder.validateConfiguration() + + expect(result.valid).toBe(false) + expect(result.error).toBe("Invalid response format from Bedrock") + }) + + it("should fail validation with connection error", async () => { + const connectionError = new Error("ECONNREFUSED") + mockSend.mockRejectedValue(connectionError) + + const result = await embedder.validateConfiguration() + + expect(result.valid).toBe(false) + expect(result.error).toBe("Connection failed") + }) + + it("should fail validation with generic error", async () => { + const genericError = new Error("Unknown error") + mockSend.mockRejectedValue(genericError) + + const result = await embedder.validateConfiguration() + + expect(result.valid).toBe(false) + expect(result.error).toBe("Configuration error") + }) + }) +}) diff --git a/src/services/code-index/embedders/bedrock.ts b/src/services/code-index/embedders/bedrock.ts new file mode 100644 index 00000000000..9bdaf602264 --- /dev/null +++ b/src/services/code-index/embedders/bedrock.ts @@ -0,0 +1,294 @@ +import { BedrockRuntimeClient, InvokeModelCommand, InvokeModelCommandInput } from "@aws-sdk/client-bedrock-runtime" +import { fromEnv, fromIni } from "@aws-sdk/credential-providers" +import { IEmbedder, EmbeddingResponse, EmbedderInfo } from "../interfaces" +import { + MAX_BATCH_TOKENS, + MAX_ITEM_TOKENS, + MAX_BATCH_RETRIES as MAX_RETRIES, + INITIAL_RETRY_DELAY_MS as INITIAL_DELAY_MS, +} from "../constants" +import { getDefaultModelId } from "../../../shared/embeddingModels" +import { t } from "../../../i18n" +import { withValidationErrorHandling, formatEmbeddingError, HttpError } from "../shared/validation-helpers" +import { TelemetryEventName } from "@roo-code/types" +import { TelemetryService } from "@roo-code/telemetry" + +/** + * AWS Bedrock implementation of the embedder interface with batching and rate limiting + */ +export class BedrockEmbedder implements IEmbedder { + private bedrockClient: BedrockRuntimeClient + private readonly defaultModelId: string + + /** + * Creates a new AWS Bedrock embedder + * @param region AWS region for Bedrock service + * @param modelId Optional model ID override + * @param profile Optional AWS profile name for credentials + */ + constructor( + private readonly region: string = "us-east-1", + modelId?: string, + private readonly profile?: string, + ) { + // Initialize the Bedrock client with appropriate credentials + const credentials = this.profile ? fromIni({ profile: this.profile }) : fromEnv() + + this.bedrockClient = new BedrockRuntimeClient({ + region: this.region, + credentials, + }) + + this.defaultModelId = modelId || getDefaultModelId("bedrock") + } + + /** + * Creates embeddings for the given texts with batching and rate limiting + * @param texts Array of text strings to embed + * @param model Optional model identifier + * @returns Promise resolving to embedding response + */ + async createEmbeddings(texts: string[], model?: string): Promise { + const modelToUse = model || this.defaultModelId + + const allEmbeddings: number[][] = [] + const usage = { promptTokens: 0, totalTokens: 0 } + const remainingTexts = [...texts] + + while (remainingTexts.length > 0) { + const currentBatch: string[] = [] + let currentBatchTokens = 0 + const processedIndices: number[] = [] + + for (let i = 0; i < remainingTexts.length; i++) { + const text = remainingTexts[i] + const itemTokens = Math.ceil(text.length / 4) + + if (itemTokens > MAX_ITEM_TOKENS) { + console.warn( + t("embeddings:textExceedsTokenLimit", { + index: i, + itemTokens, + maxTokens: MAX_ITEM_TOKENS, + }), + ) + processedIndices.push(i) + continue + } + + if (currentBatchTokens + itemTokens <= MAX_BATCH_TOKENS) { + currentBatch.push(text) + currentBatchTokens += itemTokens + processedIndices.push(i) + } else { + break + } + } + + // Remove processed items from remainingTexts (in reverse order to maintain correct indices) + for (let i = processedIndices.length - 1; i >= 0; i--) { + remainingTexts.splice(processedIndices[i], 1) + } + + if (currentBatch.length > 0) { + const batchResult = await this._embedBatchWithRetries(currentBatch, modelToUse) + allEmbeddings.push(...batchResult.embeddings) + usage.promptTokens += batchResult.usage.promptTokens + usage.totalTokens += batchResult.usage.totalTokens + } + } + + return { embeddings: allEmbeddings, usage } + } + + /** + * Helper method to handle batch embedding with retries and exponential backoff + * @param batchTexts Array of texts to embed in this batch + * @param model Model identifier to use + * @returns Promise resolving to embeddings and usage statistics + */ + private async _embedBatchWithRetries( + batchTexts: string[], + model: string, + ): Promise<{ embeddings: number[][]; usage: { promptTokens: number; totalTokens: number } }> { + for (let attempts = 0; attempts < MAX_RETRIES; attempts++) { + try { + const embeddings: number[][] = [] + let totalPromptTokens = 0 + let totalTokens = 0 + + // Process each text in the batch + // Note: Amazon Titan models typically don't support batch embedding in a single request + // So we process them individually + for (const text of batchTexts) { + const embedding = await this._invokeEmbeddingModel(text, model) + embeddings.push(embedding.embedding) + totalPromptTokens += embedding.inputTextTokenCount || 0 + totalTokens += embedding.inputTextTokenCount || 0 + } + + return { + embeddings, + usage: { + promptTokens: totalPromptTokens, + totalTokens, + }, + } + } catch (error: any) { + const hasMoreAttempts = attempts < MAX_RETRIES - 1 + + // Check if it's a rate limit error + if (error.name === "ThrottlingException" && hasMoreAttempts) { + const delayMs = INITIAL_DELAY_MS * Math.pow(2, attempts) + console.warn( + t("embeddings:rateLimitRetry", { + delayMs, + attempt: attempts + 1, + maxRetries: MAX_RETRIES, + }), + ) + await new Promise((resolve) => setTimeout(resolve, delayMs)) + continue + } + + // Capture telemetry before reformatting the error + TelemetryService.instance.captureEvent(TelemetryEventName.CODE_INDEX_ERROR, { + error: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + location: "BedrockEmbedder:_embedBatchWithRetries", + attempt: attempts + 1, + }) + + // Log the error for debugging + console.error(`Bedrock embedder error (attempt ${attempts + 1}/${MAX_RETRIES}):`, error) + + // Format and throw the error + throw formatEmbeddingError(error, MAX_RETRIES) + } + } + + throw new Error(t("embeddings:failedMaxAttempts", { attempts: MAX_RETRIES })) + } + + /** + * Invokes the embedding model for a single text + * @param text The text to embed + * @param model The model identifier to use + * @returns Promise resolving to embedding and token count + */ + private async _invokeEmbeddingModel( + text: string, + model: string, + ): Promise<{ embedding: number[]; inputTextTokenCount?: number }> { + let requestBody: any + let modelId = model + + // Prepare the request body based on the model + if (model.startsWith("amazon.titan-embed")) { + requestBody = { + inputText: text, + } + } else if (model.startsWith("cohere.embed")) { + requestBody = { + texts: [text], + input_type: "search_document", // or "search_query" depending on use case + } + } else { + // Default to Titan format + requestBody = { + inputText: text, + } + } + + const params: InvokeModelCommandInput = { + modelId, + body: JSON.stringify(requestBody), + contentType: "application/json", + accept: "application/json", + } + + const command = new InvokeModelCommand(params) + const response = await this.bedrockClient.send(command) + + // Parse the response + const responseBody = JSON.parse(new TextDecoder().decode(response.body)) + + // Extract embedding based on model type + if (model.startsWith("amazon.titan-embed")) { + return { + embedding: responseBody.embedding, + inputTextTokenCount: responseBody.inputTextTokenCount, + } + } else if (model.startsWith("cohere.embed")) { + return { + embedding: responseBody.embeddings[0], + // Cohere doesn't provide token count in response + } + } else { + // Default to Titan format + return { + embedding: responseBody.embedding, + inputTextTokenCount: responseBody.inputTextTokenCount, + } + } + } + + /** + * Validates the Bedrock embedder configuration by attempting a minimal embedding request + * @returns Promise resolving to validation result with success status and optional error message + */ + async validateConfiguration(): Promise<{ valid: boolean; error?: string }> { + return withValidationErrorHandling(async () => { + try { + // Test with a minimal embedding request + const result = await this._invokeEmbeddingModel("test", this.defaultModelId) + + // Check if we got a valid response + if (!result.embedding || result.embedding.length === 0) { + return { + valid: false, + error: t("embeddings:bedrock.invalidResponseFormat"), + } + } + + return { valid: true } + } catch (error: any) { + // Check for specific AWS errors + if (error.name === "UnrecognizedClientException") { + return { + valid: false, + error: t("embeddings:bedrock.invalidCredentials"), + } + } + + if (error.name === "AccessDeniedException") { + return { + valid: false, + error: t("embeddings:bedrock.accessDenied"), + } + } + + if (error.name === "ResourceNotFoundException") { + return { + valid: false, + error: t("embeddings:bedrock.modelNotFound", { model: this.defaultModelId }), + } + } + + // Capture telemetry for validation errors + TelemetryService.instance.captureEvent(TelemetryEventName.CODE_INDEX_ERROR, { + error: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + location: "BedrockEmbedder:validateConfiguration", + }) + throw error + } + }, "bedrock") + } + + get embedderInfo(): EmbedderInfo { + return { + name: "bedrock", + } + } +} diff --git a/src/services/code-index/interfaces/config.ts b/src/services/code-index/interfaces/config.ts index f168e268691..df29b9af241 100644 --- a/src/services/code-index/interfaces/config.ts +++ b/src/services/code-index/interfaces/config.ts @@ -15,6 +15,7 @@ export interface CodeIndexConfig { geminiOptions?: { apiKey: string } mistralOptions?: { apiKey: string } vercelAiGatewayOptions?: { apiKey: string } + bedrockOptions?: { region: string; profile?: string } qdrantUrl?: string qdrantApiKey?: string searchMinScore?: number @@ -37,6 +38,8 @@ export type PreviousConfigSnapshot = { geminiApiKey?: string mistralApiKey?: string vercelAiGatewayApiKey?: string + bedrockRegion?: string + bedrockProfile?: string qdrantUrl?: string qdrantApiKey?: string } diff --git a/src/services/code-index/interfaces/embedder.ts b/src/services/code-index/interfaces/embedder.ts index 1fcda3aca32..3f0a3d5d8a0 100644 --- a/src/services/code-index/interfaces/embedder.ts +++ b/src/services/code-index/interfaces/embedder.ts @@ -28,7 +28,14 @@ export interface EmbeddingResponse { } } -export type AvailableEmbedders = "openai" | "ollama" | "openai-compatible" | "gemini" | "mistral" | "vercel-ai-gateway" +export type AvailableEmbedders = + | "openai" + | "ollama" + | "openai-compatible" + | "gemini" + | "mistral" + | "vercel-ai-gateway" + | "bedrock" export interface EmbedderInfo { name: AvailableEmbedders diff --git a/src/services/code-index/interfaces/manager.ts b/src/services/code-index/interfaces/manager.ts index 527900f6d1c..9d2493d7888 100644 --- a/src/services/code-index/interfaces/manager.ts +++ b/src/services/code-index/interfaces/manager.ts @@ -70,7 +70,14 @@ export interface ICodeIndexManager { } export type IndexingState = "Standby" | "Indexing" | "Indexed" | "Error" -export type EmbedderProvider = "openai" | "ollama" | "openai-compatible" | "gemini" | "mistral" | "vercel-ai-gateway" +export type EmbedderProvider = + | "openai" + | "ollama" + | "openai-compatible" + | "gemini" + | "mistral" + | "vercel-ai-gateway" + | "bedrock" export interface IndexProgressUpdate { systemStatus: IndexingState diff --git a/src/services/code-index/service-factory.ts b/src/services/code-index/service-factory.ts index 6d69e1f0b6c..54e54520f24 100644 --- a/src/services/code-index/service-factory.ts +++ b/src/services/code-index/service-factory.ts @@ -5,6 +5,7 @@ import { OpenAICompatibleEmbedder } from "./embedders/openai-compatible" import { GeminiEmbedder } from "./embedders/gemini" import { MistralEmbedder } from "./embedders/mistral" import { VercelAiGatewayEmbedder } from "./embedders/vercel-ai-gateway" +import { BedrockEmbedder } from "./embedders/bedrock" import { EmbedderProvider, getDefaultModelId, getModelDimension } from "../../shared/embeddingModels" import { QdrantVectorStore } from "./vector-store/qdrant-client" import { codeParser, DirectoryScanner, FileWatcher } from "./processors" @@ -79,6 +80,11 @@ export class CodeIndexServiceFactory { throw new Error(t("embeddings:serviceFactory.vercelAiGatewayConfigMissing")) } return new VercelAiGatewayEmbedder(config.vercelAiGatewayOptions.apiKey, config.modelId) + } else if (provider === "bedrock") { + if (!config.bedrockOptions?.region) { + throw new Error(t("embeddings:serviceFactory.bedrockConfigMissing")) + } + return new BedrockEmbedder(config.bedrockOptions.region, config.modelId, config.bedrockOptions.profile) } throw new Error( diff --git a/src/shared/embeddingModels.ts b/src/shared/embeddingModels.ts index 80c51a6b455..063d70120f4 100644 --- a/src/shared/embeddingModels.ts +++ b/src/shared/embeddingModels.ts @@ -2,7 +2,14 @@ * Defines profiles for different embedding models, including their dimensions. */ -export type EmbedderProvider = "openai" | "ollama" | "openai-compatible" | "gemini" | "mistral" | "vercel-ai-gateway" // Add other providers as needed +export type EmbedderProvider = + | "openai" + | "ollama" + | "openai-compatible" + | "gemini" + | "mistral" + | "vercel-ai-gateway" + | "bedrock" // Add other providers as needed export interface EmbeddingModelProfile { dimension: number @@ -70,6 +77,15 @@ export const EMBEDDING_MODEL_PROFILES: EmbeddingModelProfiles = { "mistral/codestral-embed": { dimension: 1536, scoreThreshold: 0.4 }, "mistral/mistral-embed": { dimension: 1024, scoreThreshold: 0.4 }, }, + bedrock: { + // Amazon Titan Embed models + "amazon.titan-embed-text-v1": { dimension: 1536, scoreThreshold: 0.4 }, + "amazon.titan-embed-text-v2:0": { dimension: 1024, scoreThreshold: 0.4 }, + "amazon.titan-embed-image-v1": { dimension: 1024, scoreThreshold: 0.4 }, + // Cohere models available through Bedrock + "cohere.embed-english-v3": { dimension: 1024, scoreThreshold: 0.4 }, + "cohere.embed-multilingual-v3": { dimension: 1024, scoreThreshold: 0.4 }, + }, } /** @@ -163,6 +179,9 @@ export function getDefaultModelId(provider: EmbedderProvider): string { case "vercel-ai-gateway": return "openai/text-embedding-3-large" + case "bedrock": + return "amazon.titan-embed-text-v2:0" + default: // Fallback for unknown providers console.warn(`Unknown provider for default model ID: ${provider}. Falling back to OpenAI default.`) From 013496efb56fdbb58290fac67a9dbade306a4a08 Mon Sep 17 00:00:00 2001 From: Roo Code Date: Tue, 14 Oct 2025 16:40:25 +0000 Subject: [PATCH 02/17] fix: add missing bedrockOptions to loadConfiguration return type --- src/services/code-index/config-manager.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/services/code-index/config-manager.ts b/src/services/code-index/config-manager.ts index d61f7541bea..a1fb2f4a0e4 100644 --- a/src/services/code-index/config-manager.ts +++ b/src/services/code-index/config-manager.ts @@ -160,6 +160,7 @@ export class CodeIndexConfigManager { geminiOptions?: { apiKey: string } mistralOptions?: { apiKey: string } vercelAiGatewayOptions?: { apiKey: string } + bedrockOptions?: { region: string; profile?: string } qdrantUrl?: string qdrantApiKey?: string searchMinScore?: number From 2a5f75ab8b6a0fd2116869a82844ef2ce80be522 Mon Sep 17 00:00:00 2001 From: George Goranov Date: Fri, 21 Nov 2025 18:04:33 +0200 Subject: [PATCH 03/17] Fix various issues that the original PR missed. --- packages/types/src/codebase-index.ts | 5 +- src/core/webview/ClineProvider.ts | 4 + src/core/webview/webviewMessageHandler.ts | 17 ++ .../__tests__/config-manager.spec.ts | 14 +- src/services/code-index/config-manager.ts | 10 +- .../embedders/__tests__/bedrock.spec.ts | 20 +- src/services/code-index/embedders/bedrock.ts | 16 +- src/services/code-index/service-factory.ts | 5 +- src/shared/WebviewMessage.ts | 3 + .../src/components/chat/CodeIndexPopover.tsx | 211 +++++++++++++++++- webview-ui/src/i18n/locales/en/settings.json | 8 + 11 files changed, 273 insertions(+), 40 deletions(-) diff --git a/packages/types/src/codebase-index.ts b/packages/types/src/codebase-index.ts index be7778f5387..d56d4d0a2b5 100644 --- a/packages/types/src/codebase-index.ts +++ b/packages/types/src/codebase-index.ts @@ -22,7 +22,7 @@ export const codebaseIndexConfigSchema = z.object({ codebaseIndexEnabled: z.boolean().optional(), codebaseIndexQdrantUrl: z.string().optional(), codebaseIndexEmbedderProvider: z - .enum(["openai", "ollama", "openai-compatible", "gemini", "mistral", "vercel-ai-gateway"]) + .enum(["openai", "ollama", "openai-compatible", "gemini", "mistral", "vercel-ai-gateway", "bedrock"]) .optional(), codebaseIndexEmbedderBaseUrl: z.string().optional(), codebaseIndexEmbedderModelId: z.string().optional(), @@ -36,6 +36,9 @@ export const codebaseIndexConfigSchema = z.object({ // OpenAI Compatible specific fields codebaseIndexOpenAiCompatibleBaseUrl: z.string().optional(), codebaseIndexOpenAiCompatibleModelDimension: z.number().optional(), + // Bedrock specific fields + codebaseIndexBedrockRegion: z.string().optional(), + codebaseIndexBedrockProfile: z.string().optional(), }) export type CodebaseIndexConfig = z.infer diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 91b86879668..9c71938f2a4 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -1946,6 +1946,8 @@ export class ClineProvider codebaseIndexOpenAiCompatibleBaseUrl: codebaseIndexConfig?.codebaseIndexOpenAiCompatibleBaseUrl, codebaseIndexSearchMaxResults: codebaseIndexConfig?.codebaseIndexSearchMaxResults, codebaseIndexSearchMinScore: codebaseIndexConfig?.codebaseIndexSearchMinScore, + codebaseIndexBedrockRegion: codebaseIndexConfig?.codebaseIndexBedrockRegion, + codebaseIndexBedrockProfile: codebaseIndexConfig?.codebaseIndexBedrockProfile, }, // Only set mdmCompliant if there's an actual MDM policy // undefined means no MDM policy, true means compliant, false means non-compliant @@ -2164,6 +2166,8 @@ export class ClineProvider stateValues.codebaseIndexConfig?.codebaseIndexOpenAiCompatibleBaseUrl, codebaseIndexSearchMaxResults: stateValues.codebaseIndexConfig?.codebaseIndexSearchMaxResults, codebaseIndexSearchMinScore: stateValues.codebaseIndexConfig?.codebaseIndexSearchMinScore, + codebaseIndexBedrockRegion: stateValues.codebaseIndexConfig?.codebaseIndexBedrockRegion, + codebaseIndexBedrockProfile: stateValues.codebaseIndexConfig?.codebaseIndexBedrockProfile, }, profileThresholds: stateValues.profileThresholds ?? {}, includeDiagnosticMessages: stateValues.includeDiagnosticMessages ?? true, diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index af5f9925c35..635129b6c71 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -2439,6 +2439,11 @@ export const webviewMessageHandler = async ( const settings = message.codeIndexSettings + // DEBUG: Log received settings + provider.log( + `[DEBUG] Received settings to save: provider=${settings.codebaseIndexEmbedderProvider}, bedrockRegion=${settings.codebaseIndexBedrockRegion}, bedrockProfile=${settings.codebaseIndexBedrockProfile}`, + ) + try { // Check if embedder provider has changed const currentConfig = getGlobalState("codebaseIndexConfig") || {} @@ -2455,10 +2460,17 @@ export const webviewMessageHandler = async ( codebaseIndexEmbedderModelId: settings.codebaseIndexEmbedderModelId, codebaseIndexEmbedderModelDimension: settings.codebaseIndexEmbedderModelDimension, // Generic dimension codebaseIndexOpenAiCompatibleBaseUrl: settings.codebaseIndexOpenAiCompatibleBaseUrl, + codebaseIndexBedrockRegion: settings.codebaseIndexBedrockRegion, + codebaseIndexBedrockProfile: settings.codebaseIndexBedrockProfile, codebaseIndexSearchMaxResults: settings.codebaseIndexSearchMaxResults, codebaseIndexSearchMinScore: settings.codebaseIndexSearchMinScore, } + // DEBUG: Log what we're saving to global state + provider.log( + `[DEBUG] Saving to global state: bedrockRegion=${globalStateConfig.codebaseIndexBedrockRegion}, bedrockProfile=${globalStateConfig.codebaseIndexBedrockProfile}`, + ) + // Save global state first await updateGlobalState("codebaseIndexConfig", globalStateConfig) @@ -2494,6 +2506,11 @@ export const webviewMessageHandler = async ( ) } + // DEBUG: Log what we're sending back to webview + provider.log( + `[DEBUG] Sending success response to webview: bedrockRegion=${globalStateConfig.codebaseIndexBedrockRegion}, bedrockProfile=${globalStateConfig.codebaseIndexBedrockProfile}`, + ) + // Send success response first - settings are saved regardless of validation await provider.postMessageToWebview({ type: "codeIndexSettingsSaved", diff --git a/src/services/code-index/__tests__/config-manager.spec.ts b/src/services/code-index/__tests__/config-manager.spec.ts index 9fc096ba742..83c6a58911a 100644 --- a/src/services/code-index/__tests__/config-manager.spec.ts +++ b/src/services/code-index/__tests__/config-manager.spec.ts @@ -98,7 +98,7 @@ describe("CodeIndexConfigManager", () => { const result = await configManager.loadConfiguration() - expect(result.currentConfig).toEqual({ + expect(result.currentConfig).toMatchObject({ isConfigured: false, embedderProvider: "openai", modelId: undefined, @@ -129,7 +129,7 @@ describe("CodeIndexConfigManager", () => { const result = await configManager.loadConfiguration() - expect(result.currentConfig).toEqual({ + expect(result.currentConfig).toMatchObject({ isConfigured: true, embedderProvider: "openai", modelId: "text-embedding-3-large", @@ -162,7 +162,7 @@ describe("CodeIndexConfigManager", () => { const result = await configManager.loadConfiguration() - expect(result.currentConfig).toEqual({ + expect(result.currentConfig).toMatchObject({ isConfigured: true, embedderProvider: "openai-compatible", modelId: "text-embedding-3-large", @@ -199,7 +199,7 @@ describe("CodeIndexConfigManager", () => { const result = await configManager.loadConfiguration() - expect(result.currentConfig).toEqual({ + expect(result.currentConfig).toMatchObject({ isConfigured: true, embedderProvider: "openai-compatible", modelId: "custom-model", @@ -237,7 +237,7 @@ describe("CodeIndexConfigManager", () => { const result = await configManager.loadConfiguration() - expect(result.currentConfig).toEqual({ + expect(result.currentConfig).toMatchObject({ isConfigured: true, embedderProvider: "openai-compatible", modelId: "custom-model", @@ -275,7 +275,7 @@ describe("CodeIndexConfigManager", () => { const result = await configManager.loadConfiguration() - expect(result.currentConfig).toEqual({ + expect(result.currentConfig).toMatchObject({ isConfigured: true, embedderProvider: "openai-compatible", modelId: "custom-model", @@ -1286,7 +1286,7 @@ describe("CodeIndexConfigManager", () => { it("should return correct configuration via getConfig", () => { const config = configManager.getConfig() - expect(config).toEqual({ + expect(config).toMatchObject({ isConfigured: true, embedderProvider: "openai", modelId: "text-embedding-3-large", diff --git a/src/services/code-index/config-manager.ts b/src/services/code-index/config-manager.ts index a1fb2f4a0e4..a2eac70a69d 100644 --- a/src/services/code-index/config-manager.ts +++ b/src/services/code-index/config-manager.ts @@ -139,9 +139,9 @@ export class CodeIndexConfigManager { this.geminiOptions = geminiApiKey ? { apiKey: geminiApiKey } : undefined this.mistralOptions = mistralApiKey ? { apiKey: mistralApiKey } : undefined this.vercelAiGatewayOptions = vercelAiGatewayApiKey ? { apiKey: vercelAiGatewayApiKey } : undefined - this.bedrockOptions = bedrockRegion - ? { region: bedrockRegion, profile: bedrockProfile || undefined } - : undefined + // Set bedrockOptions only if both region and profile are provided + this.bedrockOptions = + bedrockRegion && bedrockProfile ? { region: bedrockRegion, profile: bedrockProfile } : undefined } /** @@ -252,9 +252,11 @@ export class CodeIndexConfigManager { const isConfigured = !!(apiKey && qdrantUrl) return isConfigured } else if (this.embedderProvider === "bedrock") { + // Both region and profile are required for Bedrock const region = this.bedrockOptions?.region + const profile = this.bedrockOptions?.profile const qdrantUrl = this.qdrantUrl - const isConfigured = !!(region && qdrantUrl) + const isConfigured = !!(region && profile && qdrantUrl) return isConfigured } return false // Should not happen if embedderProvider is always set correctly diff --git a/src/services/code-index/embedders/__tests__/bedrock.spec.ts b/src/services/code-index/embedders/__tests__/bedrock.spec.ts index b88ce786fdd..8af4e855ad6 100644 --- a/src/services/code-index/embedders/__tests__/bedrock.spec.ts +++ b/src/services/code-index/embedders/__tests__/bedrock.spec.ts @@ -76,7 +76,7 @@ describe("BedrockEmbedder", () => { send: mockSend, })) - embedder = new BedrockEmbedder("us-east-1", "amazon.titan-embed-text-v2:0") + embedder = new BedrockEmbedder("us-east-1", "test-profile", "amazon.titan-embed-text-v2:0") }) afterEach(() => { @@ -84,17 +84,21 @@ describe("BedrockEmbedder", () => { }) describe("constructor", () => { - it("should initialize with provided region and model", () => { + it("should initialize with provided region, profile and model", () => { expect(embedder.embedderInfo.name).toBe("bedrock") }) - it("should use default region if not provided", () => { - const defaultEmbedder = new BedrockEmbedder() - expect(defaultEmbedder).toBeDefined() + it("should require both region and profile", () => { + expect(() => new BedrockEmbedder("", "profile", "model")).toThrow( + "Both region and profile are required for AWS Bedrock embedder", + ) + expect(() => new BedrockEmbedder("us-east-1", "", "model")).toThrow( + "Both region and profile are required for AWS Bedrock embedder", + ) }) - it("should use profile if provided", () => { - const profileEmbedder = new BedrockEmbedder("us-west-2", undefined, "dev-profile") + it("should use profile for credentials", () => { + const profileEmbedder = new BedrockEmbedder("us-west-2", "dev-profile") expect(profileEmbedder).toBeDefined() }) }) @@ -169,7 +173,7 @@ describe("BedrockEmbedder", () => { }) it("should handle Cohere model format", async () => { - const cohereEmbedder = new BedrockEmbedder("us-east-1", "cohere.embed-english-v3") + const cohereEmbedder = new BedrockEmbedder("us-east-1", "test-profile", "cohere.embed-english-v3") const testTexts = ["Hello world"] const mockResponse = { body: new TextEncoder().encode( diff --git a/src/services/code-index/embedders/bedrock.ts b/src/services/code-index/embedders/bedrock.ts index 9bdaf602264..48e6976c574 100644 --- a/src/services/code-index/embedders/bedrock.ts +++ b/src/services/code-index/embedders/bedrock.ts @@ -22,17 +22,21 @@ export class BedrockEmbedder implements IEmbedder { /** * Creates a new AWS Bedrock embedder - * @param region AWS region for Bedrock service + * @param region AWS region for Bedrock service (required) + * @param profile AWS profile name for credentials (required) * @param modelId Optional model ID override - * @param profile Optional AWS profile name for credentials */ constructor( - private readonly region: string = "us-east-1", + private readonly region: string, + private readonly profile: string, modelId?: string, - private readonly profile?: string, ) { - // Initialize the Bedrock client with appropriate credentials - const credentials = this.profile ? fromIni({ profile: this.profile }) : fromEnv() + if (!region || !profile) { + throw new Error("Both region and profile are required for AWS Bedrock embedder") + } + + // Initialize the Bedrock client with credentials from the specified profile + const credentials = fromIni({ profile: this.profile }) this.bedrockClient = new BedrockRuntimeClient({ region: this.region, diff --git a/src/services/code-index/service-factory.ts b/src/services/code-index/service-factory.ts index 54e54520f24..76cf54161f9 100644 --- a/src/services/code-index/service-factory.ts +++ b/src/services/code-index/service-factory.ts @@ -81,10 +81,11 @@ export class CodeIndexServiceFactory { } return new VercelAiGatewayEmbedder(config.vercelAiGatewayOptions.apiKey, config.modelId) } else if (provider === "bedrock") { - if (!config.bedrockOptions?.region) { + // Both region and profile are required for Bedrock + if (!config.bedrockOptions?.region || !config.bedrockOptions?.profile) { throw new Error(t("embeddings:serviceFactory.bedrockConfigMissing")) } - return new BedrockEmbedder(config.bedrockOptions.region, config.modelId, config.bedrockOptions.profile) + return new BedrockEmbedder(config.bedrockOptions.region, config.bedrockOptions.profile, config.modelId) } throw new Error( diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index d43a2fce043..9c9913abb51 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -288,10 +288,13 @@ export interface WebviewMessage { | "gemini" | "mistral" | "vercel-ai-gateway" + | "bedrock" codebaseIndexEmbedderBaseUrl?: string codebaseIndexEmbedderModelId: string codebaseIndexEmbedderModelDimension?: number // Generic dimension for all providers codebaseIndexOpenAiCompatibleBaseUrl?: string + codebaseIndexBedrockRegion?: string + codebaseIndexBedrockProfile?: string codebaseIndexSearchMaxResults?: number codebaseIndexSearchMinScore?: number diff --git a/webview-ui/src/components/chat/CodeIndexPopover.tsx b/webview-ui/src/components/chat/CodeIndexPopover.tsx index 45bf4224a12..57e82e2fc9f 100644 --- a/webview-ui/src/components/chat/CodeIndexPopover.tsx +++ b/webview-ui/src/components/chat/CodeIndexPopover.tsx @@ -65,6 +65,10 @@ interface LocalCodeIndexSettings { codebaseIndexSearchMaxResults?: number codebaseIndexSearchMinScore?: number + // Bedrock-specific settings + codebaseIndexBedrockRegion?: string + codebaseIndexBedrockProfile?: string + // Secret settings (start empty, will be loaded separately) codeIndexOpenAiKey?: string codeIndexQdrantApiKey?: string @@ -149,6 +153,17 @@ const createValidationSchema = (provider: EmbedderProvider, t: any) => { .min(1, t("settings:codeIndex.validation.modelSelectionRequired")), }) + case "bedrock": + return baseSchema.extend({ + codebaseIndexBedrockRegion: z.string().min(1, t("settings:codeIndex.validation.bedrockRegionRequired")), + codebaseIndexBedrockProfile: z + .string() + .min(1, t("settings:codeIndex.validation.bedrockProfileRequired")), + codebaseIndexEmbedderModelId: z + .string() + .min(1, t("settings:codeIndex.validation.modelSelectionRequired")), + }) + default: return baseSchema } @@ -187,6 +202,8 @@ export const CodeIndexPopover: React.FC = ({ codebaseIndexEmbedderModelDimension: undefined, codebaseIndexSearchMaxResults: CODEBASE_INDEX_DEFAULTS.DEFAULT_SEARCH_RESULTS, codebaseIndexSearchMinScore: CODEBASE_INDEX_DEFAULTS.DEFAULT_SEARCH_MIN_SCORE, + codebaseIndexBedrockRegion: "", + codebaseIndexBedrockProfile: "", codeIndexOpenAiKey: "", codeIndexQdrantApiKey: "", codebaseIndexOpenAiCompatibleBaseUrl: "", @@ -210,6 +227,14 @@ export const CodeIndexPopover: React.FC = ({ // Initialize settings from global state useEffect(() => { if (codebaseIndexConfig) { + // DEBUG: Log what we're loading from config + console.log("[CodeIndexPopover] Loading settings from codebaseIndexConfig:", { + bedrockRegion: codebaseIndexConfig.codebaseIndexBedrockRegion, + bedrockProfile: codebaseIndexConfig.codebaseIndexBedrockProfile, + provider: codebaseIndexConfig.codebaseIndexEmbedderProvider, + fullConfig: codebaseIndexConfig, + }) + const settings = { codebaseIndexEnabled: codebaseIndexConfig.codebaseIndexEnabled ?? true, codebaseIndexQdrantUrl: codebaseIndexConfig.codebaseIndexQdrantUrl || "", @@ -222,6 +247,8 @@ export const CodeIndexPopover: React.FC = ({ codebaseIndexConfig.codebaseIndexSearchMaxResults ?? CODEBASE_INDEX_DEFAULTS.DEFAULT_SEARCH_RESULTS, codebaseIndexSearchMinScore: codebaseIndexConfig.codebaseIndexSearchMinScore ?? CODEBASE_INDEX_DEFAULTS.DEFAULT_SEARCH_MIN_SCORE, + codebaseIndexBedrockRegion: codebaseIndexConfig.codebaseIndexBedrockRegion || "", + codebaseIndexBedrockProfile: codebaseIndexConfig.codebaseIndexBedrockProfile || "", codeIndexOpenAiKey: "", codeIndexQdrantApiKey: "", codebaseIndexOpenAiCompatibleBaseUrl: codebaseIndexConfig.codebaseIndexOpenAiCompatibleBaseUrl || "", @@ -230,6 +257,12 @@ export const CodeIndexPopover: React.FC = ({ codebaseIndexMistralApiKey: "", codebaseIndexVercelAiGatewayApiKey: "", } + + console.log("[CodeIndexPopover] Setting initial/current settings to:", { + bedrockRegion: settings.codebaseIndexBedrockRegion, + bedrockProfile: settings.codebaseIndexBedrockProfile, + }) + setInitialSettings(settings) setCurrentSettings(settings) @@ -278,15 +311,64 @@ export const CodeIndexPopover: React.FC = ({ } else if (event.data.type === "codeIndexSettingsSaved") { if (event.data.success) { setSaveStatus("saved") - // Update initial settings to match current settings after successful save - // This ensures hasUnsavedChanges becomes false - const savedSettings = { ...currentSettingsRef.current } - setInitialSettings(savedSettings) - // Also update current settings to maintain consistency - setCurrentSettings(savedSettings) + + // DEBUG: Log what backend returned + console.log("[CodeIndexPopover] Received save success from backend:", { + bedrockRegion: event.data.settings?.codebaseIndexBedrockRegion, + bedrockProfile: event.data.settings?.codebaseIndexBedrockProfile, + allSettings: event.data.settings, + }) + + // Use the settings returned from the backend to update both initial and current settings + // This ensures we have the exact values that were saved + if (event.data.settings) { + const savedSettings = { + codebaseIndexEnabled: event.data.settings.codebaseIndexEnabled ?? true, + codebaseIndexQdrantUrl: event.data.settings.codebaseIndexQdrantUrl || "", + codebaseIndexEmbedderProvider: + event.data.settings.codebaseIndexEmbedderProvider || "openai", + codebaseIndexEmbedderBaseUrl: event.data.settings.codebaseIndexEmbedderBaseUrl || "", + codebaseIndexEmbedderModelId: event.data.settings.codebaseIndexEmbedderModelId || "", + codebaseIndexEmbedderModelDimension: + event.data.settings.codebaseIndexEmbedderModelDimension || undefined, + codebaseIndexSearchMaxResults: + event.data.settings.codebaseIndexSearchMaxResults ?? + CODEBASE_INDEX_DEFAULTS.DEFAULT_SEARCH_RESULTS, + codebaseIndexSearchMinScore: + event.data.settings.codebaseIndexSearchMinScore ?? + CODEBASE_INDEX_DEFAULTS.DEFAULT_SEARCH_MIN_SCORE, + codebaseIndexBedrockRegion: event.data.settings.codebaseIndexBedrockRegion || "", + codebaseIndexBedrockProfile: event.data.settings.codebaseIndexBedrockProfile || "", + codeIndexOpenAiKey: currentSettingsRef.current.codeIndexOpenAiKey, + codeIndexQdrantApiKey: currentSettingsRef.current.codeIndexQdrantApiKey, + codebaseIndexOpenAiCompatibleBaseUrl: + event.data.settings.codebaseIndexOpenAiCompatibleBaseUrl || "", + codebaseIndexOpenAiCompatibleApiKey: + currentSettingsRef.current.codebaseIndexOpenAiCompatibleApiKey, + codebaseIndexGeminiApiKey: currentSettingsRef.current.codebaseIndexGeminiApiKey, + codebaseIndexMistralApiKey: currentSettingsRef.current.codebaseIndexMistralApiKey, + codebaseIndexVercelAiGatewayApiKey: + currentSettingsRef.current.codebaseIndexVercelAiGatewayApiKey, + } + + console.log("[CodeIndexPopover] Updated settings after save:", { + bedrockRegion: savedSettings.codebaseIndexBedrockRegion, + bedrockProfile: savedSettings.codebaseIndexBedrockProfile, + }) + + console.log("[CodeIndexPopover] About to update state with saved settings:", { + bedrockRegion: savedSettings.codebaseIndexBedrockRegion, + bedrockProfile: savedSettings.codebaseIndexBedrockProfile, + }) + + setInitialSettings(savedSettings) + setCurrentSettings(savedSettings) + + console.log("[CodeIndexPopover] State updated with saved settings") + } + // Request secret status to ensure we have the latest state // This is important to maintain placeholder display after save - vscode.postMessage({ type: "requestCodeIndexSecretStatus" }) setSaveStatus("idle") @@ -440,6 +522,7 @@ export const CodeIndexPopover: React.FC = ({ errors[err.path[0] as string] = err.message } }) + console.log("[CodeIndexPopover] Validation errors:", errors) setFormErrors(errors) } return false @@ -483,6 +566,8 @@ export const CodeIndexPopover: React.FC = ({ useEscapeKey(open, handlePopoverClose) const handleSaveSettings = () => { + console.log("[CodeIndexPopover] handleSaveSettings called") + // Validate settings before saving if (!validateSettings()) { return @@ -511,6 +596,14 @@ export const CodeIndexPopover: React.FC = ({ // Always include codebaseIndexEnabled to ensure it's persisted settingsToSave.codebaseIndexEnabled = currentSettings.codebaseIndexEnabled + // DEBUG: Log Bedrock settings being saved + console.log("[CodeIndexPopover] Saving settings:", { + provider: settingsToSave.codebaseIndexEmbedderProvider, + bedrockRegion: settingsToSave.codebaseIndexBedrockRegion, + bedrockProfile: settingsToSave.codebaseIndexBedrockProfile, + allSettings: settingsToSave, + }) + // Save settings to backend vscode.postMessage({ type: "saveCodeIndexSettingsAtomic", @@ -531,7 +624,8 @@ export const CodeIndexPopover: React.FC = ({ const getAvailableModels = () => { if (!codebaseIndexModels) return [] - const models = codebaseIndexModels[currentSettings.codebaseIndexEmbedderProvider] + const models = + codebaseIndexModels[currentSettings.codebaseIndexEmbedderProvider as keyof typeof codebaseIndexModels] return models ? Object.keys(models) : [] } @@ -669,6 +763,9 @@ export const CodeIndexPopover: React.FC = ({ {t("settings:codeIndex.vercelAiGatewayProvider")} + + {t("settings:codeIndex.bedrockProvider")} + @@ -716,7 +813,7 @@ export const CodeIndexPopover: React.FC = ({ {getAvailableModels().map((modelId) => { const model = codebaseIndexModels?.[ - currentSettings.codebaseIndexEmbedderProvider + currentSettings.codebaseIndexEmbedderProvider as keyof typeof codebaseIndexModels ]?.[modelId] return ( @@ -973,7 +1070,7 @@ export const CodeIndexPopover: React.FC = ({ {getAvailableModels().map((modelId) => { const model = codebaseIndexModels?.[ - currentSettings.codebaseIndexEmbedderProvider + currentSettings.codebaseIndexEmbedderProvider as keyof typeof codebaseIndexModels ]?.[modelId] return ( @@ -1038,7 +1135,7 @@ export const CodeIndexPopover: React.FC = ({ {getAvailableModels().map((modelId) => { const model = codebaseIndexModels?.[ - currentSettings.codebaseIndexEmbedderProvider + currentSettings.codebaseIndexEmbedderProvider as keyof typeof codebaseIndexModels ]?.[modelId] return ( @@ -1108,7 +1205,97 @@ export const CodeIndexPopover: React.FC = ({ {getAvailableModels().map((modelId) => { const model = codebaseIndexModels?.[ - currentSettings.codebaseIndexEmbedderProvider + currentSettings.codebaseIndexEmbedderProvider as keyof typeof codebaseIndexModels + ]?.[modelId] + return ( + + {modelId}{" "} + {model + ? t("settings:codeIndex.modelDimensions", { + dimension: model.dimension, + }) + : ""} + + ) + })} + + {formErrors.codebaseIndexEmbedderModelId && ( +

+ {formErrors.codebaseIndexEmbedderModelId} +

+ )} + + + )} + + {currentSettings.codebaseIndexEmbedderProvider === "bedrock" && ( + <> +
+ + + updateSetting("codebaseIndexBedrockRegion", e.target.value) + } + placeholder={t("settings:codeIndex.bedrockRegionPlaceholder")} + className={cn("w-full", { + "border-red-500": formErrors.codebaseIndexBedrockRegion, + })} + /> + {formErrors.codebaseIndexBedrockRegion && ( +

+ {formErrors.codebaseIndexBedrockRegion} +

+ )} +
+ +
+ + + updateSetting("codebaseIndexBedrockProfile", e.target.value) + } + placeholder={t("settings:codeIndex.bedrockProfilePlaceholder")} + className={cn("w-full", { + "border-red-500": formErrors.codebaseIndexBedrockProfile, + })} + /> + {formErrors.codebaseIndexBedrockProfile && ( +

+ {formErrors.codebaseIndexBedrockProfile} +

+ )} + {!formErrors.codebaseIndexBedrockProfile && ( +

+ {t("settings:codeIndex.bedrockProfileDescription")} +

+ )} +
+ +
+ + + updateSetting("codebaseIndexEmbedderModelId", e.target.value) + } + className={cn("w-full", { + "border-red-500": formErrors.codebaseIndexEmbedderModelId, + })}> + + {t("settings:codeIndex.selectModel")} + + {getAvailableModels().map((modelId) => { + const model = + codebaseIndexModels?.[ + currentSettings.codebaseIndexEmbedderProvider as keyof typeof codebaseIndexModels ]?.[modelId] return ( diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index dfccc49cc4c..f1b06b329ca 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -69,6 +69,12 @@ "vercelAiGatewayProvider": "Vercel AI Gateway", "vercelAiGatewayApiKeyLabel": "API Key", "vercelAiGatewayApiKeyPlaceholder": "Enter your Vercel AI Gateway API key", + "bedrockProvider": "AWS Bedrock", + "bedrockRegionLabel": "AWS Region", + "bedrockRegionPlaceholder": "us-east-1", + "bedrockProfileLabel": "AWS Profile", + "bedrockProfilePlaceholder": "default", + "bedrockProfileDescription": "AWS profile name from ~/.aws/credentials (required).", "openaiCompatibleProvider": "OpenAI Compatible", "openAiKeyLabel": "OpenAI API Key", "openAiKeyPlaceholder": "Enter your OpenAI API key", @@ -135,6 +141,8 @@ "geminiApiKeyRequired": "Gemini API key is required", "mistralApiKeyRequired": "Mistral API key is required", "vercelAiGatewayApiKeyRequired": "Vercel AI Gateway API key is required", + "bedrockRegionRequired": "AWS region is required", + "bedrockProfileRequired": "AWS profile is required", "ollamaBaseUrlRequired": "Ollama base URL is required", "baseUrlRequired": "Base URL is required", "modelDimensionMinValue": "Model dimension must be greater than 0" From a7dab7761f91f74c3fd8bcaa485691cb83c4c9dc Mon Sep 17 00:00:00 2001 From: George Goranov Date: Tue, 25 Nov 2025 16:08:09 +0200 Subject: [PATCH 04/17] Remove debug logs --- src/core/webview/webviewMessageHandler.ts | 15 ------- .../src/components/chat/CodeIndexPopover.tsx | 45 ------------------- 2 files changed, 60 deletions(-) diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index 2b373f38007..1a0afa1fa3f 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -2362,11 +2362,6 @@ export const webviewMessageHandler = async ( const settings = message.codeIndexSettings - // DEBUG: Log received settings - provider.log( - `[DEBUG] Received settings to save: provider=${settings.codebaseIndexEmbedderProvider}, bedrockRegion=${settings.codebaseIndexBedrockRegion}, bedrockProfile=${settings.codebaseIndexBedrockProfile}`, - ) - try { // Check if embedder provider has changed const currentConfig = getGlobalState("codebaseIndexConfig") || {} @@ -2389,11 +2384,6 @@ export const webviewMessageHandler = async ( codebaseIndexSearchMinScore: settings.codebaseIndexSearchMinScore, } - // DEBUG: Log what we're saving to global state - provider.log( - `[DEBUG] Saving to global state: bedrockRegion=${globalStateConfig.codebaseIndexBedrockRegion}, bedrockProfile=${globalStateConfig.codebaseIndexBedrockProfile}`, - ) - // Save global state first await updateGlobalState("codebaseIndexConfig", globalStateConfig) @@ -2435,11 +2425,6 @@ export const webviewMessageHandler = async ( ) } - // DEBUG: Log what we're sending back to webview - provider.log( - `[DEBUG] Sending success response to webview: bedrockRegion=${globalStateConfig.codebaseIndexBedrockRegion}, bedrockProfile=${globalStateConfig.codebaseIndexBedrockProfile}`, - ) - // Send success response first - settings are saved regardless of validation await provider.postMessageToWebview({ type: "codeIndexSettingsSaved", diff --git a/webview-ui/src/components/chat/CodeIndexPopover.tsx b/webview-ui/src/components/chat/CodeIndexPopover.tsx index f02cd11934e..27ae78a3070 100644 --- a/webview-ui/src/components/chat/CodeIndexPopover.tsx +++ b/webview-ui/src/components/chat/CodeIndexPopover.tsx @@ -248,14 +248,6 @@ export const CodeIndexPopover: React.FC = ({ // Initialize settings from global state useEffect(() => { if (codebaseIndexConfig) { - // DEBUG: Log what we're loading from config - console.log("[CodeIndexPopover] Loading settings from codebaseIndexConfig:", { - bedrockRegion: codebaseIndexConfig.codebaseIndexBedrockRegion, - bedrockProfile: codebaseIndexConfig.codebaseIndexBedrockProfile, - provider: codebaseIndexConfig.codebaseIndexEmbedderProvider, - fullConfig: codebaseIndexConfig, - }) - const settings = { codebaseIndexEnabled: codebaseIndexConfig.codebaseIndexEnabled ?? true, codebaseIndexQdrantUrl: codebaseIndexConfig.codebaseIndexQdrantUrl || "", @@ -279,12 +271,6 @@ export const CodeIndexPopover: React.FC = ({ codebaseIndexVercelAiGatewayApiKey: "", codebaseIndexOpenRouterApiKey: "", } - - console.log("[CodeIndexPopover] Setting initial/current settings to:", { - bedrockRegion: settings.codebaseIndexBedrockRegion, - bedrockProfile: settings.codebaseIndexBedrockProfile, - }) - setInitialSettings(settings) setCurrentSettings(settings) @@ -333,14 +319,6 @@ export const CodeIndexPopover: React.FC = ({ } else if (event.data.type === "codeIndexSettingsSaved") { if (event.data.success) { setSaveStatus("saved") - - // DEBUG: Log what backend returned - console.log("[CodeIndexPopover] Received save success from backend:", { - bedrockRegion: event.data.settings?.codebaseIndexBedrockRegion, - bedrockProfile: event.data.settings?.codebaseIndexBedrockProfile, - allSettings: event.data.settings, - }) - // Use the settings returned from the backend to update both initial and current settings // This ensures we have the exact values that were saved if (event.data.settings) { @@ -373,20 +351,8 @@ export const CodeIndexPopover: React.FC = ({ currentSettingsRef.current.codebaseIndexVercelAiGatewayApiKey, } - console.log("[CodeIndexPopover] Updated settings after save:", { - bedrockRegion: savedSettings.codebaseIndexBedrockRegion, - bedrockProfile: savedSettings.codebaseIndexBedrockProfile, - }) - - console.log("[CodeIndexPopover] About to update state with saved settings:", { - bedrockRegion: savedSettings.codebaseIndexBedrockRegion, - bedrockProfile: savedSettings.codebaseIndexBedrockProfile, - }) - setInitialSettings(savedSettings) setCurrentSettings(savedSettings) - - console.log("[CodeIndexPopover] State updated with saved settings") } // Request secret status to ensure we have the latest state @@ -553,7 +519,6 @@ export const CodeIndexPopover: React.FC = ({ errors[err.path[0] as string] = err.message } }) - console.log("[CodeIndexPopover] Validation errors:", errors) setFormErrors(errors) } return false @@ -597,8 +562,6 @@ export const CodeIndexPopover: React.FC = ({ useEscapeKey(open, handlePopoverClose) const handleSaveSettings = () => { - console.log("[CodeIndexPopover] handleSaveSettings called") - // Validate settings before saving if (!validateSettings()) { return @@ -627,14 +590,6 @@ export const CodeIndexPopover: React.FC = ({ // Always include codebaseIndexEnabled to ensure it's persisted settingsToSave.codebaseIndexEnabled = currentSettings.codebaseIndexEnabled - // DEBUG: Log Bedrock settings being saved - console.log("[CodeIndexPopover] Saving settings:", { - provider: settingsToSave.codebaseIndexEmbedderProvider, - bedrockRegion: settingsToSave.codebaseIndexBedrockRegion, - bedrockProfile: settingsToSave.codebaseIndexBedrockProfile, - allSettings: settingsToSave, - }) - // Save settings to backend vscode.postMessage({ type: "saveCodeIndexSettingsAtomic", From de29974a67aaed0c97bd284f6c3c532144c3bc74 Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Wed, 26 Nov 2025 01:01:06 -0500 Subject: [PATCH 05/17] Rename AWS Bedrock -> Amazon Bedrock --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- .roo/rules-translate/instructions-zh-cn.md | 2 +- CHANGELOG.md | 20 +++++++++---------- src/i18n/locales/en/embeddings.json | 8 ++++---- .../embedders/__tests__/bedrock.spec.ts | 4 ++-- src/services/code-index/embedders/bedrock.ts | 6 +++--- webview-ui/src/i18n/locales/en/settings.json | 2 +- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 9e22303a350..34ac70a6cfd 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -76,7 +76,7 @@ body: label: API Provider (optional) options: - Anthropic - - AWS Bedrock + - Amazon Bedrock - Chutes AI - DeepSeek - Featherless AI diff --git a/.roo/rules-translate/instructions-zh-cn.md b/.roo/rules-translate/instructions-zh-cn.md index 241ae338dc1..6141038728c 100644 --- a/.roo/rules-translate/instructions-zh-cn.md +++ b/.roo/rules-translate/instructions-zh-cn.md @@ -115,7 +115,7 @@ - 保留英文品牌名 - 技术术语保持一致性 - - 保留英文专有名词:如"AWS Bedrock ARN" + - 保留英文专有名词:如"Amazon Bedrock ARN" 4. **用户操作** - 操作动词统一: diff --git a/CHANGELOG.md b/CHANGELOG.md index 86e435b6ee2..198561e4ca0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -374,7 +374,7 @@ ## [3.28.11] - 2025-09-29 -- Fix: Correct AWS Bedrock Claude Sonnet 4.5 model identifier (#8371 by @sunhyung, PR by @app/roomote) +- Fix: Correct Amazon Bedrock Claude Sonnet 4.5 model identifier (#8371 by @sunhyung, PR by @app/roomote) - Fix: Correct Claude Sonnet 4.5 model ID format (thanks @daniel-lxs!) ## [3.28.10] - 2025-09-29 @@ -706,7 +706,7 @@ ## [3.25.14] - 2025-08-13 - Fix: Only include verbosity parameter for models that support it (#7054 by @eastonmeth, PR by @app/roomote) -- Fix: AWS Bedrock 1M context - Move anthropic_beta to additionalModelRequestFields (thanks @daniel-lxs!) +- Fix: Amazon Bedrock 1M context - Move anthropic_beta to additionalModelRequestFields (thanks @daniel-lxs!) - Fix: Make cancelling requests more responsive by reverting recent changes ## [3.25.13] - 2025-08-12 @@ -1071,7 +1071,7 @@ - Add user-configurable search score threshold slider for semantic search (thanks @hannesrudolph!) - Add default headers and testing for litellm fetcher (thanks @andrewshu2000!) - Fix consistent cancellation error messages for thinking vs streaming phases -- Fix AWS Bedrock cross-region inference profile mapping (thanks @KevinZhao!) +- Fix Amazon Bedrock cross-region inference profile mapping (thanks @KevinZhao!) - Fix URL loading timeout issues in @ mentions (thanks @MuriloFP!) - Fix API retry exponential backoff capped at 10 minutes (thanks @MuriloFP!) - Fix Qdrant URL field auto-filling with default value (thanks @SannidhyaSah!) @@ -1085,7 +1085,7 @@ - Suppress Mermaid error rendering - Improve Mermaid buttons with light background in light mode (thanks @chrarnoldus!) - Add .vscode/ to write-protected files/directories -- Update AWS Bedrock cross-region inference profile mapping (thanks @KevinZhao!) +- Update Amazon Bedrock cross-region inference profile mapping (thanks @KevinZhao!) ## [3.22.5] - 2025-06-28 @@ -1709,7 +1709,7 @@ - Improved display of diff errors + easy copying for investigation - Fixes to .vscodeignore (thanks @franekp!) - Fix a zh-CN translation for model capabilities (thanks @zhangtony239!) -- Rename AWS Bedrock to Amazon Bedrock (thanks @ronyblum!) +- Rename Amazon Bedrock to Amazon Bedrock (thanks @ronyblum!) - Update extension title and description (thanks @StevenTCramer!) ## [3.11.12] - 2025-04-09 @@ -1958,12 +1958,12 @@ - PowerShell-specific command handling (thanks @KJ7LNW!) - OpenAI-compatible DeepSeek/QwQ reasoning support (thanks @lightrabbit!) - Anthropic-style prompt caching in the OpenAI-compatible provider (thanks @dleen!) -- Add Deepseek R1 for AWS Bedrock (thanks @ATempsch!) +- Add Deepseek R1 for Amazon Bedrock (thanks @ATempsch!) - Fix MarkdownBlock text color for Dark High Contrast theme (thanks @cannuri!) - Add gemini-2.0-pro-exp-02-05 model to vertex (thanks @shohei-ihaya!) - Bring back progress status for multi-diff edits (thanks @qdaxb!) - Refactor alert dialog styles to use the correct vscode theme (thanks @cannuri!) -- Custom ARNs in AWS Bedrock (thanks @Smartsheet-JB-Brown!) +- Custom ARNs in Amazon Bedrock (thanks @Smartsheet-JB-Brown!) - Update MCP servers directory path for platform compatibility (thanks @hannesrudolph!) - Fix browser system prompt inclusion rules (thanks @cannuri!) - Publish git tags to github from CI (thanks @pdecat!) @@ -2101,7 +2101,7 @@ ## [3.7.1] - 2025-02-24 -- Add AWS Bedrock support for Sonnet 3.7 and update some defaults to Sonnet 3.7 instead of 3.5 +- Add Amazon Bedrock support for Sonnet 3.7 and update some defaults to Sonnet 3.7 instead of 3.5 ## [3.7.0] - 2025-02-24 @@ -2118,7 +2118,7 @@ ## [3.3.24] - 2025-02-20 -- Fixed a bug with region selection preventing AWS Bedrock profiles from being saved (thanks @oprstchn!) +- Fixed a bug with region selection preventing Amazon Bedrock profiles from being saved (thanks @oprstchn!) - Updated the price of gpt-4o (thanks @marvijo-code!) ## [3.3.23] - 2025-02-20 @@ -2302,7 +2302,7 @@ - Reverts provider key entry back to checking onInput instead of onChange to hopefully address issues entering API keys (thanks @samhvw8!) - Added explicit checkbox to use Azure for OpenAI compatible providers (thanks @samhvw8!) - Fixed Glama usage reporting (thanks @punkpeye!) -- Added Llama 3.3 70B Instruct model to the AWS Bedrock provider options (thanks @Premshay!) +- Added Llama 3.3 70B Instruct model to the Amazon Bedrock provider options (thanks @Premshay!) ## [3.2.7] diff --git a/src/i18n/locales/en/embeddings.json b/src/i18n/locales/en/embeddings.json index 38bd9e7fdf2..5819e45c1a8 100644 --- a/src/i18n/locales/en/embeddings.json +++ b/src/i18n/locales/en/embeddings.json @@ -18,10 +18,10 @@ "hostNotFound": "Ollama host not found: {{baseUrl}}" }, "bedrock": { - "invalidResponseFormat": "Invalid response format from AWS Bedrock", + "invalidResponseFormat": "Invalid response format from Amazon Bedrock", "invalidCredentials": "Invalid AWS credentials. Please check your AWS configuration.", - "accessDenied": "Access denied to AWS Bedrock service. Please check your IAM permissions.", - "modelNotFound": "Model {{model}} not found in AWS Bedrock" + "accessDenied": "Access denied to Amazon Bedrock service. Please check your IAM permissions.", + "modelNotFound": "Model {{model}} not found in Amazon Bedrock" }, "scanner": { "unknownErrorProcessingFile": "Unknown error processing file {{filePath}}", @@ -55,7 +55,7 @@ "mistralConfigMissing": "Mistral configuration missing for embedder creation", "openRouterConfigMissing": "OpenRouter configuration missing for embedder creation", "vercelAiGatewayConfigMissing": "Vercel AI Gateway configuration missing for embedder creation", - "bedrockConfigMissing": "AWS Bedrock configuration missing for embedder creation", + "bedrockConfigMissing": "Amazon Bedrock configuration missing for embedder creation", "invalidEmbedderType": "Invalid embedder type configured: {{embedderProvider}}", "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.", "vectorDimensionNotDetermined": "Could not determine vector dimension for model '{{modelId}}' with provider '{{provider}}'. Check model profiles or configuration.", diff --git a/src/services/code-index/embedders/__tests__/bedrock.spec.ts b/src/services/code-index/embedders/__tests__/bedrock.spec.ts index 8af4e855ad6..80542d8ef9a 100644 --- a/src/services/code-index/embedders/__tests__/bedrock.spec.ts +++ b/src/services/code-index/embedders/__tests__/bedrock.spec.ts @@ -90,10 +90,10 @@ describe("BedrockEmbedder", () => { it("should require both region and profile", () => { expect(() => new BedrockEmbedder("", "profile", "model")).toThrow( - "Both region and profile are required for AWS Bedrock embedder", + "Both region and profile are required for Amazon Bedrock embedder", ) expect(() => new BedrockEmbedder("us-east-1", "", "model")).toThrow( - "Both region and profile are required for AWS Bedrock embedder", + "Both region and profile are required for Amazon Bedrock embedder", ) }) diff --git a/src/services/code-index/embedders/bedrock.ts b/src/services/code-index/embedders/bedrock.ts index 48e6976c574..cb2e73fc50c 100644 --- a/src/services/code-index/embedders/bedrock.ts +++ b/src/services/code-index/embedders/bedrock.ts @@ -14,14 +14,14 @@ import { TelemetryEventName } from "@roo-code/types" import { TelemetryService } from "@roo-code/telemetry" /** - * AWS Bedrock implementation of the embedder interface with batching and rate limiting + * Amazon Bedrock implementation of the embedder interface with batching and rate limiting */ export class BedrockEmbedder implements IEmbedder { private bedrockClient: BedrockRuntimeClient private readonly defaultModelId: string /** - * Creates a new AWS Bedrock embedder + * Creates a new Amazon Bedrock embedder * @param region AWS region for Bedrock service (required) * @param profile AWS profile name for credentials (required) * @param modelId Optional model ID override @@ -32,7 +32,7 @@ export class BedrockEmbedder implements IEmbedder { modelId?: string, ) { if (!region || !profile) { - throw new Error("Both region and profile are required for AWS Bedrock embedder") + throw new Error("Both region and profile are required for Amazon Bedrock embedder") } // Initialize the Bedrock client with credentials from the specified profile diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index 0425f748a2b..4036efdaa82 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -89,7 +89,7 @@ "vercelAiGatewayProvider": "Vercel AI Gateway", "vercelAiGatewayApiKeyLabel": "API Key", "vercelAiGatewayApiKeyPlaceholder": "Enter your Vercel AI Gateway API key", - "bedrockProvider": "AWS Bedrock", + "bedrockProvider": "Amazon Bedrock", "bedrockRegionLabel": "AWS Region", "bedrockRegionPlaceholder": "us-east-1", "bedrockProfileLabel": "AWS Profile", From 75487e2386b57f40ebfe703d45f48a634e7fb29a Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Wed, 26 Nov 2025 01:04:15 -0500 Subject: [PATCH 06/17] Remove some 'as any's --- src/services/code-index/config-manager.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/services/code-index/config-manager.ts b/src/services/code-index/config-manager.ts index f1ce6524378..79f409eb505 100644 --- a/src/services/code-index/config-manager.ts +++ b/src/services/code-index/config-manager.ts @@ -73,13 +73,13 @@ export class CodeIndexConfigManager { const openAiKey = this.contextProxy?.getSecret("codeIndexOpenAiKey") ?? "" const qdrantApiKey = this.contextProxy?.getSecret("codeIndexQdrantApiKey") ?? "" // Fix: Read OpenAI Compatible settings from the correct location within codebaseIndexConfig - const openAiCompatibleBaseUrl = (codebaseIndexConfig as any).codebaseIndexOpenAiCompatibleBaseUrl ?? "" + const openAiCompatibleBaseUrl = codebaseIndexConfig.codebaseIndexOpenAiCompatibleBaseUrl ?? "" const openAiCompatibleApiKey = this.contextProxy?.getSecret("codebaseIndexOpenAiCompatibleApiKey") ?? "" const geminiApiKey = this.contextProxy?.getSecret("codebaseIndexGeminiApiKey") ?? "" const mistralApiKey = this.contextProxy?.getSecret("codebaseIndexMistralApiKey") ?? "" const vercelAiGatewayApiKey = this.contextProxy?.getSecret("codebaseIndexVercelAiGatewayApiKey") ?? "" - const bedrockRegion = (codebaseIndexConfig as any).codebaseIndexBedrockRegion ?? "us-east-1" - const bedrockProfile = (codebaseIndexConfig as any).codebaseIndexBedrockProfile ?? "" + const bedrockRegion = codebaseIndexConfig.codebaseIndexBedrockRegion ?? "us-east-1" + const bedrockProfile = codebaseIndexConfig.codebaseIndexBedrockProfile ?? "" const openRouterApiKey = this.contextProxy?.getSecret("codebaseIndexOpenRouterApiKey") ?? "" // Update instance variables with configuration @@ -90,7 +90,7 @@ export class CodeIndexConfigManager { this.searchMaxResults = codebaseIndexSearchMaxResults // Validate and set model dimension - const rawDimension = (codebaseIndexConfig as any).codebaseIndexEmbedderModelDimension + const rawDimension = codebaseIndexConfig.codebaseIndexEmbedderModelDimension if (rawDimension !== undefined && rawDimension !== null) { const dimension = Number(rawDimension) if (!isNaN(dimension) && dimension > 0) { From 09d361f3b897beb6fbc27b37d3a1ce8c67311f8b Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Wed, 26 Nov 2025 01:09:10 -0500 Subject: [PATCH 07/17] Revert README changes --- README.md | 2 +- locales/ca/README.md | 2 +- locales/de/README.md | 2 +- locales/es/README.md | 2 +- locales/fr/README.md | 2 +- locales/hi/README.md | 2 +- locales/id/README.md | 2 +- locales/it/README.md | 2 +- locales/ja/README.md | 2 +- locales/ko/README.md | 2 +- locales/nl/README.md | 2 +- locales/pl/README.md | 2 +- locales/pt-BR/README.md | 2 +- locales/ru/README.md | 2 +- locales/tr/README.md | 2 +- locales/vi/README.md | 2 +- locales/zh-CN/README.md | 2 +- locales/zh-TW/README.md | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 1be0603a7c1..9e98cd88456 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ - [简体中文](locales/zh-CN/README.md) - [繁體中文](locales/zh-TW/README.md) - ... - + --- diff --git a/locales/ca/README.md b/locales/ca/README.md index cb577280991..b8feb8a99a7 100644 --- a/locales/ca/README.md +++ b/locales/ca/README.md @@ -35,7 +35,7 @@ - [简体中文](../zh-CN/README.md) - [繁體中文](../zh-TW/README.md) - ... - + --- diff --git a/locales/de/README.md b/locales/de/README.md index dd224ef6583..d63dfdf9554 100644 --- a/locales/de/README.md +++ b/locales/de/README.md @@ -35,7 +35,7 @@ - [简体中文](../zh-CN/README.md) - [繁體中文](../zh-TW/README.md) - ... - + --- diff --git a/locales/es/README.md b/locales/es/README.md index 38e2d68e84f..af7666d106a 100644 --- a/locales/es/README.md +++ b/locales/es/README.md @@ -35,7 +35,7 @@ - [简体中文](../zh-CN/README.md) - [繁體中文](../zh-TW/README.md) - ... - + --- diff --git a/locales/fr/README.md b/locales/fr/README.md index af0202945e0..b92535f9e7c 100644 --- a/locales/fr/README.md +++ b/locales/fr/README.md @@ -35,7 +35,7 @@ - [简体中文](../zh-CN/README.md) - [繁體中文](../zh-TW/README.md) - ... - + --- diff --git a/locales/hi/README.md b/locales/hi/README.md index fb6e89df4f8..4499feac72f 100644 --- a/locales/hi/README.md +++ b/locales/hi/README.md @@ -35,7 +35,7 @@ - [简体中文](../zh-CN/README.md) - [繁體中文](../zh-TW/README.md) - ... - + --- diff --git a/locales/id/README.md b/locales/id/README.md index 8620901d250..9c46a5ca2ee 100644 --- a/locales/id/README.md +++ b/locales/id/README.md @@ -35,7 +35,7 @@ - [简体中文](../zh-CN/README.md) - [繁體中文](../zh-TW/README.md) - ... - + --- diff --git a/locales/it/README.md b/locales/it/README.md index ebba49ea0a8..71bbda7c81f 100644 --- a/locales/it/README.md +++ b/locales/it/README.md @@ -35,7 +35,7 @@ - [简体中文](../zh-CN/README.md) - [繁體中文](../zh-TW/README.md) - ... - + --- diff --git a/locales/ja/README.md b/locales/ja/README.md index 7c427256486..1bf753546aa 100644 --- a/locales/ja/README.md +++ b/locales/ja/README.md @@ -35,7 +35,7 @@ - [简体中文](../zh-CN/README.md) - [繁體中文](../zh-TW/README.md) - ... - + --- diff --git a/locales/ko/README.md b/locales/ko/README.md index 55a89038d49..8b8f45ebb55 100644 --- a/locales/ko/README.md +++ b/locales/ko/README.md @@ -35,7 +35,7 @@ - [简体中文](../zh-CN/README.md) - [繁體中文](../zh-TW/README.md) - ... - + --- diff --git a/locales/nl/README.md b/locales/nl/README.md index d9471662623..983318aa81b 100644 --- a/locales/nl/README.md +++ b/locales/nl/README.md @@ -35,7 +35,7 @@ - [简体中文](../zh-CN/README.md) - [繁體中文](../zh-TW/README.md) - ... - + --- diff --git a/locales/pl/README.md b/locales/pl/README.md index f364f5ceb33..94e23b2980c 100644 --- a/locales/pl/README.md +++ b/locales/pl/README.md @@ -35,7 +35,7 @@ - [简体中文](../zh-CN/README.md) - [繁體中文](../zh-TW/README.md) - ... - + --- diff --git a/locales/pt-BR/README.md b/locales/pt-BR/README.md index 03113b06e58..abca12ffb73 100644 --- a/locales/pt-BR/README.md +++ b/locales/pt-BR/README.md @@ -35,7 +35,7 @@ - [简体中文](../zh-CN/README.md) - [繁體中文](../zh-TW/README.md) - ... - + --- diff --git a/locales/ru/README.md b/locales/ru/README.md index 8c7ac2703a0..d2689da5cf4 100644 --- a/locales/ru/README.md +++ b/locales/ru/README.md @@ -35,7 +35,7 @@ - [简体中文](../zh-CN/README.md) - [繁體中文](../zh-TW/README.md) - ... - + --- diff --git a/locales/tr/README.md b/locales/tr/README.md index 01fd7f1935f..c095677851a 100644 --- a/locales/tr/README.md +++ b/locales/tr/README.md @@ -35,7 +35,7 @@ - [简体中文](../zh-CN/README.md) - [繁體中文](../zh-TW/README.md) - ... - + --- diff --git a/locales/vi/README.md b/locales/vi/README.md index 116141664ec..5b8100eb2bd 100644 --- a/locales/vi/README.md +++ b/locales/vi/README.md @@ -35,7 +35,7 @@ - [简体中文](../zh-CN/README.md) - [繁體中文](../zh-TW/README.md) - ... - + --- diff --git a/locales/zh-CN/README.md b/locales/zh-CN/README.md index e5dc491386a..162e787a2b3 100644 --- a/locales/zh-CN/README.md +++ b/locales/zh-CN/README.md @@ -35,7 +35,7 @@ - [简体中文](../zh-CN/README.md) - [繁體中文](../zh-TW/README.md) - ... - + --- diff --git a/locales/zh-TW/README.md b/locales/zh-TW/README.md index 025e0704692..05d46aca68d 100644 --- a/locales/zh-TW/README.md +++ b/locales/zh-TW/README.md @@ -35,7 +35,7 @@ - [简体中文](../zh-CN/README.md) - [繁體中文](../zh-TW/README.md) - ... - + --- From d07af179ff6825bdbbf950cf95f1904d7d441bcb Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Wed, 26 Nov 2025 01:19:56 -0500 Subject: [PATCH 08/17] Add translations --- src/i18n/locales/ca/embeddings.json | 7 +++++++ src/i18n/locales/de/embeddings.json | 7 +++++++ src/i18n/locales/es/embeddings.json | 7 +++++++ src/i18n/locales/fr/embeddings.json | 7 +++++++ src/i18n/locales/hi/embeddings.json | 7 +++++++ src/i18n/locales/id/embeddings.json | 7 +++++++ src/i18n/locales/it/embeddings.json | 7 +++++++ src/i18n/locales/ja/embeddings.json | 7 +++++++ src/i18n/locales/ko/embeddings.json | 7 +++++++ src/i18n/locales/nl/embeddings.json | 7 +++++++ src/i18n/locales/pl/embeddings.json | 7 +++++++ src/i18n/locales/pt-BR/embeddings.json | 7 +++++++ src/i18n/locales/ru/embeddings.json | 7 +++++++ src/i18n/locales/tr/embeddings.json | 7 +++++++ src/i18n/locales/vi/embeddings.json | 7 +++++++ src/i18n/locales/zh-CN/embeddings.json | 7 +++++++ src/i18n/locales/zh-TW/embeddings.json | 7 +++++++ webview-ui/src/i18n/locales/ca/settings.json | 8 ++++++++ webview-ui/src/i18n/locales/de/settings.json | 8 ++++++++ 19 files changed, 135 insertions(+) diff --git a/src/i18n/locales/ca/embeddings.json b/src/i18n/locales/ca/embeddings.json index c00e336ee55..21a4a27ab41 100644 --- a/src/i18n/locales/ca/embeddings.json +++ b/src/i18n/locales/ca/embeddings.json @@ -6,6 +6,12 @@ "failedMaxAttempts": "No s'han pogut crear les incrustacions després de {{attempts}} intents", "textExceedsTokenLimit": "El text a l'índex {{index}} supera el límit màxim de testimonis ({{itemTokens}} > {{maxTokens}}). S'està ometent.", "rateLimitRetry": "S'ha assolit el límit de velocitat, es torna a intentar en {{delayMs}}ms (intent {{attempt}}/{{maxRetries}})", + "bedrock": { + "invalidResponseFormat": "Format de resposta no vàlid d'Amazon Bedrock", + "invalidCredentials": "Credencials d'AWS no vàlides. Si us plau, comprova la teva configuració d'AWS.", + "accessDenied": "Accés denegat al servei d'Amazon Bedrock. Si us plau, comprova els teus permisos d'IAM.", + "modelNotFound": "Model {{model}} no trobat a Amazon Bedrock" + }, "ollama": { "couldNotReadErrorBody": "No s'ha pogut llegir el cos de l'error", "requestFailed": "La sol·licitud de l'API d'Ollama ha fallat amb l'estat {{status}} {{statusText}}: {{errorBody}}", @@ -49,6 +55,7 @@ "mistralConfigMissing": "Falta la configuració de Mistral per crear l'embedder", "openRouterConfigMissing": "Falta la configuració d'OpenRouter per crear l'embedder", "vercelAiGatewayConfigMissing": "Falta la configuració de Vercel AI Gateway per crear l'embedder", + "bedrockConfigMissing": "Falta la configuració d'Amazon Bedrock per crear l'embedder", "invalidEmbedderType": "Tipus d'embedder configurat no vàlid: {{embedderProvider}}", "vectorDimensionNotDeterminedOpenAiCompatible": "No s'ha pogut determinar la dimensió del vector per al model '{{modelId}}' amb el proveïdor '{{provider}}'. Assegura't que la 'Dimensió d'incrustació' estigui configurada correctament als paràmetres del proveïdor compatible amb OpenAI.", "vectorDimensionNotDetermined": "No s'ha pogut determinar la dimensió del vector per al model '{{modelId}}' amb el proveïdor '{{provider}}'. Comprova els perfils del model o la configuració.", diff --git a/src/i18n/locales/de/embeddings.json b/src/i18n/locales/de/embeddings.json index e0c50e0a3d6..0297ec03091 100644 --- a/src/i18n/locales/de/embeddings.json +++ b/src/i18n/locales/de/embeddings.json @@ -6,6 +6,12 @@ "failedMaxAttempts": "Erstellung von Einbettungen nach {{attempts}} Versuchen fehlgeschlagen", "textExceedsTokenLimit": "Text bei Index {{index}} überschreitet das maximale Token-Limit ({{itemTokens}} > {{maxTokens}}). Wird übersprungen.", "rateLimitRetry": "Ratenlimit erreicht, Wiederholung in {{delayMs}}ms (Versuch {{attempt}}/{{maxRetries}})", + "bedrock": { + "invalidResponseFormat": "Ungültiges Antwortformat von Amazon Bedrock", + "invalidCredentials": "Ungültige AWS-Anmeldedaten. Bitte überprüfe deine AWS-Konfiguration.", + "accessDenied": "Zugriff auf den Amazon Bedrock-Dienst verweigert. Bitte überprüfe deine IAM-Berechtigungen.", + "modelNotFound": "Modell {{model}} in Amazon Bedrock nicht gefunden" + }, "ollama": { "couldNotReadErrorBody": "Fehlerinhalt konnte nicht gelesen werden", "requestFailed": "Ollama API-Anfrage fehlgeschlagen mit Status {{status}} {{statusText}}: {{errorBody}}", @@ -49,6 +55,7 @@ "mistralConfigMissing": "Mistral-Konfiguration fehlt für die Erstellung des Embedders", "openRouterConfigMissing": "OpenRouter-Konfiguration fehlt für die Erstellung des Embedders", "vercelAiGatewayConfigMissing": "Vercel AI Gateway-Konfiguration fehlt für die Erstellung des Embedders", + "bedrockConfigMissing": "Amazon Bedrock-Konfiguration fehlt für die Erstellung des Embedders", "invalidEmbedderType": "Ungültiger Embedder-Typ konfiguriert: {{embedderProvider}}", "vectorDimensionNotDeterminedOpenAiCompatible": "Konnte die Vektordimension für Modell '{{modelId}}' mit Anbieter '{{provider}}' nicht bestimmen. Stelle sicher, dass die 'Embedding-Dimension' in den OpenAI-kompatiblen Anbietereinstellungen korrekt eingestellt ist.", "vectorDimensionNotDetermined": "Konnte die Vektordimension für Modell '{{modelId}}' mit Anbieter '{{provider}}' nicht bestimmen. Überprüfe die Modellprofile oder Konfiguration.", diff --git a/src/i18n/locales/es/embeddings.json b/src/i18n/locales/es/embeddings.json index 76cd5cf53ad..eca9efcc075 100644 --- a/src/i18n/locales/es/embeddings.json +++ b/src/i18n/locales/es/embeddings.json @@ -6,6 +6,12 @@ "failedMaxAttempts": "No se pudieron crear las incrustaciones después de {{attempts}} intentos", "textExceedsTokenLimit": "El texto en el índice {{index}} supera el límite máximo de tokens ({{itemTokens}} > {{maxTokens}}). Omitiendo.", "rateLimitRetry": "Límite de velocidad alcanzado, reintentando en {{delayMs}}ms (intento {{attempt}}/{{maxRetries}})", + "bedrock": { + "invalidResponseFormat": "Formato de respuesta no válido de Amazon Bedrock", + "invalidCredentials": "Credenciales de AWS no válidas. Por favor, verifica tu configuración de AWS.", + "accessDenied": "Acceso denegado al servicio de Amazon Bedrock. Por favor, verifica tus permisos de IAM.", + "modelNotFound": "Modelo {{model}} no encontrado en Amazon Bedrock" + }, "ollama": { "couldNotReadErrorBody": "No se pudo leer el cuerpo del error", "requestFailed": "La solicitud de la API de Ollama falló con estado {{status}} {{statusText}}: {{errorBody}}", @@ -49,6 +55,7 @@ "mistralConfigMissing": "Falta la configuración de Mistral para la creación del incrustador", "openRouterConfigMissing": "Falta la configuración de OpenRouter para la creación del incrustador", "vercelAiGatewayConfigMissing": "Falta la configuración de Vercel AI Gateway para la creación del incrustador", + "bedrockConfigMissing": "Falta la configuración de Amazon Bedrock para la creación del incrustador", "invalidEmbedderType": "Tipo de incrustador configurado inválido: {{embedderProvider}}", "vectorDimensionNotDeterminedOpenAiCompatible": "No se pudo determinar la dimensión del vector para el modelo '{{modelId}}' con el proveedor '{{provider}}'. Asegúrate de que la 'Dimensión de incrustación' esté configurada correctamente en los ajustes del proveedor compatible con OpenAI.", "vectorDimensionNotDetermined": "No se pudo determinar la dimensión del vector para el modelo '{{modelId}}' con el proveedor '{{provider}}'. Verifica los perfiles del modelo o la configuración.", diff --git a/src/i18n/locales/fr/embeddings.json b/src/i18n/locales/fr/embeddings.json index 8bb97735a85..fa922179870 100644 --- a/src/i18n/locales/fr/embeddings.json +++ b/src/i18n/locales/fr/embeddings.json @@ -6,6 +6,12 @@ "failedMaxAttempts": "Échec de la création des embeddings après {{attempts}} tentatives", "textExceedsTokenLimit": "Le texte à l'index {{index}} dépasse la limite maximale de tokens ({{itemTokens}} > {{maxTokens}}). Ignoré.", "rateLimitRetry": "Limite de débit atteinte, nouvelle tentative dans {{delayMs}}ms (tentative {{attempt}}/{{maxRetries}})", + "bedrock": { + "invalidResponseFormat": "Format de réponse invalide d'Amazon Bedrock", + "invalidCredentials": "Identifiants AWS invalides. Veuillez vérifier votre configuration AWS.", + "accessDenied": "Accès refusé au service Amazon Bedrock. Veuillez vérifier vos permissions IAM.", + "modelNotFound": "Modèle {{model}} introuvable dans Amazon Bedrock" + }, "ollama": { "couldNotReadErrorBody": "Impossible de lire le corps de l'erreur", "requestFailed": "Échec de la requête API Ollama avec le statut {{status}} {{statusText}} : {{errorBody}}", @@ -49,6 +55,7 @@ "mistralConfigMissing": "Configuration Mistral manquante pour la création de l'embedder", "openRouterConfigMissing": "Configuration OpenRouter manquante pour la création de l'embedder", "vercelAiGatewayConfigMissing": "Configuration Vercel AI Gateway manquante pour la création de l'embedder", + "bedrockConfigMissing": "Configuration Amazon Bedrock manquante pour la création de l'embedder", "invalidEmbedderType": "Type d'embedder configuré invalide : {{embedderProvider}}", "vectorDimensionNotDeterminedOpenAiCompatible": "Impossible de déterminer la dimension du vecteur pour le modèle '{{modelId}}' avec le fournisseur '{{provider}}'. Assure-toi que la 'Dimension d'embedding' est correctement définie dans les paramètres du fournisseur compatible OpenAI.", "vectorDimensionNotDetermined": "Impossible de déterminer la dimension du vecteur pour le modèle '{{modelId}}' avec le fournisseur '{{provider}}'. Vérifie les profils du modèle ou la configuration.", diff --git a/src/i18n/locales/hi/embeddings.json b/src/i18n/locales/hi/embeddings.json index 26f9326e302..eb7f066c56f 100644 --- a/src/i18n/locales/hi/embeddings.json +++ b/src/i18n/locales/hi/embeddings.json @@ -6,6 +6,12 @@ "failedMaxAttempts": "{{attempts}} प्रयासों के बाद एम्बेडिंग बनाने में विफल", "textExceedsTokenLimit": "अनुक्रमणिका {{index}} पर पाठ अधिकतम टोकन सीमा ({{itemTokens}} > {{maxTokens}}) से अधिक है। छोड़ा जा रहा है।", "rateLimitRetry": "दर सीमा समाप्त, {{delayMs}}ms में पुन: प्रयास किया जा रहा है (प्रयास {{attempt}}/{{maxRetries}})", + "bedrock": { + "invalidResponseFormat": "Amazon Bedrock से अमान्य प्रतिसाद प्रारूप", + "invalidCredentials": "अमान्य AWS क्रेडेंशियल्स। कृपया अपनी AWS कॉन्फ़िगरेशन जांचें।", + "accessDenied": "Amazon Bedrock सेवा तक पहुंच अस्वीकृत। कृपया अपनी IAM अनुमतियां जांचें।", + "modelNotFound": "मॉडल {{model}} Amazon Bedrock में नहीं मिला" + }, "ollama": { "couldNotReadErrorBody": "त्रुटि सामग्री पढ़ नहीं सका", "requestFailed": "Ollama API अनुरोध स्थिति {{status}} {{statusText}} के साथ विफल: {{errorBody}}", @@ -49,6 +55,7 @@ "mistralConfigMissing": "एम्बेडर निर्माण के लिए मिस्ट्रल कॉन्फ़िगरेशन गायब है", "openRouterConfigMissing": "एम्बेडर निर्माण के लिए OpenRouter कॉन्फ़िगरेशन गायब है", "vercelAiGatewayConfigMissing": "एम्बेडर निर्माण के लिए Vercel AI Gateway कॉन्फ़िगरेशन गायब है", + "bedrockConfigMissing": "एम्बेडर निर्माण के लिए Amazon Bedrock कॉन्फ़िगरेशन गायब है", "invalidEmbedderType": "अमान्य एम्बेडर प्रकार कॉन्फ़िगर किया गया: {{embedderProvider}}", "vectorDimensionNotDeterminedOpenAiCompatible": "प्रदाता '{{provider}}' के साथ मॉडल '{{modelId}}' के लिए वेक्टर आयाम निर्धारित नहीं कर सका। कृपया सुनिश्चित करें कि OpenAI-संगत प्रदाता सेटिंग्स में 'एम्बेडिंग आयाम' सही तरीके से सेट है।", "vectorDimensionNotDetermined": "प्रदाता '{{provider}}' के साथ मॉडल '{{modelId}}' के लिए वेक्टर आयाम निर्धारित नहीं कर सका। मॉडल प्रोफ़ाइल या कॉन्फ़िगरेशन की जांच करें।", diff --git a/src/i18n/locales/id/embeddings.json b/src/i18n/locales/id/embeddings.json index b7cbf968514..cceb965430e 100644 --- a/src/i18n/locales/id/embeddings.json +++ b/src/i18n/locales/id/embeddings.json @@ -6,6 +6,12 @@ "failedMaxAttempts": "Gagal membuat embeddings setelah {{attempts}} percobaan", "textExceedsTokenLimit": "Teks pada indeks {{index}} melebihi batas maksimum token ({{itemTokens}} > {{maxTokens}}). Dilewati.", "rateLimitRetry": "Batas rate tercapai, mencoba lagi dalam {{delayMs}}ms (percobaan {{attempt}}/{{maxRetries}})", + "bedrock": { + "invalidResponseFormat": "Format respons tidak valid dari Amazon Bedrock", + "invalidCredentials": "Kredensial AWS tidak valid. Harap periksa konfigurasi AWS Anda.", + "accessDenied": "Akses ditolak ke layanan Amazon Bedrock. Harap periksa izin IAM Anda.", + "modelNotFound": "Model {{model}} tidak ditemukan di Amazon Bedrock" + }, "ollama": { "couldNotReadErrorBody": "Tidak dapat membaca body error", "requestFailed": "Permintaan API Ollama gagal dengan status {{status}} {{statusText}}: {{errorBody}}", @@ -49,6 +55,7 @@ "mistralConfigMissing": "Konfigurasi Mistral hilang untuk pembuatan embedder", "openRouterConfigMissing": "Konfigurasi OpenRouter hilang untuk pembuatan embedder", "vercelAiGatewayConfigMissing": "Konfigurasi Vercel AI Gateway hilang untuk pembuatan embedder", + "bedrockConfigMissing": "Konfigurasi Amazon Bedrock hilang untuk pembuatan embedder", "invalidEmbedderType": "Tipe embedder yang dikonfigurasi tidak valid: {{embedderProvider}}", "vectorDimensionNotDeterminedOpenAiCompatible": "Tidak dapat menentukan dimensi vektor untuk model '{{modelId}}' dengan penyedia '{{provider}}'. Pastikan 'Dimensi Embedding' diatur dengan benar di pengaturan penyedia yang kompatibel dengan OpenAI.", "vectorDimensionNotDetermined": "Tidak dapat menentukan dimensi vektor untuk model '{{modelId}}' dengan penyedia '{{provider}}'. Periksa profil model atau konfigurasi.", diff --git a/src/i18n/locales/it/embeddings.json b/src/i18n/locales/it/embeddings.json index 220b902f2cb..2e339ef5d88 100644 --- a/src/i18n/locales/it/embeddings.json +++ b/src/i18n/locales/it/embeddings.json @@ -6,6 +6,12 @@ "failedMaxAttempts": "Creazione degli embedding non riuscita dopo {{attempts}} tentativi", "textExceedsTokenLimit": "Il testo all'indice {{index}} supera il limite massimo di token ({{itemTokens}} > {{maxTokens}}). Saltato.", "rateLimitRetry": "Limite di velocità raggiunto, nuovo tentativo tra {{delayMs}}ms (tentativo {{attempt}}/{{maxRetries}})", + "bedrock": { + "invalidResponseFormat": "Formato di risposta non valido da Amazon Bedrock", + "invalidCredentials": "Credenziali AWS non valide. Si prega di verificare la configurazione AWS.", + "accessDenied": "Accesso negato al servizio Amazon Bedrock. Si prega di verificare le autorizzazioni IAM.", + "modelNotFound": "Modello {{model}} non trovato in Amazon Bedrock" + }, "ollama": { "couldNotReadErrorBody": "Impossibile leggere il corpo dell'errore", "requestFailed": "Richiesta API Ollama fallita con stato {{status}} {{statusText}}: {{errorBody}}", @@ -49,6 +55,7 @@ "mistralConfigMissing": "Configurazione di Mistral mancante per la creazione dell'embedder", "openRouterConfigMissing": "Configurazione di OpenRouter mancante per la creazione dell'embedder", "vercelAiGatewayConfigMissing": "Configurazione di Vercel AI Gateway mancante per la creazione dell'embedder", + "bedrockConfigMissing": "Configurazione di Amazon Bedrock mancante per la creazione dell'embedder", "invalidEmbedderType": "Tipo di embedder configurato non valido: {{embedderProvider}}", "vectorDimensionNotDeterminedOpenAiCompatible": "Impossibile determinare la dimensione del vettore per il modello '{{modelId}}' con il provider '{{provider}}'. Assicurati che la 'Dimensione di embedding' sia impostata correttamente nelle impostazioni del provider compatibile con OpenAI.", "vectorDimensionNotDetermined": "Impossibile determinare la dimensione del vettore per il modello '{{modelId}}' con il provider '{{provider}}'. Controlla i profili del modello o la configurazione.", diff --git a/src/i18n/locales/ja/embeddings.json b/src/i18n/locales/ja/embeddings.json index e74fef4138e..5223c204e0d 100644 --- a/src/i18n/locales/ja/embeddings.json +++ b/src/i18n/locales/ja/embeddings.json @@ -6,6 +6,12 @@ "failedMaxAttempts": "{{attempts}}回試行しましたが、埋め込みの作成に失敗しました", "textExceedsTokenLimit": "インデックス{{index}}のテキストが最大トークン制限を超えています({{itemTokens}}> {{maxTokens}})。スキップします。", "rateLimitRetry": "レート制限に達しました。{{delayMs}}ミリ秒後に再試行します(試行{{attempt}}/{{maxRetries}})", + "bedrock": { + "invalidResponseFormat": "Amazon Bedrockからの無効な応答形式", + "invalidCredentials": "無効なAWS認証情報です。AWSの設定を確認してください。", + "accessDenied": "Amazon Bedrockサービスへのアクセスが拒否されました。IAMの権限を確認してください。", + "modelNotFound": "モデル{{model}}がAmazon Bedrockに見つかりません" + }, "ollama": { "couldNotReadErrorBody": "エラー本文を読み取れませんでした", "requestFailed": "Ollama APIリクエストが失敗しました。ステータス {{status}} {{statusText}}: {{errorBody}}", @@ -49,6 +55,7 @@ "mistralConfigMissing": "エンベッダー作成のためのMistral設定がありません", "openRouterConfigMissing": "エンベッダー作成のためのOpenRouter設定がありません", "vercelAiGatewayConfigMissing": "エンベッダー作成のためのVercel AI Gateway設定がありません", + "bedrockConfigMissing": "エンベッダー作成のためのAmazon Bedrock設定がありません", "invalidEmbedderType": "無効なエンベッダータイプが設定されています: {{embedderProvider}}", "vectorDimensionNotDeterminedOpenAiCompatible": "プロバイダー '{{provider}}' のモデル '{{modelId}}' の埋め込み次元を決定できませんでした。OpenAI互換プロバイダー設定で「埋め込み次元」が正しく設定されていることを確認してください。", "vectorDimensionNotDetermined": "プロバイダー '{{provider}}' のモデル '{{modelId}}' の埋め込み次元を決定できませんでした。モデルプロファイルまたは設定を確認してください。", diff --git a/src/i18n/locales/ko/embeddings.json b/src/i18n/locales/ko/embeddings.json index 31c73fa5f26..236662eea22 100644 --- a/src/i18n/locales/ko/embeddings.json +++ b/src/i18n/locales/ko/embeddings.json @@ -6,6 +6,12 @@ "failedMaxAttempts": "{{attempts}}번 시도 후 임베딩 생성 실패", "textExceedsTokenLimit": "인덱스 {{index}}의 텍스트가 최대 토큰 제한({{itemTokens}} > {{maxTokens}})을 초과했습니다. 건너뜁니다.", "rateLimitRetry": "속도 제한에 도달했습니다. {{delayMs}}ms 후에 다시 시도합니다(시도 {{attempt}}/{{maxRetries}}).", + "bedrock": { + "invalidResponseFormat": "Amazon Bedrock에서 잘못된 응답 형식", + "invalidCredentials": "잘못된 AWS 자격증명입니다. AWS 구성을 확인하세요.", + "accessDenied": "Amazon Bedrock 서비스에 대한 액세스가 거부되었습니다. IAM 권한을 확인하세요.", + "modelNotFound": "Amazon Bedrock에서 모델 {{model}}을(를) 찾을 수 없습니다" + }, "ollama": { "couldNotReadErrorBody": "오류 본문을 읽을 수 없습니다", "requestFailed": "Ollama API 요청이 실패했습니다. 상태 {{status}} {{statusText}}: {{errorBody}}", @@ -49,6 +55,7 @@ "mistralConfigMissing": "임베더 생성을 위한 Mistral 구성이 없습니다", "openRouterConfigMissing": "임베더 생성을 위한 OpenRouter 구성이 없습니다", "vercelAiGatewayConfigMissing": "임베더 생성을 위한 Vercel AI Gateway 구성이 없습니다", + "bedrockConfigMissing": "임베더 생성을 위한 Amazon Bedrock 구성이 없습니다", "invalidEmbedderType": "잘못된 임베더 유형이 구성되었습니다: {{embedderProvider}}", "vectorDimensionNotDeterminedOpenAiCompatible": "프로바이더 '{{provider}}'의 모델 '{{modelId}}'에 대한 벡터 차원을 결정할 수 없습니다. OpenAI 호환 프로바이더 설정에서 '임베딩 차원'이 올바르게 설정되어 있는지 확인하세요.", "vectorDimensionNotDetermined": "프로바이더 '{{provider}}'의 모델 '{{modelId}}'에 대한 벡터 차원을 결정할 수 없습니다. 모델 프로필 또는 구성을 확인하세요.", diff --git a/src/i18n/locales/nl/embeddings.json b/src/i18n/locales/nl/embeddings.json index aa6d242f1f1..cce3f05c625 100644 --- a/src/i18n/locales/nl/embeddings.json +++ b/src/i18n/locales/nl/embeddings.json @@ -6,6 +6,12 @@ "failedMaxAttempts": "Insluitingen maken mislukt na {{attempts}} pogingen", "textExceedsTokenLimit": "Tekst op index {{index}} overschrijdt de maximale tokenlimiet ({{itemTokens}} > {{maxTokens}}). Wordt overgeslagen.", "rateLimitRetry": "Snelheidslimiet bereikt, opnieuw proberen over {{delayMs}}ms (poging {{attempt}}/{{maxRetries}})", + "bedrock": { + "invalidResponseFormat": "Ongeldig antwoordformaat van Amazon Bedrock", + "invalidCredentials": "Ongeldige AWS-referenties. Controleer uw AWS-configuratie.", + "accessDenied": "Toegang geweigerd tot Amazon Bedrock-service. Controleer uw IAM-machtigingen.", + "modelNotFound": "Model {{model}} niet gevonden in Amazon Bedrock" + }, "ollama": { "couldNotReadErrorBody": "Kon foutinhoud niet lezen", "requestFailed": "Ollama API-verzoek mislukt met status {{status}} {{statusText}}: {{errorBody}}", @@ -49,6 +55,7 @@ "mistralConfigMissing": "Mistral-configuratie ontbreekt voor het maken van de embedder", "openRouterConfigMissing": "OpenRouter-configuratie ontbreekt voor het maken van de embedder", "vercelAiGatewayConfigMissing": "Vercel AI Gateway-configuratie ontbreekt voor het maken van de embedder", + "bedrockConfigMissing": "Amazon Bedrock-configuratie ontbreekt voor het maken van de embedder", "invalidEmbedderType": "Ongeldig embedder-type geconfigureerd: {{embedderProvider}}", "vectorDimensionNotDeterminedOpenAiCompatible": "Kan de vectordimensie voor model '{{modelId}}' met provider '{{provider}}' niet bepalen. Zorg ervoor dat de 'Embedding Dimensie' correct is ingesteld in de OpenAI-compatibele provider-instellingen.", "vectorDimensionNotDetermined": "Kan de vectordimensie voor model '{{modelId}}' met provider '{{provider}}' niet bepalen. Controleer modelprofielen of configuratie.", diff --git a/src/i18n/locales/pl/embeddings.json b/src/i18n/locales/pl/embeddings.json index 88543ede38c..133f9f40da2 100644 --- a/src/i18n/locales/pl/embeddings.json +++ b/src/i18n/locales/pl/embeddings.json @@ -6,6 +6,12 @@ "failedMaxAttempts": "Nie udało się utworzyć osadzeń po {{attempts}} próbach", "textExceedsTokenLimit": "Tekst w indeksie {{index}} przekracza maksymalny limit tokenów ({{itemTokens}} > {{maxTokens}}). Pomijanie.", "rateLimitRetry": "Osiągnięto limit szybkości, ponawianie za {{delayMs}}ms (próba {{attempt}}/{{maxRetries}})", + "bedrock": { + "invalidResponseFormat": "Nieprawidłowy format odpowiedzi z Amazon Bedrock", + "invalidCredentials": "Nieprawidłowe poświadczenia AWS. Sprawdź konfigurację AWS.", + "accessDenied": "Odmowa dostępu do usługi Amazon Bedrock. Sprawdź uprawnienia IAM.", + "modelNotFound": "Model {{model}} nie znaleziony w Amazon Bedrock" + }, "ollama": { "couldNotReadErrorBody": "Nie można odczytać treści błędu", "requestFailed": "Żądanie API Ollama nie powiodło się ze statusem {{status}} {{statusText}}: {{errorBody}}", @@ -49,6 +55,7 @@ "mistralConfigMissing": "Brak konfiguracji Mistral do utworzenia embeddera", "openRouterConfigMissing": "Brak konfiguracji OpenRouter do utworzenia embeddera", "vercelAiGatewayConfigMissing": "Brak konfiguracji Vercel AI Gateway do utworzenia embeddera", + "bedrockConfigMissing": "Brak konfiguracji Amazon Bedrock do utworzenia embeddera", "invalidEmbedderType": "Skonfigurowano nieprawidłowy typ embeddera: {{embedderProvider}}", "vectorDimensionNotDeterminedOpenAiCompatible": "Nie można określić wymiaru wektora dla modelu '{{modelId}}' z dostawcą '{{provider}}'. Upewnij się, że 'Wymiar osadzania' jest poprawnie ustawiony w ustawieniach dostawcy kompatybilnego z OpenAI.", "vectorDimensionNotDetermined": "Nie można określić wymiaru wektora dla modelu '{{modelId}}' z dostawcą '{{provider}}'. Sprawdź profile modelu lub konfigurację.", diff --git a/src/i18n/locales/pt-BR/embeddings.json b/src/i18n/locales/pt-BR/embeddings.json index c67d0df686b..09f4a557874 100644 --- a/src/i18n/locales/pt-BR/embeddings.json +++ b/src/i18n/locales/pt-BR/embeddings.json @@ -6,6 +6,12 @@ "failedMaxAttempts": "Falha ao criar embeddings após {{attempts}} tentativas", "textExceedsTokenLimit": "O texto no índice {{index}} excede o limite máximo de tokens ({{itemTokens}} > {{maxTokens}}). Ignorando.", "rateLimitRetry": "Limite de taxa atingido, tentando novamente em {{delayMs}}ms (tentativa {{attempt}}/{{maxRetries}})", + "bedrock": { + "invalidResponseFormat": "Formato de resposta inválido do Amazon Bedrock", + "invalidCredentials": "Credenciais AWS inválidas. Verifique sua configuração AWS.", + "accessDenied": "Acesso negado ao serviço Amazon Bedrock. Verifique suas permissões IAM.", + "modelNotFound": "Modelo {{model}} não encontrado no Amazon Bedrock" + }, "ollama": { "couldNotReadErrorBody": "Não foi possível ler o corpo do erro", "requestFailed": "Solicitação da API Ollama falhou com status {{status}} {{statusText}}: {{errorBody}}", @@ -49,6 +55,7 @@ "mistralConfigMissing": "Configuração do Mistral ausente para a criação do embedder", "openRouterConfigMissing": "Configuração do OpenRouter ausente para a criação do embedder", "vercelAiGatewayConfigMissing": "Configuração do Vercel AI Gateway ausente para a criação do embedder", + "bedrockConfigMissing": "Configuração do Amazon Bedrock ausente para a criação do embedder", "invalidEmbedderType": "Tipo de embedder configurado inválido: {{embedderProvider}}", "vectorDimensionNotDeterminedOpenAiCompatible": "Não foi possível determinar a dimensão do vetor para o modelo '{{modelId}}' com o provedor '{{provider}}'. Certifique-se de que a 'Dimensão de Embedding' esteja configurada corretamente nas configurações do provedor compatível com OpenAI.", "vectorDimensionNotDetermined": "Não foi possível determinar a dimensão do vetor para o modelo '{{modelId}}' com o provedor '{{provider}}'. Verifique os perfis do modelo ou a configuração.", diff --git a/src/i18n/locales/ru/embeddings.json b/src/i18n/locales/ru/embeddings.json index 7e48af3d59e..9e94082bbfb 100644 --- a/src/i18n/locales/ru/embeddings.json +++ b/src/i18n/locales/ru/embeddings.json @@ -6,6 +6,12 @@ "failedMaxAttempts": "Не удалось создать вложения после {{attempts}} попыток", "textExceedsTokenLimit": "Текст в индексе {{index}} превышает максимальный лимит токенов ({{itemTokens}} > {{maxTokens}}). Пропускается.", "rateLimitRetry": "Достигнут лимит скорости, повторная попытка через {{delayMs}} мс (попытка {{attempt}}/{{maxRetries}})", + "bedrock": { + "invalidResponseFormat": "Неверный формат ответа от Amazon Bedrock", + "invalidCredentials": "Неверные учетные данные AWS. Проверьте конфигурацию AWS.", + "accessDenied": "Доступ запрещен к сервису Amazon Bedrock. Проверьте разрешения IAM.", + "modelNotFound": "Модель {{model}} не найдена в Amazon Bedrock" + }, "ollama": { "couldNotReadErrorBody": "Не удалось прочитать тело ошибки", "requestFailed": "Запрос к API Ollama не удался со статусом {{status}} {{statusText}}: {{errorBody}}", @@ -49,6 +55,7 @@ "mistralConfigMissing": "Конфигурация Mistral отсутствует для создания эмбеддера", "openRouterConfigMissing": "Конфигурация OpenRouter отсутствует для создания эмбеддера", "vercelAiGatewayConfigMissing": "Конфигурация Vercel AI Gateway отсутствует для создания эмбеддера", + "bedrockConfigMissing": "Конфигурация Amazon Bedrock отсутствует для создания эмбеддера", "invalidEmbedderType": "Настроен недопустимый тип эмбеддера: {{embedderProvider}}", "vectorDimensionNotDeterminedOpenAiCompatible": "Не удалось определить размерность вектора для модели '{{modelId}}' с провайдером '{{provider}}'. Убедитесь, что 'Размерность эмбеддинга' правильно установлена в настройках провайдера, совместимого с OpenAI.", "vectorDimensionNotDetermined": "Не удалось определить размерность вектора для модели '{{modelId}}' с провайдером '{{provider}}'. Проверьте профили модели или конфигурацию.", diff --git a/src/i18n/locales/tr/embeddings.json b/src/i18n/locales/tr/embeddings.json index 36efc466e3d..411ed7ab526 100644 --- a/src/i18n/locales/tr/embeddings.json +++ b/src/i18n/locales/tr/embeddings.json @@ -6,6 +6,12 @@ "failedMaxAttempts": "{{attempts}} denemeden sonra gömülmeler oluşturulamadı", "textExceedsTokenLimit": "{{index}} dizinindeki metin maksimum jeton sınırını aşıyor ({{itemTokens}} > {{maxTokens}}). Atlanıyor.", "rateLimitRetry": "Hız sınırına ulaşıldı, {{delayMs}}ms içinde yeniden deneniyor (deneme {{attempt}}/{{maxRetries}})", + "bedrock": { + "invalidResponseFormat": "Amazon Bedrock'tan geçersiz yanıt formatı", + "invalidCredentials": "Geçersiz AWS kimlik bilgileri. Lütfen AWS yapılandırmanızı kontrol edin.", + "accessDenied": "Amazon Bedrock hizmetine erişim reddedildi. Lütfen IAM izinlerinizi kontrol edin.", + "modelNotFound": "Model {{model}} Amazon Bedrock'ta bulunamadı" + }, "ollama": { "couldNotReadErrorBody": "Hata gövdesi okunamadı", "requestFailed": "Ollama API isteği {{status}} {{statusText}} durumuyla başarısız oldu: {{errorBody}}", @@ -49,6 +55,7 @@ "mistralConfigMissing": "Gömücü oluşturmak için Mistral yapılandırması eksik", "openRouterConfigMissing": "Gömücü oluşturmak için OpenRouter yapılandırması eksik", "vercelAiGatewayConfigMissing": "Gömücü oluşturmak için Vercel AI Gateway yapılandırması eksik", + "bedrockConfigMissing": "Gömücü oluşturmak için Amazon Bedrock yapılandırması eksik", "invalidEmbedderType": "Geçersiz gömücü türü yapılandırıldı: {{embedderProvider}}", "vectorDimensionNotDeterminedOpenAiCompatible": "'{{provider}}' sağlayıcısı ile '{{modelId}}' modeli için vektör boyutu belirlenemedi. OpenAI uyumlu sağlayıcı ayarlarında 'Gömme Boyutu'nun doğru ayarlandığından emin ol.", "vectorDimensionNotDetermined": "'{{provider}}' sağlayıcısı ile '{{modelId}}' modeli için vektör boyutu belirlenemedi. Model profillerini veya yapılandırmayı kontrol et.", diff --git a/src/i18n/locales/vi/embeddings.json b/src/i18n/locales/vi/embeddings.json index 96496083caa..c9f9880df08 100644 --- a/src/i18n/locales/vi/embeddings.json +++ b/src/i18n/locales/vi/embeddings.json @@ -6,6 +6,12 @@ "failedMaxAttempts": "Không thể tạo nhúng sau {{attempts}} lần thử", "textExceedsTokenLimit": "Văn bản tại chỉ mục {{index}} vượt quá giới hạn mã thông báo tối đa ({{itemTokens}} > {{maxTokens}}). Bỏ qua.", "rateLimitRetry": "Đã đạt đến giới hạn tốc độ, thử lại sau {{delayMs}}ms (lần thử {{attempt}}/{{maxRetries}})", + "bedrock": { + "invalidResponseFormat": "Định dạng phản hồi không hợp lệ từ Amazon Bedrock", + "invalidCredentials": "Thông tin đăng nhập AWS không hợp lệ. Vui lòng kiểm tra cấu hình AWS của bạn.", + "accessDenied": "Bị từ chối truy cập dịch vụ Amazon Bedrock. Vui lòng kiểm tra quyền IAM của bạn.", + "modelNotFound": "Không tìm thấy mô hình {{model}} trong Amazon Bedrock" + }, "ollama": { "couldNotReadErrorBody": "Không thể đọc nội dung lỗi", "requestFailed": "Yêu cầu API Ollama thất bại với trạng thái {{status}} {{statusText}}: {{errorBody}}", @@ -49,6 +55,7 @@ "mistralConfigMissing": "Thiếu cấu hình Mistral để tạo trình nhúng", "openRouterConfigMissing": "Thiếu cấu hình OpenRouter để tạo trình nhúng", "vercelAiGatewayConfigMissing": "Thiếu cấu hình Vercel AI Gateway để tạo trình nhúng", + "bedrockConfigMissing": "Thiếu cấu hình Amazon Bedrock để tạo trình nhúng", "invalidEmbedderType": "Loại embedder được cấu hình không hợp lệ: {{embedderProvider}}", "vectorDimensionNotDeterminedOpenAiCompatible": "Không thể xác định kích thước vector cho mô hình '{{modelId}}' với nhà cung cấp '{{provider}}'. Hãy đảm bảo 'Kích thước Embedding' được cài đặt đúng trong cài đặt nhà cung cấp tương thích OpenAI.", "vectorDimensionNotDetermined": "Không thể xác định kích thước vector cho mô hình '{{modelId}}' với nhà cung cấp '{{provider}}'. Kiểm tra hồ sơ mô hình hoặc cấu hình.", diff --git a/src/i18n/locales/zh-CN/embeddings.json b/src/i18n/locales/zh-CN/embeddings.json index dfc591391e5..c27bc078015 100644 --- a/src/i18n/locales/zh-CN/embeddings.json +++ b/src/i18n/locales/zh-CN/embeddings.json @@ -6,6 +6,12 @@ "failedMaxAttempts": "尝试 {{attempts}} 次后创建嵌入失败", "textExceedsTokenLimit": "索引 {{index}} 处的文本超过最大令牌限制 ({{itemTokens}} > {{maxTokens}})。正在跳过。", "rateLimitRetry": "已达到速率限制,将在 {{delayMs}} 毫秒后重试(尝试次数 {{attempt}}/{{maxRetries}})", + "bedrock": { + "invalidResponseFormat": "Amazon Bedrock 返回无效的响应格式", + "invalidCredentials": "AWS 凭证无效。请检查您的 AWS 配置。", + "accessDenied": "访问 Amazon Bedrock 服务被拒绝。请检查您的 IAM 权限。", + "modelNotFound": "在 Amazon Bedrock 中找不到模型 {{model}}" + }, "ollama": { "couldNotReadErrorBody": "无法读取错误内容", "requestFailed": "Ollama API 请求失败,状态码 {{status}} {{statusText}}:{{errorBody}}", @@ -49,6 +55,7 @@ "mistralConfigMissing": "创建嵌入器时缺少 Mistral 配置", "openRouterConfigMissing": "创建嵌入器时缺少 OpenRouter 配置", "vercelAiGatewayConfigMissing": "创建嵌入器时缺少 Vercel AI Gateway 配置", + "bedrockConfigMissing": "创建嵌入器时缺少 Amazon Bedrock 配置", "invalidEmbedderType": "配置的嵌入器类型无效:{{embedderProvider}}", "vectorDimensionNotDeterminedOpenAiCompatible": "无法确定提供商 '{{provider}}' 的模型 '{{modelId}}' 的向量维度。请确保在 OpenAI 兼容提供商设置中正确设置了「嵌入维度」。", "vectorDimensionNotDetermined": "无法确定提供商 '{{provider}}' 的模型 '{{modelId}}' 的向量维度。请检查模型配置文件或配置。", diff --git a/src/i18n/locales/zh-TW/embeddings.json b/src/i18n/locales/zh-TW/embeddings.json index 24ed5190967..744e7022ea1 100644 --- a/src/i18n/locales/zh-TW/embeddings.json +++ b/src/i18n/locales/zh-TW/embeddings.json @@ -6,6 +6,12 @@ "failedMaxAttempts": "嘗試 {{attempts}} 次後建立內嵌失敗", "textExceedsTokenLimit": "索引 {{index}} 處的文字超過最大權杖限制 ({{itemTokens}} > {{maxTokens}})。正在略過。", "rateLimitRetry": "已達到速率限制,將在 {{delayMs}} 毫秒後重試(嘗試次數 {{attempt}}/{{maxRetries}})", + "bedrock": { + "invalidResponseFormat": "Amazon Bedrock 傳回無效的回應格式", + "invalidCredentials": "AWS 認證無效。請檢查您的 AWS 設定。", + "accessDenied": "存取 Amazon Bedrock 服務遭拒。請檢查您的 IAM 權限。", + "modelNotFound": "在 Amazon Bedrock 中找不到模型 {{model}}" + }, "ollama": { "couldNotReadErrorBody": "無法讀取錯誤內容", "requestFailed": "Ollama API 請求失敗,狀態碼 {{status}} {{statusText}}:{{errorBody}}", @@ -49,6 +55,7 @@ "mistralConfigMissing": "建立嵌入器時缺少 Mistral 設定", "openRouterConfigMissing": "建立嵌入器時缺少 OpenRouter 設定", "vercelAiGatewayConfigMissing": "建立嵌入器時缺少 Vercel AI Gateway 設定", + "bedrockConfigMissing": "建立嵌入器時缺少 Amazon Bedrock 設定", "invalidEmbedderType": "設定的嵌入器類型無效:{{embedderProvider}}", "vectorDimensionNotDeterminedOpenAiCompatible": "無法確定提供商 '{{provider}}' 的模型 '{{modelId}}' 的向量維度。請確保在 OpenAI 相容提供商設定中正確設定了「嵌入維度」。", "vectorDimensionNotDetermined": "無法確定提供商 '{{provider}}' 的模型 '{{modelId}}' 的向量維度。請檢查模型設定檔或設定。", diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index b54bd5a3ac2..8abd261dda4 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -78,6 +78,12 @@ "vercelAiGatewayProvider": "Vercel AI Gateway", "vercelAiGatewayApiKeyLabel": "Clau API", "vercelAiGatewayApiKeyPlaceholder": "Introduïu la vostra clau API de Vercel AI Gateway", + "bedrockProvider": "Amazon Bedrock", + "bedrockRegionLabel": "Regió d'AWS", + "bedrockRegionPlaceholder": "us-east-1", + "bedrockProfileLabel": "Perfil d'AWS", + "bedrockProfilePlaceholder": "default", + "bedrockProfileDescription": "Nom del perfil d'AWS de ~/.aws/credentials (obligatori).", "openRouterProvider": "OpenRouter", "openRouterApiKeyLabel": "Clau de l'API d'OpenRouter", "openRouterApiKeyPlaceholder": "Introduïu la vostra clau de l'API d'OpenRouter", @@ -145,6 +151,8 @@ "geminiApiKeyRequired": "Cal una clau d'API de Gemini", "mistralApiKeyRequired": "La clau de l'API de Mistral és requerida", "vercelAiGatewayApiKeyRequired": "Es requereix la clau API de Vercel AI Gateway", + "bedrockRegionRequired": "Es requereix la regió d'AWS", + "bedrockProfileRequired": "Es requereix el perfil d'AWS", "ollamaBaseUrlRequired": "Cal una URL base d'Ollama", "baseUrlRequired": "Cal una URL base", "modelDimensionMinValue": "La dimensió del model ha de ser superior a 0", diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index 632757f71ac..68ae295b7de 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -80,6 +80,12 @@ "vercelAiGatewayProvider": "Vercel AI Gateway", "vercelAiGatewayApiKeyLabel": "API-Schlüssel", "vercelAiGatewayApiKeyPlaceholder": "Gib deinen Vercel AI Gateway API-Schlüssel ein", + "bedrockProvider": "Amazon Bedrock", + "bedrockRegionLabel": "AWS-Region", + "bedrockRegionPlaceholder": "us-east-1", + "bedrockProfileLabel": "AWS-Profil", + "bedrockProfilePlaceholder": "default", + "bedrockProfileDescription": "AWS-Profilname aus ~/.aws/credentials (erforderlich).", "openRouterProvider": "OpenRouter", "openRouterApiKeyLabel": "OpenRouter API-Schlüssel", "openRouterApiKeyPlaceholder": "Gib deinen OpenRouter API-Schlüssel ein", @@ -145,6 +151,8 @@ "geminiApiKeyRequired": "Gemini-API-Schlüssel ist erforderlich", "mistralApiKeyRequired": "Mistral-API-Schlüssel ist erforderlich", "vercelAiGatewayApiKeyRequired": "Vercel AI Gateway API-Schlüssel ist erforderlich", + "bedrockRegionRequired": "AWS-Region erforderlich", + "bedrockProfileRequired": "AWS-Profil erforderlich", "ollamaBaseUrlRequired": "Ollama-Basis-URL ist erforderlich", "baseUrlRequired": "Basis-URL ist erforderlich", "modelDimensionMinValue": "Modellabmessung muss größer als 0 sein", From c5f2dcc66750c943f57aa89fed59cc343d740633 Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Wed, 26 Nov 2025 01:44:36 -0500 Subject: [PATCH 09/17] More translations --- webview-ui/src/i18n/locales/es/settings.json | 8 ++++++++ webview-ui/src/i18n/locales/fr/settings.json | 8 ++++++++ webview-ui/src/i18n/locales/hi/settings.json | 8 ++++++++ webview-ui/src/i18n/locales/id/settings.json | 8 ++++++++ webview-ui/src/i18n/locales/it/settings.json | 8 ++++++++ webview-ui/src/i18n/locales/ja/settings.json | 8 ++++++++ webview-ui/src/i18n/locales/ko/settings.json | 8 ++++++++ webview-ui/src/i18n/locales/nl/settings.json | 8 ++++++++ webview-ui/src/i18n/locales/pl/settings.json | 8 ++++++++ webview-ui/src/i18n/locales/pt-BR/settings.json | 8 ++++++++ webview-ui/src/i18n/locales/ru/settings.json | 8 ++++++++ webview-ui/src/i18n/locales/tr/settings.json | 8 ++++++++ webview-ui/src/i18n/locales/vi/settings.json | 8 ++++++++ webview-ui/src/i18n/locales/zh-CN/settings.json | 8 ++++++++ webview-ui/src/i18n/locales/zh-TW/settings.json | 8 ++++++++ 15 files changed, 120 insertions(+) diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index 59327d69eae..b6a94d82b25 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -80,6 +80,12 @@ "vercelAiGatewayProvider": "Vercel AI Gateway", "vercelAiGatewayApiKeyLabel": "Clave API", "vercelAiGatewayApiKeyPlaceholder": "Introduce tu clave API de Vercel AI Gateway", + "bedrockProvider": "Amazon Bedrock", + "bedrockRegionLabel": "Región de AWS", + "bedrockRegionPlaceholder": "us-east-1", + "bedrockProfileLabel": "Perfil de AWS", + "bedrockProfilePlaceholder": "default", + "bedrockProfileDescription": "Nombre del perfil de AWS desde ~/.aws/credentials (requerido).", "openRouterProvider": "OpenRouter", "openRouterApiKeyLabel": "Clave de API de OpenRouter", "openRouterApiKeyPlaceholder": "Introduce tu clave de API de OpenRouter", @@ -145,6 +151,8 @@ "geminiApiKeyRequired": "Se requiere la clave API de Gemini", "mistralApiKeyRequired": "Se requiere la clave de API de Mistral", "vercelAiGatewayApiKeyRequired": "Se requiere la clave API de Vercel AI Gateway", + "bedrockRegionRequired": "Se requiere la región de AWS", + "bedrockProfileRequired": "Se requiere el perfil de AWS", "ollamaBaseUrlRequired": "Se requiere la URL base de Ollama", "baseUrlRequired": "Se requiere la URL base", "modelDimensionMinValue": "La dimensión del modelo debe ser mayor que 0", diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index 40ed87ed874..eeaf0ffa35a 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -80,6 +80,12 @@ "vercelAiGatewayProvider": "Vercel AI Gateway", "vercelAiGatewayApiKeyLabel": "Clé API", "vercelAiGatewayApiKeyPlaceholder": "Entrez votre clé API Vercel AI Gateway", + "bedrockProvider": "Amazon Bedrock", + "bedrockRegionLabel": "Région AWS", + "bedrockRegionPlaceholder": "us-east-1", + "bedrockProfileLabel": "Profil AWS", + "bedrockProfilePlaceholder": "default", + "bedrockProfileDescription": "Nom du profil AWS depuis ~/.aws/credentials (requis).", "openRouterProvider": "OpenRouter", "openRouterApiKeyLabel": "Clé d'API OpenRouter", "openRouterApiKeyPlaceholder": "Entrez votre clé d'API OpenRouter", @@ -145,6 +151,8 @@ "geminiApiKeyRequired": "La clé API Gemini est requise", "mistralApiKeyRequired": "La clé API Mistral est requise", "vercelAiGatewayApiKeyRequired": "La clé API Vercel AI Gateway est requise", + "bedrockRegionRequired": "La région AWS est requise", + "bedrockProfileRequired": "Le profil AWS est requis", "ollamaBaseUrlRequired": "L'URL de base Ollama est requise", "baseUrlRequired": "L'URL de base est requise", "modelDimensionMinValue": "La dimension du modèle doit être supérieure à 0", diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index 6bc61918cba..c55f4f8fec6 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -75,6 +75,12 @@ "vercelAiGatewayProvider": "Vercel AI Gateway", "vercelAiGatewayApiKeyLabel": "API कुंजी", "vercelAiGatewayApiKeyPlaceholder": "अपनी Vercel AI Gateway API कुंजी दर्ज करें", + "bedrockProvider": "Amazon Bedrock", + "bedrockRegionLabel": "AWS क्षेत्र", + "bedrockRegionPlaceholder": "us-east-1", + "bedrockProfileLabel": "AWS प्रोफ़ाइल", + "bedrockProfilePlaceholder": "default", + "bedrockProfileDescription": "~/.aws/credentials से AWS प्रोफ़ाइल नाम (आवश्यक)।", "openRouterProvider": "ओपनराउटर", "openRouterApiKeyLabel": "ओपनराउटर एपीआई कुंजी", "openRouterApiKeyPlaceholder": "अपनी ओपनराउटर एपीआई कुंजी दर्ज करें", @@ -145,6 +151,8 @@ "geminiApiKeyRequired": "Gemini API कुंजी आवश्यक है", "mistralApiKeyRequired": "मिस्ट्रल एपीआई कुंजी आवश्यक है", "vercelAiGatewayApiKeyRequired": "Vercel AI Gateway API कुंजी आवश्यक है", + "bedrockRegionRequired": "AWS क्षेत्र आवश्यक है", + "bedrockProfileRequired": "AWS प्रोफ़ाइल आवश्यक है", "ollamaBaseUrlRequired": "Ollama आधार URL आवश्यक है", "baseUrlRequired": "आधार URL आवश्यक है", "modelDimensionMinValue": "मॉडल आयाम 0 से बड़ा होना चाहिए", diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json index d33287f6548..07e5447d984 100644 --- a/webview-ui/src/i18n/locales/id/settings.json +++ b/webview-ui/src/i18n/locales/id/settings.json @@ -75,6 +75,12 @@ "vercelAiGatewayProvider": "Vercel AI Gateway", "vercelAiGatewayApiKeyLabel": "API Key", "vercelAiGatewayApiKeyPlaceholder": "Masukkan kunci API Vercel AI Gateway Anda", + "bedrockProvider": "Amazon Bedrock", + "bedrockRegionLabel": "Wilayah AWS", + "bedrockRegionPlaceholder": "us-east-1", + "bedrockProfileLabel": "Profil AWS", + "bedrockProfilePlaceholder": "default", + "bedrockProfileDescription": "Nama profil AWS dari ~/.aws/credentials (wajib).", "openRouterProvider": "OpenRouter", "openRouterApiKeyLabel": "Kunci API OpenRouter", "openRouterApiKeyPlaceholder": "Masukkan kunci API OpenRouter Anda", @@ -145,6 +151,8 @@ "geminiApiKeyRequired": "Kunci API Gemini diperlukan", "mistralApiKeyRequired": "Kunci API Mistral diperlukan", "vercelAiGatewayApiKeyRequired": "Kunci API Vercel AI Gateway diperlukan", + "bedrockRegionRequired": "Wilayah AWS diperlukan", + "bedrockProfileRequired": "Profil AWS diperlukan", "ollamaBaseUrlRequired": "URL dasar Ollama diperlukan", "baseUrlRequired": "URL dasar diperlukan", "modelDimensionMinValue": "Dimensi model harus lebih besar dari 0", diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index 7f88a1f6a72..8b07721ba65 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -75,6 +75,12 @@ "vercelAiGatewayProvider": "Vercel AI Gateway", "vercelAiGatewayApiKeyLabel": "Chiave API", "vercelAiGatewayApiKeyPlaceholder": "Inserisci la tua chiave API Vercel AI Gateway", + "bedrockProvider": "Amazon Bedrock", + "bedrockRegionLabel": "Regione AWS", + "bedrockRegionPlaceholder": "us-east-1", + "bedrockProfileLabel": "Profilo AWS", + "bedrockProfilePlaceholder": "default", + "bedrockProfileDescription": "Nome del profilo AWS da ~/.aws/credentials (richiesto).", "openRouterProvider": "OpenRouter", "openRouterApiKeyLabel": "Chiave API OpenRouter", "openRouterApiKeyPlaceholder": "Inserisci la tua chiave API OpenRouter", @@ -145,6 +151,8 @@ "geminiApiKeyRequired": "È richiesta la chiave API Gemini", "mistralApiKeyRequired": "La chiave API di Mistral è richiesta", "vercelAiGatewayApiKeyRequired": "È richiesta la chiave API Vercel AI Gateway", + "bedrockRegionRequired": "La regione AWS è richiesta", + "bedrockProfileRequired": "Il profilo AWS è richiesto", "ollamaBaseUrlRequired": "È richiesto l'URL di base di Ollama", "baseUrlRequired": "È richiesto l'URL di base", "modelDimensionMinValue": "La dimensione del modello deve essere maggiore di 0", diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index cefe8ca20dc..5358893069e 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -75,6 +75,12 @@ "vercelAiGatewayProvider": "Vercel AI Gateway", "vercelAiGatewayApiKeyLabel": "APIキー", "vercelAiGatewayApiKeyPlaceholder": "Vercel AI GatewayのAPIキーを入力してください", + "bedrockProvider": "Amazon Bedrock", + "bedrockRegionLabel": "AWS リージョン", + "bedrockRegionPlaceholder": "us-east-1", + "bedrockProfileLabel": "AWS プロファイル", + "bedrockProfilePlaceholder": "default", + "bedrockProfileDescription": "~/.aws/credentials の AWS プロファイル名(必須)。", "openRouterProvider": "OpenRouter", "openRouterApiKeyLabel": "OpenRouter APIキー", "openRouterApiKeyPlaceholder": "OpenRouter APIキーを入力してください", @@ -145,6 +151,8 @@ "geminiApiKeyRequired": "Gemini APIキーが必要です", "mistralApiKeyRequired": "Mistral APIキーが必要です", "vercelAiGatewayApiKeyRequired": "Vercel AI Gateway APIキーが必要です", + "bedrockRegionRequired": "AWS リージョンは必須です", + "bedrockProfileRequired": "AWS プロファイルは必須です", "ollamaBaseUrlRequired": "OllamaのベースURLが必要です", "baseUrlRequired": "ベースURLが必要です", "modelDimensionMinValue": "モデルの次元は0より大きくなければなりません", diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index d7b0359cf2e..be96edde5b2 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -78,6 +78,12 @@ "vercelAiGatewayProvider": "Vercel AI Gateway", "vercelAiGatewayApiKeyLabel": "API 키", "vercelAiGatewayApiKeyPlaceholder": "Vercel AI Gateway API 키를 입력하세요", + "bedrockProvider": "Amazon Bedrock", + "bedrockRegionLabel": "AWS 리전", + "bedrockRegionPlaceholder": "us-east-1", + "bedrockProfileLabel": "AWS 프로필", + "bedrockProfilePlaceholder": "default", + "bedrockProfileDescription": "~/.aws/credentials의 AWS 프로필 이름(필수).", "openRouterProvider": "OpenRouter", "openRouterApiKeyLabel": "OpenRouter API 키", "openRouterApiKeyPlaceholder": "OpenRouter API 키를 입력하세요", @@ -145,6 +151,8 @@ "geminiApiKeyRequired": "Gemini API 키가 필요합니다", "mistralApiKeyRequired": "Mistral API 키가 필요합니다", "vercelAiGatewayApiKeyRequired": "Vercel AI Gateway API 키가 필요합니다", + "bedrockRegionRequired": "AWS 리전이 필요합니다", + "bedrockProfileRequired": "AWS 프로필이 필요합니다", "ollamaBaseUrlRequired": "Ollama 기본 URL이 필요합니다", "baseUrlRequired": "기본 URL이 필요합니다", "modelDimensionMinValue": "모델 차원은 0보다 커야 합니다", diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json index ad0f2264b71..61845e0bf4b 100644 --- a/webview-ui/src/i18n/locales/nl/settings.json +++ b/webview-ui/src/i18n/locales/nl/settings.json @@ -75,6 +75,12 @@ "vercelAiGatewayProvider": "Vercel AI Gateway", "vercelAiGatewayApiKeyLabel": "API-sleutel", "vercelAiGatewayApiKeyPlaceholder": "Voer uw Vercel AI Gateway API-sleutel in", + "bedrockProvider": "Amazon Bedrock", + "bedrockRegionLabel": "AWS-regio", + "bedrockRegionPlaceholder": "us-east-1", + "bedrockProfileLabel": "AWS-profiel", + "bedrockProfilePlaceholder": "default", + "bedrockProfileDescription": "AWS-profielnaam uit ~/.aws/credentials (vereist).", "openRouterProvider": "OpenRouter", "openRouterApiKeyLabel": "OpenRouter API-sleutel", "openRouterApiKeyPlaceholder": "Voer uw OpenRouter API-sleutel in", @@ -145,6 +151,8 @@ "geminiApiKeyRequired": "Gemini API-sleutel is vereist", "mistralApiKeyRequired": "Mistral API-sleutel is vereist", "vercelAiGatewayApiKeyRequired": "Vercel AI Gateway API-sleutel is vereist", + "bedrockRegionRequired": "AWS-regio is vereist", + "bedrockProfileRequired": "AWS-profiel is vereist", "ollamaBaseUrlRequired": "Ollama basis-URL is vereist", "baseUrlRequired": "Basis-URL is vereist", "modelDimensionMinValue": "Modelafmeting moet groter zijn dan 0", diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index 37053fb4bf8..f89b76dcaf2 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -78,6 +78,12 @@ "vercelAiGatewayProvider": "Vercel AI Gateway", "vercelAiGatewayApiKeyLabel": "Klucz API", "vercelAiGatewayApiKeyPlaceholder": "Wprowadź swój klucz API Vercel AI Gateway", + "bedrockProvider": "Amazon Bedrock", + "bedrockRegionLabel": "Region AWS", + "bedrockRegionPlaceholder": "us-east-1", + "bedrockProfileLabel": "Profil AWS", + "bedrockProfilePlaceholder": "default", + "bedrockProfileDescription": "Nazwa profilu AWS z ~/.aws/credentials (wymagane).", "openRouterProvider": "OpenRouter", "openRouterApiKeyLabel": "Klucz API OpenRouter", "openRouterApiKeyPlaceholder": "Wprowadź swój klucz API OpenRouter", @@ -145,6 +151,8 @@ "geminiApiKeyRequired": "Wymagany jest klucz API Gemini", "mistralApiKeyRequired": "Klucz API Mistral jest wymagany", "vercelAiGatewayApiKeyRequired": "Klucz API Vercel AI Gateway jest wymagany", + "bedrockRegionRequired": "Region AWS jest wymagany", + "bedrockProfileRequired": "Profil AWS jest wymagany", "ollamaBaseUrlRequired": "Wymagany jest bazowy adres URL Ollama", "baseUrlRequired": "Wymagany jest bazowy adres URL", "modelDimensionMinValue": "Wymiar modelu musi być większy niż 0", diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index d8206816354..183ba03d9f3 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -75,6 +75,12 @@ "vercelAiGatewayProvider": "Vercel AI Gateway", "vercelAiGatewayApiKeyLabel": "Chave de API", "vercelAiGatewayApiKeyPlaceholder": "Digite sua chave de API do Vercel AI Gateway", + "bedrockProvider": "Amazon Bedrock", + "bedrockRegionLabel": "Região da AWS", + "bedrockRegionPlaceholder": "us-east-1", + "bedrockProfileLabel": "Perfil da AWS", + "bedrockProfilePlaceholder": "default", + "bedrockProfileDescription": "Nome do perfil da AWS em ~/.aws/credentials (obrigatório).", "openRouterProvider": "OpenRouter", "openRouterApiKeyLabel": "Chave de API do OpenRouter", "openRouterApiKeyPlaceholder": "Digite sua chave de API do OpenRouter", @@ -145,6 +151,8 @@ "geminiApiKeyRequired": "A chave de API do Gemini é obrigatória", "mistralApiKeyRequired": "A chave de API Mistral é obrigatória", "vercelAiGatewayApiKeyRequired": "A chave de API do Vercel AI Gateway é obrigatória", + "bedrockRegionRequired": "A região da AWS é obrigatória", + "bedrockProfileRequired": "O perfil da AWS é obrigatório", "ollamaBaseUrlRequired": "A URL base do Ollama é obrigatória", "baseUrlRequired": "A URL base é obrigatória", "modelDimensionMinValue": "A dimensão do modelo deve ser maior que 0", diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index 4ebb8c4b0dc..52c1723d9e4 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -75,6 +75,12 @@ "vercelAiGatewayProvider": "Vercel AI Gateway", "vercelAiGatewayApiKeyLabel": "Ключ API", "vercelAiGatewayApiKeyPlaceholder": "Введите свой API-ключ Vercel AI Gateway", + "bedrockProvider": "Amazon Bedrock", + "bedrockRegionLabel": "Регион AWS", + "bedrockRegionPlaceholder": "us-east-1", + "bedrockProfileLabel": "Профиль AWS", + "bedrockProfilePlaceholder": "default", + "bedrockProfileDescription": "Имя профиля AWS из ~/.aws/credentials (обязательно).", "openRouterProvider": "OpenRouter", "openRouterApiKeyLabel": "Ключ API OpenRouter", "openRouterApiKeyPlaceholder": "Введите свой ключ API OpenRouter", @@ -145,6 +151,8 @@ "geminiApiKeyRequired": "Требуется ключ API Gemini", "mistralApiKeyRequired": "Требуется API-ключ Mistral", "vercelAiGatewayApiKeyRequired": "Требуется API-ключ Vercel AI Gateway", + "bedrockRegionRequired": "Требуется регион AWS", + "bedrockProfileRequired": "Требуется профиль AWS", "ollamaBaseUrlRequired": "Требуется базовый URL Ollama", "baseUrlRequired": "Требуется базовый URL", "modelDimensionMinValue": "Размерность модели должна быть больше 0", diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index 71d21cbe586..0f9588ec704 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -78,6 +78,12 @@ "vercelAiGatewayProvider": "Vercel AI Gateway", "vercelAiGatewayApiKeyLabel": "API Anahtarı", "vercelAiGatewayApiKeyPlaceholder": "Vercel AI Gateway API anahtarınızı girin", + "bedrockProvider": "Amazon Bedrock", + "bedrockRegionLabel": "AWS Bölgesi", + "bedrockRegionPlaceholder": "us-east-1", + "bedrockProfileLabel": "AWS Profili", + "bedrockProfilePlaceholder": "default", + "bedrockProfileDescription": "~/.aws/credentials dosyasından AWS profil adı (gerekli).", "openRouterProvider": "OpenRouter", "openRouterApiKeyLabel": "OpenRouter API Anahtarı", "openRouterApiKeyPlaceholder": "OpenRouter API anahtarınızı girin", @@ -145,6 +151,8 @@ "geminiApiKeyRequired": "Gemini API anahtarı gereklidir", "mistralApiKeyRequired": "Mistral API anahtarı gereklidir", "vercelAiGatewayApiKeyRequired": "Vercel AI Gateway API anahtarı gereklidir", + "bedrockRegionRequired": "AWS bölgesi gereklidir", + "bedrockProfileRequired": "AWS profili gereklidir", "ollamaBaseUrlRequired": "Ollama temel URL'si gereklidir", "baseUrlRequired": "Temel URL'si gereklidir", "modelDimensionMinValue": "Model boyutu 0'dan büyük olmalıdır", diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index 23268def152..e34cc216bb7 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -78,6 +78,12 @@ "vercelAiGatewayProvider": "Vercel AI Gateway", "vercelAiGatewayApiKeyLabel": "Khóa API", "vercelAiGatewayApiKeyPlaceholder": "Nhập khóa API Vercel AI Gateway của bạn", + "bedrockProvider": "Amazon Bedrock", + "bedrockRegionLabel": "Vùng AWS", + "bedrockRegionPlaceholder": "us-east-1", + "bedrockProfileLabel": "Hồ sơ AWS", + "bedrockProfilePlaceholder": "default", + "bedrockProfileDescription": "Tên hồ sơ AWS từ ~/.aws/credentials (bắt buộc).", "openRouterProvider": "OpenRouter", "openRouterApiKeyLabel": "Khóa API OpenRouter", "openRouterApiKeyPlaceholder": "Nhập khóa API OpenRouter của bạn", @@ -145,6 +151,8 @@ "geminiApiKeyRequired": "Yêu cầu khóa API Gemini", "mistralApiKeyRequired": "Cần có khóa API của Mistral", "vercelAiGatewayApiKeyRequired": "Cần có khóa API Vercel AI Gateway", + "bedrockRegionRequired": "Vùng AWS là bắt buộc", + "bedrockProfileRequired": "Hồ sơ AWS là bắt buộc", "ollamaBaseUrlRequired": "Yêu cầu URL cơ sở Ollama", "baseUrlRequired": "Yêu cầu URL cơ sở", "modelDimensionMinValue": "Kích thước mô hình phải lớn hơn 0", diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index e4fcd5663a5..4215bb5cefc 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -80,6 +80,12 @@ "vercelAiGatewayProvider": "Vercel AI Gateway", "vercelAiGatewayApiKeyLabel": "API 密钥", "vercelAiGatewayApiKeyPlaceholder": "输入您的 Vercel AI Gateway API 密钥", + "bedrockProvider": "Amazon Bedrock", + "bedrockRegionLabel": "AWS 区域", + "bedrockRegionPlaceholder": "us-east-1", + "bedrockProfileLabel": "AWS 配置文件", + "bedrockProfilePlaceholder": "default", + "bedrockProfileDescription": "来自 ~/.aws/credentials 的 AWS 配置文件名称(必需)。", "openRouterProvider": "OpenRouter", "openRouterApiKeyLabel": "OpenRouter API 密钥", "openRouterApiKeyPlaceholder": "输入您的 OpenRouter API 密钥", @@ -145,6 +151,8 @@ "geminiApiKeyRequired": "需要 Gemini API 密钥", "mistralApiKeyRequired": "需要 Mistral API 密钥", "vercelAiGatewayApiKeyRequired": "需要 Vercel AI Gateway API 密钥", + "bedrockRegionRequired": "AWS 区域为必填项", + "bedrockProfileRequired": "AWS 配置文件为必填项", "ollamaBaseUrlRequired": "需要 Ollama 基础 URL", "baseUrlRequired": "需要基础 URL", "modelDimensionMinValue": "模型维度必须大于 0", diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index 0928791014b..9b2189195f5 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -75,6 +75,12 @@ "vercelAiGatewayProvider": "Vercel AI Gateway", "vercelAiGatewayApiKeyLabel": "API 金鑰", "vercelAiGatewayApiKeyPlaceholder": "輸入您的 Vercel AI Gateway API 金鑰", + "bedrockProvider": "Amazon Bedrock", + "bedrockRegionLabel": "AWS 區域", + "bedrockRegionPlaceholder": "us-east-1", + "bedrockProfileLabel": "AWS 設定檔", + "bedrockProfilePlaceholder": "default", + "bedrockProfileDescription": "來自 ~/.aws/credentials 的 AWS 設定檔名稱(必需)。", "openRouterProvider": "OpenRouter", "openRouterApiKeyLabel": "OpenRouter API 金鑰", "openRouterApiKeyPlaceholder": "輸入您的 OpenRouter API 金鑰", @@ -145,6 +151,8 @@ "geminiApiKeyRequired": "需要 Gemini API 金鑰", "mistralApiKeyRequired": "需要 Mistral API 金鑰", "vercelAiGatewayApiKeyRequired": "需要 Vercel AI Gateway API 金鑰", + "bedrockRegionRequired": "AWS 區域為必填", + "bedrockProfileRequired": "AWS 設定檔為必填", "ollamaBaseUrlRequired": "需要 Ollama 基礎 URL", "baseUrlRequired": "需要基礎 URL", "modelDimensionMinValue": "模型維度必須大於 0", From 885ecf877b84b59ff285dd21dc74ca159bf46b97 Mon Sep 17 00:00:00 2001 From: George Goranov Date: Wed, 26 Nov 2025 13:49:06 +0200 Subject: [PATCH 10/17] Remove leftover code from a debugging session. --- .../src/components/chat/CodeIndexPopover.tsx | 43 +++---------------- 1 file changed, 7 insertions(+), 36 deletions(-) diff --git a/webview-ui/src/components/chat/CodeIndexPopover.tsx b/webview-ui/src/components/chat/CodeIndexPopover.tsx index 1998db3a863..e819380fcf1 100644 --- a/webview-ui/src/components/chat/CodeIndexPopover.tsx +++ b/webview-ui/src/components/chat/CodeIndexPopover.tsx @@ -311,44 +311,15 @@ export const CodeIndexPopover: React.FC = ({ } else if (event.data.type === "codeIndexSettingsSaved") { if (event.data.success) { setSaveStatus("saved") - // Use the settings returned from the backend to update both initial and current settings - // This ensures we have the exact values that were saved - if (event.data.settings) { - const savedSettings = { - codebaseIndexEnabled: event.data.settings.codebaseIndexEnabled ?? true, - codebaseIndexQdrantUrl: event.data.settings.codebaseIndexQdrantUrl || "", - codebaseIndexEmbedderProvider: - event.data.settings.codebaseIndexEmbedderProvider || "openai", - codebaseIndexEmbedderBaseUrl: event.data.settings.codebaseIndexEmbedderBaseUrl || "", - codebaseIndexEmbedderModelId: event.data.settings.codebaseIndexEmbedderModelId || "", - codebaseIndexEmbedderModelDimension: - event.data.settings.codebaseIndexEmbedderModelDimension || undefined, - codebaseIndexSearchMaxResults: - event.data.settings.codebaseIndexSearchMaxResults ?? - CODEBASE_INDEX_DEFAULTS.DEFAULT_SEARCH_RESULTS, - codebaseIndexSearchMinScore: - event.data.settings.codebaseIndexSearchMinScore ?? - CODEBASE_INDEX_DEFAULTS.DEFAULT_SEARCH_MIN_SCORE, - codebaseIndexBedrockRegion: event.data.settings.codebaseIndexBedrockRegion || "", - codebaseIndexBedrockProfile: event.data.settings.codebaseIndexBedrockProfile || "", - codeIndexOpenAiKey: currentSettingsRef.current.codeIndexOpenAiKey, - codeIndexQdrantApiKey: currentSettingsRef.current.codeIndexQdrantApiKey, - codebaseIndexOpenAiCompatibleBaseUrl: - event.data.settings.codebaseIndexOpenAiCompatibleBaseUrl || "", - codebaseIndexOpenAiCompatibleApiKey: - currentSettingsRef.current.codebaseIndexOpenAiCompatibleApiKey, - codebaseIndexGeminiApiKey: currentSettingsRef.current.codebaseIndexGeminiApiKey, - codebaseIndexMistralApiKey: currentSettingsRef.current.codebaseIndexMistralApiKey, - codebaseIndexVercelAiGatewayApiKey: - currentSettingsRef.current.codebaseIndexVercelAiGatewayApiKey, - } - - setInitialSettings(savedSettings) - setCurrentSettings(savedSettings) - } - + // Update initial settings to match current settings after successful save + // This ensures hasUnsavedChanges becomes false + const savedSettings = { ...currentSettingsRef.current } + setInitialSettings(savedSettings) + // Also update current settings to maintain consistency + setCurrentSettings(savedSettings) // Request secret status to ensure we have the latest state // This is important to maintain placeholder display after save + vscode.postMessage({ type: "requestCodeIndexSecretStatus" }) setSaveStatus("idle") From 840d95aa78b52b549595003510867846fc029ac3 Mon Sep 17 00:00:00 2001 From: George Goranov Date: Wed, 26 Nov 2025 14:02:07 +0200 Subject: [PATCH 11/17] fix: add bedrock to codebaseIndexModelsSchema and update brace-expansion override - Add bedrock provider to codebaseIndexModelsSchema type definition to fix empty model dropdown in UI - Update pnpm override for brace-expansion from '>=2.0.2' to '^2.0.2' to resolve ESM/CommonJS compatibility issues --- package.json | 2 +- packages/types/src/codebase-index.ts | 1 + pnpm-lock.yaml | 28 +++++++++++++--------------- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 793658b459f..0f3c3b7ba04 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "tar-fs": ">=3.1.1", "esbuild": ">=0.25.0", "undici": ">=5.29.0", - "brace-expansion": ">=2.0.2", + "brace-expansion": "^2.0.2", "form-data": ">=4.0.4", "bluebird": ">=3.7.2", "glob": ">=11.1.0" diff --git a/packages/types/src/codebase-index.ts b/packages/types/src/codebase-index.ts index af9357be5b2..8673e98e7d6 100644 --- a/packages/types/src/codebase-index.ts +++ b/packages/types/src/codebase-index.ts @@ -64,6 +64,7 @@ export const codebaseIndexModelsSchema = z.object({ mistral: z.record(z.string(), z.object({ dimension: z.number() })).optional(), "vercel-ai-gateway": z.record(z.string(), z.object({ dimension: z.number() })).optional(), openrouter: z.record(z.string(), z.object({ dimension: z.number() })).optional(), + bedrock: z.record(z.string(), z.object({ dimension: z.number() })).optional(), }) export type CodebaseIndexModels = z.infer diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 971fcd4cc2a..ab40f864404 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,7 +8,7 @@ overrides: tar-fs: '>=3.1.1' esbuild: '>=0.25.0' undici: '>=5.29.0' - brace-expansion: '>=2.0.2' + brace-expansion: ^2.0.2 form-data: '>=4.0.4' bluebird: '>=3.7.2' glob: '>=11.1.0' @@ -4574,9 +4574,8 @@ packages: bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} - balanced-match@3.0.1: - resolution: {integrity: sha512-vjtV3hiLqYDNRoiAv0zC4QaGAMPomEoq83PRmYIofPswwZurCeWR5LByXm7SyoL0Zh5+2z0+HC7jG8gSZJUh0w==} - engines: {node: '>= 16'} + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} bare-events@2.5.4: resolution: {integrity: sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==} @@ -4659,9 +4658,8 @@ packages: bowser@2.11.0: resolution: {integrity: sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==} - brace-expansion@4.0.1: - resolution: {integrity: sha512-YClrbvTCXGe70pU2JiEiPLYXO9gQkyxYeKpJIQHVS/gOs6EWMQP2RYBwjFLNT322Ji8TOC3IMPfsYCedNpzKfA==} - engines: {node: '>= 18'} + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} @@ -14054,7 +14052,7 @@ snapshots: sirv: 3.0.1 tinyglobby: 0.2.14 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@20.17.50)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.2.1)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) '@vitest/utils@3.2.4': dependencies: @@ -14398,7 +14396,7 @@ snapshots: bail@2.0.2: {} - balanced-match@3.0.1: {} + balanced-match@1.0.2: {} bare-events@2.5.4: optional: true @@ -14485,9 +14483,9 @@ snapshots: bowser@2.11.0: {} - brace-expansion@4.0.1: + brace-expansion@2.0.2: dependencies: - balanced-match: 3.0.1 + balanced-match: 1.0.2 braces@3.0.3: dependencies: @@ -17968,7 +17966,7 @@ snapshots: minimatch@10.0.1: dependencies: - brace-expansion: 4.0.1 + brace-expansion: 2.0.2 minimatch@10.1.1: dependencies: @@ -17976,15 +17974,15 @@ snapshots: minimatch@3.1.2: dependencies: - brace-expansion: 4.0.1 + brace-expansion: 2.0.2 minimatch@5.1.6: dependencies: - brace-expansion: 4.0.1 + brace-expansion: 2.0.2 minimatch@9.0.5: dependencies: - brace-expansion: 4.0.1 + brace-expansion: 2.0.2 minimist@1.2.8: {} From b30fc96b91ffe4ce9f69e084dfbac8d329cccca4 Mon Sep 17 00:00:00 2001 From: Smartsheet-JB-Brown Date: Tue, 25 Nov 2025 14:36:32 -0800 Subject: [PATCH 12/17] Improvements to AWS Bedrock embeddings support - Enhanced bedrock.ts embedder implementation - Added comprehensive test coverage in bedrock.spec.ts - Updated config-manager.ts for better Bedrock configuration handling - Improved service-factory.ts integration - Updated embeddingModels.ts with Bedrock models - Enhanced CodeIndexPopover.tsx UI for Bedrock options - Added auto-populate test for CodeIndexPopover - Updated pnpm-lock.yaml dependencies --- pnpm-lock.yaml | 2 +- src/services/code-index/config-manager.ts | 13 +- .../embedders/__tests__/bedrock.spec.ts | 141 +++++++- src/services/code-index/embedders/bedrock.ts | 55 ++- src/services/code-index/service-factory.ts | 4 +- src/shared/embeddingModels.ts | 2 + .../src/components/chat/CodeIndexPopover.tsx | 36 +- .../CodeIndexPopover.auto-populate.spec.tsx | 332 ++++++++++++++++++ 8 files changed, 557 insertions(+), 28 deletions(-) create mode 100644 webview-ui/src/components/chat/__tests__/CodeIndexPopover.auto-populate.spec.tsx diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ab40f864404..6558ec50221 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14052,7 +14052,7 @@ snapshots: sirv: 3.0.1 tinyglobby: 0.2.14 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.2.1)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@20.17.57)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) '@vitest/utils@3.2.4': dependencies: diff --git a/src/services/code-index/config-manager.ts b/src/services/code-index/config-manager.ts index 79f409eb505..f3a2a00f5f5 100644 --- a/src/services/code-index/config-manager.ts +++ b/src/services/code-index/config-manager.ts @@ -143,10 +143,10 @@ export class CodeIndexConfigManager { this.geminiOptions = geminiApiKey ? { apiKey: geminiApiKey } : undefined this.mistralOptions = mistralApiKey ? { apiKey: mistralApiKey } : undefined this.vercelAiGatewayOptions = vercelAiGatewayApiKey ? { apiKey: vercelAiGatewayApiKey } : undefined - // Set bedrockOptions only if both region and profile are provided - this.bedrockOptions = - bedrockRegion && bedrockProfile ? { region: bedrockRegion, profile: bedrockProfile } : undefined - this.openRouterOptions = openRouterApiKey ? { apiKey: openRouterApiKey } : undefined + // Set bedrockOptions if region is provided (profile is optional) + this.bedrockOptions = bedrockRegion + ? { region: bedrockRegion, profile: bedrockProfile || undefined } + : undefined } /** @@ -260,11 +260,10 @@ export class CodeIndexConfigManager { const isConfigured = !!(apiKey && qdrantUrl) return isConfigured } else if (this.embedderProvider === "bedrock") { - // Both region and profile are required for Bedrock + // Only region is required for Bedrock (profile is optional) const region = this.bedrockOptions?.region - const profile = this.bedrockOptions?.profile const qdrantUrl = this.qdrantUrl - const isConfigured = !!(region && profile && qdrantUrl) + const isConfigured = !!(region && qdrantUrl) return isConfigured } else if (this.embedderProvider === "openrouter") { const apiKey = this.openRouterOptions?.apiKey diff --git a/src/services/code-index/embedders/__tests__/bedrock.spec.ts b/src/services/code-index/embedders/__tests__/bedrock.spec.ts index 80542d8ef9a..de4b3b15bb6 100644 --- a/src/services/code-index/embedders/__tests__/bedrock.spec.ts +++ b/src/services/code-index/embedders/__tests__/bedrock.spec.ts @@ -88,12 +88,9 @@ describe("BedrockEmbedder", () => { expect(embedder.embedderInfo.name).toBe("bedrock") }) - it("should require both region and profile", () => { + it("should require region", () => { expect(() => new BedrockEmbedder("", "profile", "model")).toThrow( - "Both region and profile are required for Amazon Bedrock embedder", - ) - expect(() => new BedrockEmbedder("us-east-1", "", "model")).toThrow( - "Both region and profile are required for Amazon Bedrock embedder", + "Region is required for AWS Bedrock embedder", ) }) @@ -202,6 +199,140 @@ describe("BedrockEmbedder", () => { }) }) + it("should create embeddings with Nova multimodal model", async () => { + const novaMultimodalEmbedder = new BedrockEmbedder( + "us-east-1", + "test-profile", + "amazon.nova-2-multimodal-embeddings-v1:0", + ) + const testTexts = ["Hello world"] + const mockResponse = { + body: new TextEncoder().encode( + JSON.stringify({ + embeddings: [ + { + embedding: [0.1, 0.2, 0.3], + }, + ], + inputTextTokenCount: 2, + }), + ), + } + mockSend.mockResolvedValue(mockResponse) + + const result = await novaMultimodalEmbedder.createEmbeddings(testTexts) + + expect(mockSend).toHaveBeenCalled() + const command = mockSend.mock.calls[0][0] as any + expect(command.input.modelId).toBe("amazon.nova-2-multimodal-embeddings-v1:0") + const bodyStr = + typeof command.input.body === "string" + ? command.input.body + : new TextDecoder().decode(command.input.body as Uint8Array) + // Nova multimodal embeddings use a task-based format with nested text object + expect(JSON.parse(bodyStr || "{}")).toEqual({ + taskType: "SINGLE_EMBEDDING", + singleEmbeddingParams: { + embeddingPurpose: "GENERIC_INDEX", + embeddingDimension: 1024, + text: { + truncationMode: "END", + value: "Hello world", + }, + }, + }) + + expect(result).toEqual({ + embeddings: [[0.1, 0.2, 0.3]], + usage: { promptTokens: 2, totalTokens: 2 }, + }) + }) + + it("should handle Nova multimodal model with multiple texts", async () => { + const novaMultimodalEmbedder = new BedrockEmbedder( + "us-east-1", + "test-profile", + "amazon.nova-2-multimodal-embeddings-v1:0", + ) + const testTexts = ["Hello world", "Another text"] + const mockResponses = [ + { + body: new TextEncoder().encode( + JSON.stringify({ + embeddings: [ + { + embedding: [0.1, 0.2, 0.3], + }, + ], + inputTextTokenCount: 2, + }), + ), + }, + { + body: new TextEncoder().encode( + JSON.stringify({ + embeddings: [ + { + embedding: [0.4, 0.5, 0.6], + }, + ], + inputTextTokenCount: 3, + }), + ), + }, + ] + + mockSend.mockResolvedValueOnce(mockResponses[0]).mockResolvedValueOnce(mockResponses[1]) + + const result = await novaMultimodalEmbedder.createEmbeddings(testTexts) + + expect(mockSend).toHaveBeenCalledTimes(2) + + // Verify the request format for both texts + const firstCommand = mockSend.mock.calls[0][0] as any + const firstBodyStr = + typeof firstCommand.input.body === "string" + ? firstCommand.input.body + : new TextDecoder().decode(firstCommand.input.body as Uint8Array) + // Nova multimodal embeddings use a task-based format with nested text object + expect(JSON.parse(firstBodyStr || "{}")).toEqual({ + taskType: "SINGLE_EMBEDDING", + singleEmbeddingParams: { + embeddingPurpose: "GENERIC_INDEX", + embeddingDimension: 1024, + text: { + truncationMode: "END", + value: "Hello world", + }, + }, + }) + + const secondCommand = mockSend.mock.calls[1][0] as any + const secondBodyStr = + typeof secondCommand.input.body === "string" + ? secondCommand.input.body + : new TextDecoder().decode(secondCommand.input.body as Uint8Array) + expect(JSON.parse(secondBodyStr || "{}")).toEqual({ + taskType: "SINGLE_EMBEDDING", + singleEmbeddingParams: { + embeddingPurpose: "GENERIC_INDEX", + embeddingDimension: 1024, + text: { + truncationMode: "END", + value: "Another text", + }, + }, + }) + + expect(result).toEqual({ + embeddings: [ + [0.1, 0.2, 0.3], + [0.4, 0.5, 0.6], + ], + usage: { promptTokens: 5, totalTokens: 5 }, + }) + }) + it("should use custom model when provided", async () => { const testTexts = ["Hello world"] const customModel = "amazon.titan-embed-text-v1" diff --git a/src/services/code-index/embedders/bedrock.ts b/src/services/code-index/embedders/bedrock.ts index cb2e73fc50c..5182b9d2095 100644 --- a/src/services/code-index/embedders/bedrock.ts +++ b/src/services/code-index/embedders/bedrock.ts @@ -23,20 +23,21 @@ export class BedrockEmbedder implements IEmbedder { /** * Creates a new Amazon Bedrock embedder * @param region AWS region for Bedrock service (required) - * @param profile AWS profile name for credentials (required) + * @param profile AWS profile name for credentials (optional - uses default credential chain if not provided) * @param modelId Optional model ID override */ constructor( private readonly region: string, - private readonly profile: string, + private readonly profile?: string, modelId?: string, ) { - if (!region || !profile) { - throw new Error("Both region and profile are required for Amazon Bedrock embedder") + if (!region) { + throw new Error("Region is required for AWS Bedrock embedder") } - // Initialize the Bedrock client with credentials from the specified profile - const credentials = fromIni({ profile: this.profile }) + // Initialize the Bedrock client with credentials + // If profile is specified, use it; otherwise use default credential chain + const credentials = this.profile ? fromIni({ profile: this.profile }) : fromEnv() this.bedrockClient = new BedrockRuntimeClient({ region: this.region, @@ -188,7 +189,22 @@ export class BedrockEmbedder implements IEmbedder { let modelId = model // Prepare the request body based on the model - if (model.startsWith("amazon.titan-embed")) { + if (model.startsWith("amazon.nova-2-multimodal")) { + // Nova multimodal embeddings use a task-based format with embeddingParams + // Reference: https://docs.aws.amazon.com/bedrock/latest/userguide/embeddings-nova.html + requestBody = { + taskType: "SINGLE_EMBEDDING", + singleEmbeddingParams: { + embeddingPurpose: "GENERIC_INDEX", + embeddingDimension: 1024, // Nova supports 1024 or 3072 + text: { + truncationMode: "END", + value: text, + }, + }, + } + console.log(`[BedrockEmbedder] Nova multimodal request for model ${model}:`, JSON.stringify(requestBody)) + } else if (model.startsWith("amazon.titan-embed")) { requestBody = { inputText: text, } @@ -211,14 +227,35 @@ export class BedrockEmbedder implements IEmbedder { accept: "application/json", } + console.log(`[BedrockEmbedder] Sending request to model ${modelId}`) + console.log(`[BedrockEmbedder] Request body:`, requestBody) + const command = new InvokeModelCommand(params) - const response = await this.bedrockClient.send(command) + + let response + try { + response = await this.bedrockClient.send(command) + } catch (error: any) { + console.error(`[BedrockEmbedder] API error for model ${modelId}:`, error) + console.error(`[BedrockEmbedder] Error name:`, error.name) + console.error(`[BedrockEmbedder] Error message:`, error.message) + console.error(`[BedrockEmbedder] Error details:`, JSON.stringify(error, null, 2)) + throw error + } // Parse the response const responseBody = JSON.parse(new TextDecoder().decode(response.body)) + console.log(`[BedrockEmbedder] Response for model ${modelId}:`, responseBody) // Extract embedding based on model type - if (model.startsWith("amazon.titan-embed")) { + if (model.startsWith("amazon.nova-2-multimodal")) { + // Nova multimodal returns { embeddings: [{ embedding: [...] }] } + // Reference: AWS Bedrock documentation + return { + embedding: responseBody.embeddings?.[0]?.embedding || responseBody.embedding, + inputTextTokenCount: responseBody.inputTextTokenCount, + } + } else if (model.startsWith("amazon.titan-embed")) { return { embedding: responseBody.embedding, inputTextTokenCount: responseBody.inputTextTokenCount, diff --git a/src/services/code-index/service-factory.ts b/src/services/code-index/service-factory.ts index 45cffb87bb6..f7ef573c4fa 100644 --- a/src/services/code-index/service-factory.ts +++ b/src/services/code-index/service-factory.ts @@ -82,8 +82,8 @@ export class CodeIndexServiceFactory { } return new VercelAiGatewayEmbedder(config.vercelAiGatewayOptions.apiKey, config.modelId) } else if (provider === "bedrock") { - // Both region and profile are required for Bedrock - if (!config.bedrockOptions?.region || !config.bedrockOptions?.profile) { + // Only region is required for Bedrock (profile is optional) + if (!config.bedrockOptions?.region) { throw new Error(t("embeddings:serviceFactory.bedrockConfigMissing")) } return new BedrockEmbedder(config.bedrockOptions.region, config.bedrockOptions.profile, config.modelId) diff --git a/src/shared/embeddingModels.ts b/src/shared/embeddingModels.ts index cf70acc6fc9..1c88e5b083c 100644 --- a/src/shared/embeddingModels.ts +++ b/src/shared/embeddingModels.ts @@ -83,6 +83,8 @@ export const EMBEDDING_MODEL_PROFILES: EmbeddingModelProfiles = { "amazon.titan-embed-text-v1": { dimension: 1536, scoreThreshold: 0.4 }, "amazon.titan-embed-text-v2:0": { dimension: 1024, scoreThreshold: 0.4 }, "amazon.titan-embed-image-v1": { dimension: 1024, scoreThreshold: 0.4 }, + // Amazon Nova Embed models + "amazon.nova-2-multimodal-embeddings-v1:0": { dimension: 1024, scoreThreshold: 0.4 }, // Cohere models available through Bedrock "cohere.embed-english-v3": { dimension: 1024, scoreThreshold: 0.4 }, "cohere.embed-multilingual-v3": { dimension: 1024, scoreThreshold: 0.4 }, diff --git a/webview-ui/src/components/chat/CodeIndexPopover.tsx b/webview-ui/src/components/chat/CodeIndexPopover.tsx index e819380fcf1..177b7a99e0e 100644 --- a/webview-ui/src/components/chat/CodeIndexPopover.tsx +++ b/webview-ui/src/components/chat/CodeIndexPopover.tsx @@ -158,9 +158,7 @@ const createValidationSchema = (provider: EmbedderProvider, t: any) => { case "bedrock": return baseSchema.extend({ codebaseIndexBedrockRegion: z.string().min(1, t("settings:codeIndex.validation.bedrockRegionRequired")), - codebaseIndexBedrockProfile: z - .string() - .min(1, t("settings:codeIndex.validation.bedrockProfileRequired")), + codebaseIndexBedrockProfile: z.string().optional(), codebaseIndexEmbedderModelId: z .string() .min(1, t("settings:codeIndex.validation.modelSelectionRequired")), @@ -187,7 +185,7 @@ export const CodeIndexPopover: React.FC = ({ }) => { const SECRET_PLACEHOLDER = "••••••••••••••••" const { t } = useAppTranslation() - const { codebaseIndexConfig, codebaseIndexModels, cwd } = useExtensionState() + const { codebaseIndexConfig, codebaseIndexModels, cwd, apiConfiguration } = useExtensionState() const [open, setOpen] = useState(false) const [isAdvancedSettingsOpen, setIsAdvancedSettingsOpen] = useState(false) const [isSetupSettingsOpen, setIsSetupSettingsOpen] = useState(false) @@ -689,6 +687,33 @@ export const CodeIndexPopover: React.FC = ({ updateSetting("codebaseIndexEmbedderProvider", value) // Clear model selection when switching providers updateSetting("codebaseIndexEmbedderModelId", "") + + // Auto-populate Region and Profile when switching to Bedrock + // if the main API provider is also configured for Bedrock + if ( + value === "bedrock" && + apiConfiguration?.apiProvider === "bedrock" + ) { + // Only populate if currently empty + if ( + !currentSettings.codebaseIndexBedrockRegion && + apiConfiguration.awsRegion + ) { + updateSetting( + "codebaseIndexBedrockRegion", + apiConfiguration.awsRegion, + ) + } + if ( + !currentSettings.codebaseIndexBedrockProfile && + apiConfiguration.awsProfile + ) { + updateSetting( + "codebaseIndexBedrockProfile", + apiConfiguration.awsProfile, + ) + } + } }}> @@ -1206,6 +1231,9 @@ export const CodeIndexPopover: React.FC = ({
{ + /** + * Test 1: Happy Path - Auto-population works + * Main API provider is Bedrock with region "us-west-2" and profile "my-profile" + * Code indexing fields are empty + * User switches provider to "bedrock" + * Expected: updateSetting is called to populate Region and Profile + */ + test("auto-populates Region and Profile when switching to Bedrock and main API is Bedrock", () => { + const mockUpdateSetting = vi.fn() + const currentSettings = { + codebaseIndexBedrockRegion: "", + codebaseIndexBedrockProfile: "", + } + const apiConfiguration = { + apiProvider: "bedrock", + awsRegion: "us-west-2", + awsProfile: "my-profile", + } + + // Simulate the onValueChange logic from lines 737-752 + const value = "bedrock" + + // Clear model selection + mockUpdateSetting("codebaseIndexEmbedderModelId", "") + + // Auto-populate Region and Profile when switching to Bedrock + if (value === "bedrock" && apiConfiguration?.apiProvider === "bedrock") { + if (!currentSettings.codebaseIndexBedrockRegion && apiConfiguration.awsRegion) { + mockUpdateSetting("codebaseIndexBedrockRegion", apiConfiguration.awsRegion) + } + if (!currentSettings.codebaseIndexBedrockProfile && apiConfiguration.awsProfile) { + mockUpdateSetting("codebaseIndexBedrockProfile", apiConfiguration.awsProfile) + } + } + + // Verify updateSetting was called correctly + expect(mockUpdateSetting).toHaveBeenCalledWith("codebaseIndexEmbedderModelId", "") + expect(mockUpdateSetting).toHaveBeenCalledWith("codebaseIndexBedrockRegion", "us-west-2") + expect(mockUpdateSetting).toHaveBeenCalledWith("codebaseIndexBedrockProfile", "my-profile") + expect(mockUpdateSetting).toHaveBeenCalledTimes(3) + }) + + /** + * Test 2: Main API is not Bedrock + * Main API provider is "openai" (not Bedrock) + * User switches code indexing provider to "bedrock" + * Expected: Only model is cleared, no auto-population + */ + test("does not auto-populate when main API provider is not Bedrock", () => { + const mockUpdateSetting = vi.fn() + const currentSettings = { + codebaseIndexBedrockRegion: "", + codebaseIndexBedrockProfile: "", + } + const apiConfiguration: TestApiConfiguration = { + apiProvider: "openai", + apiKey: "test-key", + } + + // Simulate the onValueChange logic + const value = "bedrock" + + mockUpdateSetting("codebaseIndexEmbedderModelId", "") + + if (value === "bedrock" && apiConfiguration?.apiProvider === "bedrock") { + if (!currentSettings.codebaseIndexBedrockRegion && apiConfiguration.awsRegion) { + mockUpdateSetting("codebaseIndexBedrockRegion", apiConfiguration.awsRegion) + } + if (!currentSettings.codebaseIndexBedrockProfile && apiConfiguration.awsProfile) { + mockUpdateSetting("codebaseIndexBedrockProfile", apiConfiguration.awsProfile) + } + } + + // Verify only model was cleared, no auto-population + expect(mockUpdateSetting).toHaveBeenCalledWith("codebaseIndexEmbedderModelId", "") + expect(mockUpdateSetting).toHaveBeenCalledTimes(1) + expect(mockUpdateSetting).not.toHaveBeenCalledWith("codebaseIndexBedrockRegion", expect.anything()) + expect(mockUpdateSetting).not.toHaveBeenCalledWith("codebaseIndexBedrockProfile", expect.anything()) + }) + + /** + * Test 3: Existing values not overwritten + * Code indexing already has Region "eu-west-1" configured + * Main API has Region "us-west-2" + * User switches provider to "bedrock" + * Expected: Region is NOT updated (existing value preserved) + */ + test("does not overwrite existing Region value when switching to Bedrock", () => { + const mockUpdateSetting = vi.fn() + const currentSettings = { + codebaseIndexBedrockRegion: "eu-west-1", + codebaseIndexBedrockProfile: "", + } + const apiConfiguration = { + apiProvider: "bedrock", + awsRegion: "us-west-2", + awsProfile: "default", + } + + // Simulate the onValueChange logic + const value = "bedrock" + + mockUpdateSetting("codebaseIndexEmbedderModelId", "") + + if (value === "bedrock" && apiConfiguration?.apiProvider === "bedrock") { + if (!currentSettings.codebaseIndexBedrockRegion && apiConfiguration.awsRegion) { + mockUpdateSetting("codebaseIndexBedrockRegion", apiConfiguration.awsRegion) + } + if (!currentSettings.codebaseIndexBedrockProfile && apiConfiguration.awsProfile) { + mockUpdateSetting("codebaseIndexBedrockProfile", apiConfiguration.awsProfile) + } + } + + // Verify Region was NOT updated (it already had a value) + expect(mockUpdateSetting).toHaveBeenCalledWith("codebaseIndexEmbedderModelId", "") + expect(mockUpdateSetting).toHaveBeenCalledWith("codebaseIndexBedrockProfile", "default") + expect(mockUpdateSetting).not.toHaveBeenCalledWith("codebaseIndexBedrockRegion", expect.anything()) + expect(mockUpdateSetting).toHaveBeenCalledTimes(2) + }) + + /** + * Test 4: Partial population + * Main API has Region but no Profile + * Code indexing fields are empty + * User switches to "bedrock" + * Expected: Only Region is populated, Profile is not + */ + test("only populates Region when Profile is not configured in main API", () => { + const mockUpdateSetting = vi.fn() + const currentSettings = { + codebaseIndexBedrockRegion: "", + codebaseIndexBedrockProfile: "", + } + const apiConfiguration: TestApiConfiguration = { + apiProvider: "bedrock", + awsRegion: "ap-southeast-1", + // No awsProfile configured + } + + // Simulate the onValueChange logic + const value = "bedrock" + + mockUpdateSetting("codebaseIndexEmbedderModelId", "") + + if (value === "bedrock" && apiConfiguration?.apiProvider === "bedrock") { + if (!currentSettings.codebaseIndexBedrockRegion && apiConfiguration.awsRegion) { + mockUpdateSetting("codebaseIndexBedrockRegion", apiConfiguration.awsRegion) + } + if (!currentSettings.codebaseIndexBedrockProfile && apiConfiguration.awsProfile) { + mockUpdateSetting("codebaseIndexBedrockProfile", apiConfiguration.awsProfile) + } + } + + // Verify only Region was populated + expect(mockUpdateSetting).toHaveBeenCalledWith("codebaseIndexEmbedderModelId", "") + expect(mockUpdateSetting).toHaveBeenCalledWith("codebaseIndexBedrockRegion", "ap-southeast-1") + expect(mockUpdateSetting).not.toHaveBeenCalledWith("codebaseIndexBedrockProfile", expect.anything()) + expect(mockUpdateSetting).toHaveBeenCalledTimes(2) + }) + + /** + * Test 5: Empty main API config + * Main API provider is Bedrock but has no region/profile configured + * User switches code indexing to "bedrock" + * Expected: No auto-population (nothing to populate from) + */ + test("does not populate when main API Bedrock config is empty", () => { + const mockUpdateSetting = vi.fn() + const currentSettings = { + codebaseIndexBedrockRegion: "", + codebaseIndexBedrockProfile: "", + } + const apiConfiguration: TestApiConfiguration = { + apiProvider: "bedrock", + // No awsRegion or awsProfile configured + } + + // Simulate the onValueChange logic + const value = "bedrock" + + mockUpdateSetting("codebaseIndexEmbedderModelId", "") + + if (value === "bedrock" && apiConfiguration?.apiProvider === "bedrock") { + if (!currentSettings.codebaseIndexBedrockRegion && apiConfiguration.awsRegion) { + mockUpdateSetting("codebaseIndexBedrockRegion", apiConfiguration.awsRegion) + } + if (!currentSettings.codebaseIndexBedrockProfile && apiConfiguration.awsProfile) { + mockUpdateSetting("codebaseIndexBedrockProfile", apiConfiguration.awsProfile) + } + } + + // Verify only model was cleared, no auto-population + expect(mockUpdateSetting).toHaveBeenCalledWith("codebaseIndexEmbedderModelId", "") + expect(mockUpdateSetting).toHaveBeenCalledTimes(1) + expect(mockUpdateSetting).not.toHaveBeenCalledWith("codebaseIndexBedrockRegion", expect.anything()) + expect(mockUpdateSetting).not.toHaveBeenCalledWith("codebaseIndexBedrockProfile", expect.anything()) + }) + + /** + * Test 6: Verify Profile can be empty while Region is populated + * This tests that auto-population handles undefined/null Profile correctly + */ + test("handles undefined Profile in main API config gracefully", () => { + const mockUpdateSetting = vi.fn() + const currentSettings = { + codebaseIndexBedrockRegion: "", + codebaseIndexBedrockProfile: "", + } + const apiConfiguration = { + apiProvider: "bedrock", + awsRegion: "us-east-1", + awsProfile: undefined, // Explicitly undefined + } + + // Simulate the onValueChange logic + const value = "bedrock" + + mockUpdateSetting("codebaseIndexEmbedderModelId", "") + + if (value === "bedrock" && apiConfiguration?.apiProvider === "bedrock") { + if (!currentSettings.codebaseIndexBedrockRegion && apiConfiguration.awsRegion) { + mockUpdateSetting("codebaseIndexBedrockRegion", apiConfiguration.awsRegion) + } + if (!currentSettings.codebaseIndexBedrockProfile && apiConfiguration.awsProfile) { + mockUpdateSetting("codebaseIndexBedrockProfile", apiConfiguration.awsProfile) + } + } + + // Verify only Region was populated (Profile is undefined) + expect(mockUpdateSetting).toHaveBeenCalledWith("codebaseIndexEmbedderModelId", "") + expect(mockUpdateSetting).toHaveBeenCalledWith("codebaseIndexBedrockRegion", "us-east-1") + expect(mockUpdateSetting).not.toHaveBeenCalledWith("codebaseIndexBedrockProfile", expect.anything()) + expect(mockUpdateSetting).toHaveBeenCalledTimes(2) + }) + + /** + * Test 7: Does not populate when switching TO other providers + * This ensures the feature only works when switching TO Bedrock specifically + */ + test("does not trigger auto-population when switching to non-Bedrock provider", () => { + const mockUpdateSetting = vi.fn() + const currentSettings = { + codebaseIndexBedrockRegion: "", + codebaseIndexBedrockProfile: "", + } + const apiConfiguration = { + apiProvider: "bedrock", + awsRegion: "us-west-2", + awsProfile: "my-profile", + } + + // Simulate switching to openai instead of bedrock + const value: string = "openai" + + mockUpdateSetting("codebaseIndexEmbedderModelId", "") + + // The condition intentionally won't match since value is "openai" + if (value === "bedrock" && apiConfiguration?.apiProvider === "bedrock") { + if (!currentSettings.codebaseIndexBedrockRegion && apiConfiguration.awsRegion) { + mockUpdateSetting("codebaseIndexBedrockRegion", apiConfiguration.awsRegion) + } + if (!currentSettings.codebaseIndexBedrockProfile && apiConfiguration.awsProfile) { + mockUpdateSetting("codebaseIndexBedrockProfile", apiConfiguration.awsProfile) + } + } + + // Verify only model was cleared, no auto-population + expect(mockUpdateSetting).toHaveBeenCalledWith("codebaseIndexEmbedderModelId", "") + expect(mockUpdateSetting).toHaveBeenCalledTimes(1) + expect(mockUpdateSetting).not.toHaveBeenCalledWith("codebaseIndexBedrockRegion", expect.anything()) + expect(mockUpdateSetting).not.toHaveBeenCalledWith("codebaseIndexBedrockProfile", expect.anything()) + }) + + /** + * Test 8: Both fields have existing values + * Neither field should be auto-populated if both already have values + */ + test("does not overwrite when both Region and Profile already have values", () => { + const mockUpdateSetting = vi.fn() + const currentSettings = { + codebaseIndexBedrockRegion: "eu-central-1", + codebaseIndexBedrockProfile: "production", + } + const apiConfiguration = { + apiProvider: "bedrock", + awsRegion: "us-west-2", + awsProfile: "default", + } + + // Simulate the onValueChange logic + const value = "bedrock" + + mockUpdateSetting("codebaseIndexEmbedderModelId", "") + + if (value === "bedrock" && apiConfiguration?.apiProvider === "bedrock") { + if (!currentSettings.codebaseIndexBedrockRegion && apiConfiguration.awsRegion) { + mockUpdateSetting("codebaseIndexBedrockRegion", apiConfiguration.awsRegion) + } + if (!currentSettings.codebaseIndexBedrockProfile && apiConfiguration.awsProfile) { + mockUpdateSetting("codebaseIndexBedrockProfile", apiConfiguration.awsProfile) + } + } + + // Verify neither field was updated (both already had values) + expect(mockUpdateSetting).toHaveBeenCalledWith("codebaseIndexEmbedderModelId", "") + expect(mockUpdateSetting).not.toHaveBeenCalledWith("codebaseIndexBedrockRegion", expect.anything()) + expect(mockUpdateSetting).not.toHaveBeenCalledWith("codebaseIndexBedrockProfile", expect.anything()) + expect(mockUpdateSetting).toHaveBeenCalledTimes(1) + }) +}) From 70b7e2dffb8e6a58dff3698377913f4bf005c852 Mon Sep 17 00:00:00 2001 From: George Goranov Date: Wed, 26 Nov 2025 14:26:51 +0200 Subject: [PATCH 13/17] Restore openrouter config --- src/services/code-index/config-manager.ts | 1 + src/shared/embeddingModels.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/services/code-index/config-manager.ts b/src/services/code-index/config-manager.ts index f3a2a00f5f5..b911a09d42d 100644 --- a/src/services/code-index/config-manager.ts +++ b/src/services/code-index/config-manager.ts @@ -143,6 +143,7 @@ export class CodeIndexConfigManager { this.geminiOptions = geminiApiKey ? { apiKey: geminiApiKey } : undefined this.mistralOptions = mistralApiKey ? { apiKey: mistralApiKey } : undefined this.vercelAiGatewayOptions = vercelAiGatewayApiKey ? { apiKey: vercelAiGatewayApiKey } : undefined + this.openRouterOptions = openRouterApiKey ? { apiKey: openRouterApiKey } : undefined // Set bedrockOptions if region is provided (profile is optional) this.bedrockOptions = bedrockRegion ? { region: bedrockRegion, profile: bedrockProfile || undefined } diff --git a/src/shared/embeddingModels.ts b/src/shared/embeddingModels.ts index 1c88e5b083c..781a4e46560 100644 --- a/src/shared/embeddingModels.ts +++ b/src/shared/embeddingModels.ts @@ -10,7 +10,7 @@ export type EmbedderProvider = | "mistral" | "vercel-ai-gateway" | "bedrock" - | "openrouter" + | "openrouter" // Add other providers as needed export interface EmbeddingModelProfile { dimension: number From 28479e3747d74c17455bc834c36306c8699b24aa Mon Sep 17 00:00:00 2001 From: George Goranov Date: Wed, 26 Nov 2025 14:27:14 +0200 Subject: [PATCH 14/17] Remove debug log --- src/services/code-index/embedders/bedrock.ts | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/services/code-index/embedders/bedrock.ts b/src/services/code-index/embedders/bedrock.ts index 5182b9d2095..2430b465dc8 100644 --- a/src/services/code-index/embedders/bedrock.ts +++ b/src/services/code-index/embedders/bedrock.ts @@ -203,7 +203,6 @@ export class BedrockEmbedder implements IEmbedder { }, }, } - console.log(`[BedrockEmbedder] Nova multimodal request for model ${model}:`, JSON.stringify(requestBody)) } else if (model.startsWith("amazon.titan-embed")) { requestBody = { inputText: text, @@ -227,25 +226,12 @@ export class BedrockEmbedder implements IEmbedder { accept: "application/json", } - console.log(`[BedrockEmbedder] Sending request to model ${modelId}`) - console.log(`[BedrockEmbedder] Request body:`, requestBody) - const command = new InvokeModelCommand(params) - let response - try { - response = await this.bedrockClient.send(command) - } catch (error: any) { - console.error(`[BedrockEmbedder] API error for model ${modelId}:`, error) - console.error(`[BedrockEmbedder] Error name:`, error.name) - console.error(`[BedrockEmbedder] Error message:`, error.message) - console.error(`[BedrockEmbedder] Error details:`, JSON.stringify(error, null, 2)) - throw error - } + const response = await this.bedrockClient.send(command) // Parse the response const responseBody = JSON.parse(new TextDecoder().decode(response.body)) - console.log(`[BedrockEmbedder] Response for model ${modelId}:`, responseBody) // Extract embedding based on model type if (model.startsWith("amazon.nova-2-multimodal")) { From 8dd3053b4cfb6b0242a94d64365a757d98e45da3 Mon Sep 17 00:00:00 2001 From: George Goranov Date: Wed, 26 Nov 2025 14:34:03 +0200 Subject: [PATCH 15/17] Fix config-manager.spec.ts unit test. --- src/services/code-index/__tests__/config-manager.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/services/code-index/__tests__/config-manager.spec.ts b/src/services/code-index/__tests__/config-manager.spec.ts index 1bf7e914788..d3bec15920a 100644 --- a/src/services/code-index/__tests__/config-manager.spec.ts +++ b/src/services/code-index/__tests__/config-manager.spec.ts @@ -104,6 +104,7 @@ describe("CodeIndexConfigManager", () => { modelId: undefined, openAiOptions: { openAiNativeApiKey: "" }, ollamaOptions: { ollamaBaseUrl: "" }, + bedrockOptions: { region: "us-east-1", profile: undefined }, qdrantUrl: "http://localhost:6333", qdrantApiKey: "", searchMinScore: 0.4, From fe05a5173922cb4bf2756fda2bac0817fd0339bd Mon Sep 17 00:00:00 2001 From: George Goranov Date: Wed, 26 Nov 2025 14:51:59 +0200 Subject: [PATCH 16/17] Add translations for "optional" --- webview-ui/src/i18n/locales/ca/settings.json | 1 + webview-ui/src/i18n/locales/de/settings.json | 1 + webview-ui/src/i18n/locales/en/settings.json | 3 ++- webview-ui/src/i18n/locales/es/settings.json | 1 + webview-ui/src/i18n/locales/fr/settings.json | 1 + webview-ui/src/i18n/locales/hi/settings.json | 1 + webview-ui/src/i18n/locales/id/settings.json | 1 + webview-ui/src/i18n/locales/it/settings.json | 1 + webview-ui/src/i18n/locales/ja/settings.json | 1 + webview-ui/src/i18n/locales/ko/settings.json | 1 + webview-ui/src/i18n/locales/nl/settings.json | 1 + webview-ui/src/i18n/locales/pl/settings.json | 1 + webview-ui/src/i18n/locales/pt-BR/settings.json | 1 + webview-ui/src/i18n/locales/ru/settings.json | 1 + webview-ui/src/i18n/locales/tr/settings.json | 1 + webview-ui/src/i18n/locales/vi/settings.json | 1 + webview-ui/src/i18n/locales/zh-CN/settings.json | 1 + webview-ui/src/i18n/locales/zh-TW/settings.json | 1 + 18 files changed, 19 insertions(+), 1 deletion(-) diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index 8abd261dda4..75feccd2ddb 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -158,6 +158,7 @@ "modelDimensionMinValue": "La dimensió del model ha de ser superior a 0", "openRouterApiKeyRequired": "Clau API d'OpenRouter és requerida" }, + "optional": "opcional", "advancedConfigLabel": "Configuració avançada", "searchMinScoreLabel": "Llindar de puntuació de cerca", "searchMinScoreDescription": "Puntuació mínima de similitud (0.0-1.0) requerida per als resultats de la cerca. Valors més baixos retornen més resultats però poden ser menys rellevants. Valors més alts retornen menys resultats però més rellevants.", diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index 68ae295b7de..2b380115780 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -158,6 +158,7 @@ "modelDimensionMinValue": "Modellabmessung muss größer als 0 sein", "openRouterApiKeyRequired": "OpenRouter API-Schlüssel ist erforderlich" }, + "optional": "optional", "advancedConfigLabel": "Erweiterte Konfiguration", "searchMinScoreLabel": "Suchergebnis-Schwellenwert", "searchMinScoreDescription": "Mindestähnlichkeitswert (0.0-1.0), der für Suchergebnisse erforderlich ist. Niedrigere Werte liefern mehr Ergebnisse, die jedoch möglicherweise weniger relevant sind. Höhere Werte liefern weniger, aber relevantere Ergebnisse.", diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index 4036efdaa82..7548d44be19 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -170,7 +170,8 @@ "ollamaBaseUrlRequired": "Ollama base URL is required", "baseUrlRequired": "Base URL is required", "modelDimensionMinValue": "Model dimension must be greater than 0" - } + }, + "optional": "optional" }, "autoApprove": { "description": "Run these actions without asking for permission. Only enable for actions you fully trust and if you understand the security risks.", diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index b6a94d82b25..8519938d4af 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -158,6 +158,7 @@ "modelDimensionMinValue": "La dimensión del modelo debe ser mayor que 0", "openRouterApiKeyRequired": "Se requiere la clave API de OpenRouter" }, + "optional": "opcional", "advancedConfigLabel": "Configuración avanzada", "searchMinScoreLabel": "Umbral de puntuación de búsqueda", "searchMinScoreDescription": "Puntuación mínima de similitud (0.0-1.0) requerida para los resultados de búsqueda. Valores más bajos devuelven más resultados pero pueden ser menos relevantes. Valores más altos devuelven menos resultados pero más relevantes.", diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index eeaf0ffa35a..13f54eb59fd 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -158,6 +158,7 @@ "modelDimensionMinValue": "La dimension du modèle doit être supérieure à 0", "openRouterApiKeyRequired": "Clé API OpenRouter est requise" }, + "optional": "optionnel", "advancedConfigLabel": "Configuration avancée", "searchMinScoreLabel": "Seuil de score de recherche", "searchMinScoreDescription": "Score de similarité minimum (0.0-1.0) requis pour les résultats de recherche. Des valeurs plus faibles renvoient plus de résultats mais peuvent être moins pertinents. Des valeurs plus élevées renvoient moins de résultats mais plus pertinents.", diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index c55f4f8fec6..b9ceadc55bf 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -158,6 +158,7 @@ "modelDimensionMinValue": "मॉडल आयाम 0 से बड़ा होना चाहिए", "openRouterApiKeyRequired": "OpenRouter API कुंजी आवश्यक है" }, + "optional": "वैकल्पिक", "advancedConfigLabel": "उन्नत कॉन्फ़िगरेशन", "searchMinScoreLabel": "खोज स्कोर थ्रेसहोल्ड", "searchMinScoreDescription": "खोज परिणामों के लिए आवश्यक न्यूनतम समानता स्कोर (0.0-1.0)। कम मान अधिक परिणाम लौटाते हैं लेकिन कम प्रासंगिक हो सकते हैं। उच्च मान कम लेकिन अधिक प्रासंगिक परिणाम लौटाते हैं।", diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json index 07e5447d984..2426f8be3cf 100644 --- a/webview-ui/src/i18n/locales/id/settings.json +++ b/webview-ui/src/i18n/locales/id/settings.json @@ -158,6 +158,7 @@ "modelDimensionMinValue": "Dimensi model harus lebih besar dari 0", "openRouterApiKeyRequired": "Kunci API OpenRouter diperlukan" }, + "optional": "opsional", "advancedConfigLabel": "Konfigurasi Lanjutan", "searchMinScoreLabel": "Ambang Batas Skor Pencarian", "searchMinScoreDescription": "Skor kesamaan minimum (0.0-1.0) yang diperlukan untuk hasil pencarian. Nilai yang lebih rendah mengembalikan lebih banyak hasil tetapi mungkin kurang relevan. Nilai yang lebih tinggi mengembalikan lebih sedikit hasil tetapi lebih relevan.", diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index 8b07721ba65..752b8a6dd20 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -158,6 +158,7 @@ "modelDimensionMinValue": "La dimensione del modello deve essere maggiore di 0", "openRouterApiKeyRequired": "Chiave API OpenRouter è richiesta" }, + "optional": "opzionale", "advancedConfigLabel": "Configurazione avanzata", "searchMinScoreLabel": "Soglia punteggio di ricerca", "searchMinScoreDescription": "Punteggio minimo di somiglianza (0.0-1.0) richiesto per i risultati della ricerca. Valori più bassi restituiscono più risultati ma potrebbero essere meno pertinenti. Valori più alti restituiscono meno risultati ma più pertinenti.", diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index 5358893069e..9281f3be15a 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -158,6 +158,7 @@ "modelDimensionMinValue": "モデルの次元は0より大きくなければなりません", "openRouterApiKeyRequired": "OpenRouter APIキーが必要です" }, + "optional": "オプション", "advancedConfigLabel": "詳細設定", "searchMinScoreLabel": "検索スコアのしきい値", "searchMinScoreDescription": "検索結果に必要な最小類似度スコア(0.0-1.0)。値を低くするとより多くの結果が返されますが、関連性が低くなる可能性があります。値を高くすると返される結果は少なくなりますが、より関連性が高くなります。", diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index be96edde5b2..c555b81f243 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -158,6 +158,7 @@ "modelDimensionMinValue": "모델 차원은 0보다 커야 합니다", "openRouterApiKeyRequired": "OpenRouter API 키가 필요합니다" }, + "optional": "선택 사항", "advancedConfigLabel": "고급 구성", "searchMinScoreLabel": "검색 점수 임계값", "searchMinScoreDescription": "검색 결과에 필요한 최소 유사도 점수(0.0-1.0). 값이 낮을수록 더 많은 결과가 반환되지만 관련성이 떨어질 수 있습니다. 값이 높을수록 결과는 적지만 관련성이 높은 결과가 반환됩니다.", diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json index 61845e0bf4b..01da609400c 100644 --- a/webview-ui/src/i18n/locales/nl/settings.json +++ b/webview-ui/src/i18n/locales/nl/settings.json @@ -158,6 +158,7 @@ "modelDimensionMinValue": "Modelafmeting moet groter zijn dan 0", "openRouterApiKeyRequired": "OpenRouter API-sleutel is vereist" }, + "optional": "optioneel", "advancedConfigLabel": "Geavanceerde configuratie", "searchMinScoreLabel": "Zoekscore drempel", "searchMinScoreDescription": "Minimale overeenkomstscore (0.0-1.0) vereist voor zoekresultaten. Lagere waarden leveren meer resultaten op, maar zijn mogelijk minder relevant. Hogere waarden leveren minder, maar relevantere resultaten op.", diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index f89b76dcaf2..a8cf0eca78e 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -158,6 +158,7 @@ "modelDimensionMinValue": "Wymiar modelu musi być większy niż 0", "openRouterApiKeyRequired": "Wymagany jest klucz API OpenRouter" }, + "optional": "opcjonalny", "advancedConfigLabel": "Konfiguracja zaawansowana", "searchMinScoreLabel": "Próg wyniku wyszukiwania", "searchMinScoreDescription": "Minimalny wynik podobieństwa (0.0-1.0) wymagany dla wyników wyszukiwania. Niższe wartości zwracają więcej wyników, ale mogą być mniej trafne. Wyższe wartości zwracają mniej wyników, ale bardziej trafnych.", diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index 183ba03d9f3..0cb0c48afd5 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -158,6 +158,7 @@ "modelDimensionMinValue": "A dimensão do modelo deve ser maior que 0", "openRouterApiKeyRequired": "Chave API do OpenRouter é obrigatória" }, + "optional": "opcional", "advancedConfigLabel": "Configuração Avançada", "searchMinScoreLabel": "Limite de pontuação de busca", "searchMinScoreDescription": "Pontuação mínima de similaridade (0.0-1.0) necessária para os resultados da busca. Valores mais baixos retornam mais resultados, mas podem ser menos relevantes. Valores mais altos retornam menos resultados, mas mais relevantes.", diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index 52c1723d9e4..69cca8038f5 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -158,6 +158,7 @@ "modelDimensionMinValue": "Размерность модели должна быть больше 0", "openRouterApiKeyRequired": "Требуется ключ API OpenRouter" }, + "optional": "необязательно", "advancedConfigLabel": "Расширенная конфигурация", "searchMinScoreLabel": "Порог оценки поиска", "searchMinScoreDescription": "Минимальный балл сходства (0.0-1.0), необходимый для результатов поиска. Более низкие значения возвращают больше результатов, но они могут быть менее релевантными. Более высокие значения возвращают меньше результатов, но более релевантных.", diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index 0f9588ec704..c4491f618c2 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -158,6 +158,7 @@ "modelDimensionMinValue": "Model boyutu 0'dan büyük olmalıdır", "openRouterApiKeyRequired": "OpenRouter API anahtarı gereklidir" }, + "optional": "isteğe bağlı", "advancedConfigLabel": "Gelişmiş Yapılandırma", "searchMinScoreLabel": "Arama Skoru Eşiği", "searchMinScoreDescription": "Arama sonuçları için gereken minimum benzerlik puanı (0.0-1.0). Düşük değerler daha fazla sonuç döndürür ancak daha az alakalı olabilir. Yüksek değerler daha az ancak daha alakalı sonuçlar döndürür.", diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index e34cc216bb7..8691d3e7db2 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -158,6 +158,7 @@ "modelDimensionMinValue": "Kích thước mô hình phải lớn hơn 0", "openRouterApiKeyRequired": "Yêu cầu khóa API OpenRouter" }, + "optional": "tùy chọn", "advancedConfigLabel": "Cấu hình nâng cao", "searchMinScoreLabel": "Ngưỡng điểm tìm kiếm", "searchMinScoreDescription": "Điểm tương đồng tối thiểu (0.0-1.0) cần thiết cho kết quả tìm kiếm. Giá trị thấp hơn trả về nhiều kết quả hơn nhưng có thể kém liên quan hơn. Giá trị cao hơn trả về ít kết quả hơn nhưng có liên quan hơn.", diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index 4215bb5cefc..39684435896 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -158,6 +158,7 @@ "modelDimensionMinValue": "模型维度必须大于 0", "openRouterApiKeyRequired": "OpenRouter API 密钥是必需的" }, + "optional": "可选", "advancedConfigLabel": "高级配置", "searchMinScoreLabel": "搜索分数阈值", "searchMinScoreDescription": "搜索结果所需的最低相似度分数(0.0-1.0)。较低的值返回更多结果,但可能不太相关。较高的值返回较少但更相关的结果。", diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index 9b2189195f5..6dc3eada7f9 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -158,6 +158,7 @@ "modelDimensionMinValue": "模型維度必須大於 0", "openRouterApiKeyRequired": "OpenRouter API 密鑰是必需的" }, + "optional": "可選", "advancedConfigLabel": "進階設定", "searchMinScoreLabel": "搜尋分數閾值", "searchMinScoreDescription": "搜尋結果所需的最低相似度分數(0.0-1.0)。較低的值會傳回更多結果,但可能較不相關。較高的值會傳回較少但更相關的結果。", From 28e18ee29213ea104ff2f6652171b6e1990bd46a Mon Sep 17 00:00:00 2001 From: George Goranov Date: Wed, 26 Nov 2025 15:07:31 +0200 Subject: [PATCH 17/17] Revert unnecessary change related to open ia embedder --- src/services/code-index/config-manager.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/services/code-index/config-manager.ts b/src/services/code-index/config-manager.ts index b911a09d42d..7de0d8d3de4 100644 --- a/src/services/code-index/config-manager.ts +++ b/src/services/code-index/config-manager.ts @@ -51,11 +51,8 @@ export class CodeIndexConfigManager { codebaseIndexEmbedderProvider: "openai", codebaseIndexEmbedderBaseUrl: "", codebaseIndexEmbedderModelId: "", - codebaseIndexEmbedderModelDimension: undefined, codebaseIndexSearchMinScore: undefined, codebaseIndexSearchMaxResults: undefined, - codebaseIndexOpenAiCompatibleBaseUrl: "", - codebaseIndexOpenAiCompatibleModelDimension: undefined, codebaseIndexBedrockRegion: "us-east-1", codebaseIndexBedrockProfile: "", }