diff --git a/Dockerfile b/Dockerfile index ffec336..4eb8a3c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -32,6 +32,12 @@ RUN apt-get update && apt-get install -y \ COPY package*.json ./ RUN npm install --ignore-scripts +# --ignore-scripts skips node-gyp rebuild for native modules +# (security best-practice, blocks malicious postinstall scripts). +# Explicitly rebuild better-sqlite3 so its arm64/amd64 .node binding +# is compiled — otherwise the runtime fails with "Could not locate +# the bindings file" on architectures lacking a prebuild. +RUN npm rebuild better-sqlite3 # Install Chrome via Puppeteer as fallback (system Chromium will be used first) RUN npx puppeteer browsers install chrome || true COPY . . diff --git a/doc2vec.ts b/doc2vec.ts index 47ab0de..3c306df 100644 --- a/doc2vec.ts +++ b/doc2vec.ts @@ -89,15 +89,19 @@ export class Doc2Vec { } else { const openaiApiKey = embeddingConfig.openai?.api_key || process.env.OPENAI_API_KEY; const openaiModel = embeddingConfig.openai?.model || process.env.OPENAI_MODEL || 'text-embedding-3-large'; - + const openaiBaseURL = embeddingConfig.openai?.base_url || process.env.OPENAI_BASE_URL; + if (!openaiApiKey) { this.logger.error('OpenAI requires api_key to be configured'); process.exit(1); } - - this.openai = new OpenAI({ apiKey: openaiApiKey }); + + this.openai = new OpenAI({ + apiKey: openaiApiKey, + ...(openaiBaseURL && { baseURL: openaiBaseURL }), + }); this.embeddingModel = openaiModel; - this.logger.info(`Using OpenAI with model: ${openaiModel} (${this.embeddingDimension} dimensions)`); + this.logger.info(`Using OpenAI with model: ${openaiModel} (${this.embeddingDimension} dimensions)${openaiBaseURL ? ` via ${openaiBaseURL}` : ''}`); } this.contentProcessor = new ContentProcessor(this.logger); diff --git a/mcp/src/index.ts b/mcp/src/index.ts index 7f48875..7273cf2 100644 --- a/mcp/src/index.ts +++ b/mcp/src/index.ts @@ -34,6 +34,7 @@ const embeddingProvider = process.env.EMBEDDING_PROVIDER || 'openai'; // OpenAI configuration const openAIApiKey = process.env.OPENAI_API_KEY; const openAIModel = process.env.OPENAI_MODEL || 'text-embedding-3-large'; +const openAIBaseURL = process.env.OPENAI_BASE_URL; // Optional: override API base URL for Ollama / other OpenAI-compatible endpoints // Azure OpenAI configuration const azureApiKey = process.env.AZURE_OPENAI_KEY; @@ -110,6 +111,7 @@ async function createEmbeddings(text: string): Promise { case 'openai': { const openai = new OpenAI({ apiKey: openAIApiKey, + ...(openAIBaseURL && { baseURL: openAIBaseURL }), }); const response = await openai.embeddings.create({ model: openAIModel, diff --git a/types.ts b/types.ts index 9f1341b..e39a238 100644 --- a/types.ts +++ b/types.ts @@ -98,8 +98,9 @@ export interface EmbeddingConfig { provider: 'openai' | 'azure'; dimension?: number; openai?: { - api_key?: string; // Can also use OPENAI_API_KEY env var - model?: string; // Default: text-embedding-3-large + api_key?: string; // Can also use OPENAI_API_KEY env var + model?: string; // Default: text-embedding-3-large + base_url?: string; // Override OpenAI API base URL — useful for Ollama or other OpenAI-compatible endpoints. Can also use OPENAI_BASE_URL env var. }; azure?: { api_key?: string; // Can also use AZURE_OPENAI_KEY env var