fix: remove i18n dependencies from embedders and vector store for worker compatibility

- Remove i18n imports from all embedder implementations (openai, openai-compatible, ollama)
- Remove i18n import from qdrant-client vector store
- Replace all translation calls with plain English strings
- This allows these modules to be used in worker threads where vscode APIs are not available
This commit is contained in:
hannesrudolph 2025-07-03 11:08:57 -06:00
parent ce0d891777
commit cb4bb8476f
4 changed files with 23 additions and 69 deletions

View file

@ -2,7 +2,6 @@ import { ApiHandlerOptions } from "../../../shared/api"
import { EmbedderInfo, EmbeddingResponse, IEmbedder } from "../interfaces"
import { getModelQueryPrefix } from "../../../shared/embeddingModels"
import { MAX_ITEM_TOKENS } from "../constants"
import { t } from "../../../i18n"
/**
* Implements the IEmbedder interface using a local Ollama instance.
@ -39,11 +38,7 @@ export class CodeIndexOllamaEmbedder implements IEmbedder {
const estimatedTokens = Math.ceil(prefixedText.length / 4)
if (estimatedTokens > MAX_ITEM_TOKENS) {
console.warn(
t("embeddings:textWithPrefixExceedsTokenLimit", {
index,
estimatedTokens,
maxTokens: MAX_ITEM_TOKENS,
}),
`Text at index ${index} with prefix exceeds token limit (${estimatedTokens} > ${MAX_ITEM_TOKENS})`,
)
// Return original text if adding prefix would exceed limit
return text
@ -67,18 +62,14 @@ export class CodeIndexOllamaEmbedder implements IEmbedder {
})
if (!response.ok) {
let errorBody = t("embeddings:ollama.couldNotReadErrorBody")
let errorBody = "Could not read error body"
try {
errorBody = await response.text()
} catch (e) {
// Ignore error reading body
}
throw new Error(
t("embeddings:ollama.requestFailed", {
status: response.status,
statusText: response.statusText,
errorBody,
}),
`Ollama request failed with status ${response.status} ${response.statusText}: ${errorBody}`,
)
}
@ -87,7 +78,7 @@ export class CodeIndexOllamaEmbedder implements IEmbedder {
// Extract embeddings using 'embeddings' key as requested
const embeddings = data.embeddings
if (!embeddings || !Array.isArray(embeddings)) {
throw new Error(t("embeddings:ollama.invalidResponseStructure"))
throw new Error("Invalid response structure: expected 'embeddings' array")
}
return {
@ -97,7 +88,7 @@ export class CodeIndexOllamaEmbedder implements IEmbedder {
// Log the original error for debugging purposes
console.error("Ollama embedding failed:", error)
// Re-throw a more specific error for the caller
throw new Error(t("embeddings:ollama.embeddingFailed", { message: error.message }))
throw new Error(`Ollama embedding failed: ${error.message}`)
}
}

View file

@ -7,7 +7,6 @@ import {
INITIAL_RETRY_DELAY_MS as INITIAL_DELAY_MS,
} from "../constants"
import { getDefaultModelId, getModelQueryPrefix } from "../../../shared/embeddingModels"
import { t } from "../../../i18n"
interface EmbeddingItem {
embedding: string | number[]
@ -89,11 +88,7 @@ export class OpenAICompatibleEmbedder implements IEmbedder {
const estimatedTokens = Math.ceil(prefixedText.length / 4)
if (estimatedTokens > MAX_ITEM_TOKENS) {
console.warn(
t("embeddings:textWithPrefixExceedsTokenLimit", {
index,
estimatedTokens,
maxTokens: MAX_ITEM_TOKENS,
}),
`Text at index ${index} with prefix exceeds token limit (${estimatedTokens} > ${MAX_ITEM_TOKENS})`,
)
// Return original text if adding prefix would exceed limit
return text
@ -115,14 +110,8 @@ export class OpenAICompatibleEmbedder implements IEmbedder {
const text = remainingTexts[i]
const itemTokens = Math.ceil(text.length / 4)
if (itemTokens > this.maxItemTokens) {
console.warn(
t("embeddings:textExceedsTokenLimit", {
index: i,
itemTokens,
maxTokens: this.maxItemTokens,
}),
)
if (itemTokens > MAX_ITEM_TOKENS) {
console.warn(`Text at index ${i} exceeds token limit (${itemTokens} > ${MAX_ITEM_TOKENS})`)
processedIndices.push(i)
continue
}
@ -278,13 +267,7 @@ export class OpenAICompatibleEmbedder implements IEmbedder {
if (isRateLimitError && hasMoreAttempts) {
const delayMs = INITIAL_DELAY_MS * Math.pow(2, attempts)
console.warn(
t("embeddings:rateLimitRetry", {
delayMs,
attempt: attempts + 1,
maxRetries: MAX_RETRIES,
}),
)
console.warn(`Rate limit hit, retrying in ${delayMs}ms (attempt ${attempts + 1}/${MAX_RETRIES})`)
await new Promise((resolve) => setTimeout(resolve, delayMs))
continue
}
@ -293,7 +276,7 @@ export class OpenAICompatibleEmbedder implements IEmbedder {
console.error(`OpenAI Compatible embedder error (attempt ${attempts + 1}/${MAX_RETRIES}):`, error)
// Provide more context in the error message using robust error extraction
let errorMessage = t("embeddings:unknownError")
let errorMessage = "Unknown error"
if (httpError?.message) {
errorMessage = httpError.message
} else if (typeof error === "string") {
@ -302,25 +285,25 @@ export class OpenAICompatibleEmbedder implements IEmbedder {
try {
errorMessage = String(error)
} catch {
errorMessage = t("embeddings:unknownError")
errorMessage = "Unknown error"
}
}
const statusCode = httpError?.status || httpError?.response?.status
if (statusCode === 401) {
throw new Error(t("embeddings:authenticationFailed"))
throw new Error("Authentication failed. Please check your API key.")
} else if (statusCode) {
throw new Error(
t("embeddings:failedWithStatus", { attempts: MAX_RETRIES, statusCode, errorMessage }),
`Failed to create embeddings after ${MAX_RETRIES} attempts. Status: ${statusCode}. Error: ${errorMessage}`,
)
} else {
throw new Error(t("embeddings:failedWithError", { attempts: MAX_RETRIES, errorMessage }))
throw new Error(`Failed to create embeddings after ${MAX_RETRIES} attempts. Error: ${errorMessage}`)
}
}
}
throw new Error(t("embeddings:failedMaxAttempts", { attempts: MAX_RETRIES }))
throw new Error(`Failed to create embeddings after ${MAX_RETRIES} attempts`)
}
/**

View file

@ -9,7 +9,6 @@ import {
INITIAL_RETRY_DELAY_MS as INITIAL_DELAY_MS,
} from "../constants"
import { getModelQueryPrefix } from "../../../shared/embeddingModels"
import { t } from "../../../i18n"
/**
* OpenAI implementation of the embedder interface with batching and rate limiting
@ -50,11 +49,7 @@ export class OpenAiEmbedder extends OpenAiNativeHandler implements IEmbedder {
const estimatedTokens = Math.ceil(prefixedText.length / 4)
if (estimatedTokens > MAX_ITEM_TOKENS) {
console.warn(
t("embeddings:textWithPrefixExceedsTokenLimit", {
index,
estimatedTokens,
maxTokens: MAX_ITEM_TOKENS,
}),
`Text at index ${index} with prefix exceeds token limit (${estimatedTokens} > ${MAX_ITEM_TOKENS})`,
)
// Return original text if adding prefix would exceed limit
return text
@ -77,13 +72,7 @@ export class OpenAiEmbedder extends OpenAiNativeHandler implements IEmbedder {
const itemTokens = Math.ceil(text.length / 4)
if (itemTokens > MAX_ITEM_TOKENS) {
console.warn(
t("embeddings:textExceedsTokenLimit", {
index: i,
itemTokens,
maxTokens: MAX_ITEM_TOKENS,
}),
)
console.warn(`Text at index ${i} exceeds token limit (${itemTokens} > ${MAX_ITEM_TOKENS})`)
processedIndices.push(i)
continue
}
@ -143,13 +132,7 @@ export class OpenAiEmbedder extends OpenAiNativeHandler implements IEmbedder {
if (isRateLimitError && hasMoreAttempts) {
const delayMs = INITIAL_DELAY_MS * Math.pow(2, attempts)
console.warn(
t("embeddings:rateLimitRetry", {
delayMs,
attempt: attempts + 1,
maxRetries: MAX_RETRIES,
}),
)
console.warn(`Rate limit hit, retrying in ${delayMs}ms (attempt ${attempts + 1}/${MAX_RETRIES})`)
await new Promise((resolve) => setTimeout(resolve, delayMs))
continue
}
@ -174,18 +157,18 @@ export class OpenAiEmbedder extends OpenAiNativeHandler implements IEmbedder {
const statusCode = error?.status || error?.response?.status
if (statusCode === 401) {
throw new Error(t("embeddings:authenticationFailed"))
throw new Error("Authentication failed. Please check your API key.")
} else if (statusCode) {
throw new Error(
t("embeddings:failedWithStatus", { attempts: MAX_RETRIES, statusCode, errorMessage }),
`Failed to create embeddings after ${MAX_RETRIES} attempts. Status: ${statusCode}. Error: ${errorMessage}`,
)
} else {
throw new Error(t("embeddings:failedWithError", { attempts: MAX_RETRIES, errorMessage }))
throw new Error(`Failed to create embeddings after ${MAX_RETRIES} attempts. Error: ${errorMessage}`)
}
}
}
throw new Error(t("embeddings:failedMaxAttempts", { attempts: MAX_RETRIES }))
throw new Error(`Failed to create embeddings after ${MAX_RETRIES} attempts`)
}
get embedderInfo(): EmbedderInfo {

View file

@ -5,7 +5,6 @@ import { getWorkspacePath } from "../../../utils/path"
import { IVectorStore } from "../interfaces/vector-store"
import { Payload, VectorStoreSearchResult } from "../interfaces"
import { MAX_SEARCH_RESULTS, SEARCH_MIN_SCORE } from "../constants"
import { t } from "../../../i18n"
/**
* Qdrant implementation of the vector store interface
@ -205,9 +204,7 @@ export class QdrantVectorStore implements IVectorStore {
)
// Provide a more user-friendly error message that includes the original error
throw new Error(
t("embeddings:vectorStore.qdrantConnectionFailed", { qdrantUrl: this.qdrantUrl, errorMessage }),
)
throw new Error(`Failed to connect to Qdrant at ${this.qdrantUrl}: ${errorMessage}`)
}
}