From 711747a5a073fbd2c23a73b782710e392bcc6d21 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Fri, 10 Apr 2026 13:41:55 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=8E=20fix:=20Install=20LadybugDB=20Ext?= =?UTF-8?q?ensions=20and=20Patch=20Vector=20Load=20for=20GitNexus=20Search?= =?UTF-8?q?=20(#12607)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two upstream GitNexus 1.5.3 bugs combine to break query() in serve mode: 1. pool-adapter.ts calls LOAD EXTENSION fts but never INSTALL fts. The CI-produced .gitnexus/ artifact doesn't include the extension cache (~/.kuzu/extension/), so LOAD silently fails in the fresh container and all BM25/FTS searches return empty. 2. pool-adapter.ts only loads the FTS extension — it never loads the vector extension. Every CALL QUERY_VECTOR_INDEX in semanticSearch fails, so hybrid search's semantic leg returns empty too. Combined, query() returns empty even for exact function names because both the BM25 and semantic legs of RRF merging have zero inputs. Meanwhile context()/cypher()/route_map() still work because they use plain Cypher with no extensions. Workaround: - Add install-extensions.js that runs INSTALL fts and INSTALL vector against a throwaway database during Docker build, populating ~/.kuzu/extension/ with the cached extension binaries - Sed-patch pool-adapter.js at build time to also LOAD EXTENSION vector alongside the existing FTS load, wrapped in try/catch - Update deploy workflow to copy install-extensions.js into the build context --- .fly/gitnexus/Dockerfile | 16 ++++++++++ .fly/gitnexus/install-extensions.js | 43 +++++++++++++++++++++++++++ .github/workflows/gitnexus-deploy.yml | 1 + 3 files changed, 60 insertions(+) create mode 100644 .fly/gitnexus/install-extensions.js diff --git a/.fly/gitnexus/Dockerfile b/.fly/gitnexus/Dockerfile index 911f90d244..6a3a8c6118 100644 --- a/.fly/gitnexus/Dockerfile +++ b/.fly/gitnexus/Dockerfile @@ -18,6 +18,22 @@ RUN echo "deb http://deb.debian.org/debian trixie main" > /etc/apt/sources.list. && rm /etc/apt/sources.list.d/trixie.list \ && rm -rf /var/lib/apt/lists/* +# 3. Pre-install LadybugDB FTS + vector extensions so the cache in +# ~/.kuzu/extension/ is baked into the image. Workaround for upstream +# bug: gitnexus serve's pool-adapter calls LOAD EXTENSION but never +# INSTALL, so without this step, query()'s BM25 + semantic search +# silently return empty. +COPY install-extensions.js /tmp/install-extensions.js +RUN node /tmp/install-extensions.js && rm -rf /tmp/install-extensions.js /tmp/lbug-ext-install + +# 4. Patch pool-adapter.js to also LOAD EXTENSION vector after FTS. +# Upstream only loads FTS at serve time; without vector extension +# loaded, semantic search's CALL QUERY_VECTOR_INDEX fails silently. +RUN POOL_ADAPTER=/usr/local/lib/node_modules/gitnexus/dist/core/lbug/pool-adapter.js \ + && grep -q "LOAD EXTENSION fts" "$POOL_ADAPTER" \ + && sed -i "s|await available\[0\]\.query('LOAD EXTENSION fts');|await available[0].query('LOAD EXTENSION fts'); try { await available[0].query('LOAD EXTENSION vector'); } catch (e) { /* vector extension may not be installed */ }|g" "$POOL_ADAPTER" \ + && echo "pool-adapter.js patched to load vector extension" + # Copy pre-built GitNexus indexes (one per branch) and register each. # The directory name becomes the repo name in `list_repos` output, so # each branch lands in /LibreChat or /LibreChat-dev etc. diff --git a/.fly/gitnexus/install-extensions.js b/.fly/gitnexus/install-extensions.js new file mode 100644 index 0000000000..f8cb1b5183 --- /dev/null +++ b/.fly/gitnexus/install-extensions.js @@ -0,0 +1,43 @@ +/** + * Pre-install LadybugDB extensions (FTS + vector) into the Docker image's + * extension cache (~/.kuzu/extension/). Without this, gitnexus serve's + * pool-adapter calls LOAD EXTENSION fts at runtime but fails silently + * because the extension was never installed, causing all BM25 and + * semantic queries via the query() tool to return empty. + * + * This is a workaround for an upstream GitNexus 1.5.3 bug: + * pool-adapter.ts loads extensions but never installs them, and the + * CI-produced .gitnexus/ artifact doesn't include the extension cache. + */ + +const path = require('path'); +const fs = require('fs'); + +// @ladybugdb/core lives under the globally-installed gitnexus package +const lbugPath = '/usr/local/lib/node_modules/gitnexus/node_modules/@ladybugdb/core'; +const lbug = require(lbugPath); + +const tmpDir = '/tmp/lbug-ext-install'; +fs.mkdirSync(tmpDir, { recursive: true }); + +// Open a throwaway database to run INSTALL against. The extension cache +// persists in ~/.kuzu/extension/ regardless of which database was used. +const db = new lbug.Database(path.join(tmpDir, 'db'), 0, false, false); +const conn = new lbug.Connection(db); + +(async () => { + try { + await conn.query('INSTALL fts'); + console.log('FTS extension installed'); + } catch (err) { + console.error('FTS install failed:', err.message); + process.exit(1); + } + try { + await conn.query('INSTALL vector'); + console.log('Vector extension installed'); + } catch (err) { + console.error('Vector install failed:', err.message); + process.exit(1); + } +})(); diff --git a/.github/workflows/gitnexus-deploy.yml b/.github/workflows/gitnexus-deploy.yml index 8e6ac2d84b..4a647d787b 100644 --- a/.github/workflows/gitnexus-deploy.yml +++ b/.github/workflows/gitnexus-deploy.yml @@ -102,6 +102,7 @@ jobs: cp .fly/gitnexus/Dockerfile deploy/Dockerfile cp .fly/gitnexus/Caddyfile deploy/Caddyfile cp .fly/gitnexus/entrypoint.sh deploy/entrypoint.sh + cp .fly/gitnexus/install-extensions.js deploy/install-extensions.js echo "Deploy context:" ls -la deploy/ echo "Indexes staged:"