diff --git a/gitnexus/package-lock.json b/gitnexus/package-lock.json index 2e35a60a7..9eb3f67b1 100644 --- a/gitnexus/package-lock.json +++ b/gitnexus/package-lock.json @@ -1937,10 +1937,20 @@ "license": "MIT" }, "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-3.0.3.tgz", + "integrity": "sha512-Sn98ftV3KfsO8xfLPHG6oT8y+b0yvbrLgZjgPDXsharNY15tTAjqIsIju4S32nl6/iEUNNE4v+yL2Zhm8ooP3w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "PSF-2.0" }, "node_modules/array-back": { "version": "6.2.3", @@ -3134,9 +3144,9 @@ "license": "ISC" }, "node_modules/ip-address": { - "version": "10.7.2", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.7.2.tgz", - "integrity": "sha512-7H/2gFSIitxc0hG3nOI1glS8QLo/EHBFFLk8vEUjXY/xu0AdL8jZ9U1IzO2PUm0d2D/ofQcAifb0g6OBkt8U7w==", + "version": "10.7.4", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.7.4.tgz", + "integrity": "sha512-DWBMKyeM25D70nrIiTkgQth59/G+naKOTep6huF9j+GmeK3DMD60Zvxg5d5qQnz+38AHgou6ean2LECX+lrKDg==", "license": "MIT", "engines": { "node": ">= 12" @@ -3213,9 +3223,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.4.3.tgz", - "integrity": "sha512-yzzNtgczwgoVHNigCyKTXcQJU4Y8t/ikU4UxXW0BvrLfHTGWZhsNcOT2s/a7vn81/4KqVnNmHjaUEPlvWnNwVw==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.5.0.tgz", + "integrity": "sha512-paNr4LFIFPjeeSmwNYdrb8FafLLG/Cr2Af3GjbsHJ5CxIjH4r0c2emlmRdAtpPAieP1gRVzk6buBbVP5gBMGAg==", "funding": [ { "type": "github", @@ -3228,7 +3238,7 @@ ], "license": "MIT", "dependencies": { - "argparse": "^2.0.1" + "argparse": "^3.0.3" }, "bin": { "js-yaml": "bin/js-yaml.mjs" @@ -5426,9 +5436,9 @@ } }, "node_modules/zod": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", - "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", + "version": "4.6.7", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.7.tgz", + "integrity": "sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/gitnexus/package.json b/gitnexus/package.json index fee19ab03..65417d65f 100644 --- a/gitnexus/package.json +++ b/gitnexus/package.json @@ -45,7 +45,8 @@ "vendor/**/README.md", "vendor/leiden/index.cjs", "vendor/leiden/utils.cjs", - "vendor/lbug-fts/manifest.json" + "vendor/lbug-fts/manifest.json", + "vendor/lbug-vector/manifest.json" ], "scripts": { "build": "node scripts/build.js", diff --git a/gitnexus/src/core/lbug/extension-loader.ts b/gitnexus/src/core/lbug/extension-loader.ts index 575b3587d..93a922769 100644 --- a/gitnexus/src/core/lbug/extension-loader.ts +++ b/gitnexus/src/core/lbug/extension-loader.ts @@ -13,6 +13,7 @@ import { nodePlatformTuple, resolveFtsVersionPair, resolveVendoredFtsPath, + resolveVendoredVectorPath, } from './vendored-extension-path.js'; import { logger } from '../logger.js'; @@ -219,8 +220,8 @@ export const installDuckDbExtensionOutOfProcess = async ( * Centralized lifecycle manager for optional LadybugDB extensions. * * Tries `LOAD` first — it is per-connection, idempotent, and never - * touches the network. For FTS, a packaged vendored path is path-LOADed - * before the named `LOAD EXTENSION fts`. If `LOAD` fails and the active + * touches the network. For FTS and VECTOR, a packaged vendored path is + * path-LOADed before the named `LOAD EXTENSION`. If `LOAD` fails and the active * policy permits, the manager runs a single bounded out-of-process * `INSTALL` attempt per process and retries `LOAD`. Capability outcomes * are cached so unavailable extensions degrade search features without @@ -289,10 +290,13 @@ export class ExtensionManager { return false; } - if (name === 'fts') { + const isVector = name.toLowerCase() === 'vector'; + if (name === 'fts' || isVector) { const tuple = opts.platformTuple ?? nodePlatformTuple(); const vendorRoot = opts.vendorRoot ?? defaultVendorRoot(); - const vendored = resolveVendoredFtsPath({ vendorRoot, tuple }); + const vendored = isVector + ? resolveVendoredVectorPath({ vendorRoot, tuple }) + : resolveVendoredFtsPath({ vendorRoot, tuple }); if (vendored) { attempts.push({ source: 'vendored', tuple }); const vendoredError = await this.tryLoadPath(query, vendored); @@ -301,7 +305,7 @@ export class ExtensionManager { return true; } lastInspectPath = vendored; - } else if (isUnsupportedFtsTuple(tuple, vendorRoot)) { + } else if (name === 'fts' && isUnsupportedFtsTuple(tuple, vendorRoot)) { attempts.push({ source: 'vendored', tuple }); this.markUnavailable( name, diff --git a/gitnexus/src/core/lbug/native-check.ts b/gitnexus/src/core/lbug/native-check.ts index 7f4d81b3f..33d7e8e5d 100644 --- a/gitnexus/src/core/lbug/native-check.ts +++ b/gitnexus/src/core/lbug/native-check.ts @@ -3,7 +3,7 @@ import path from 'path'; import { createRequire } from 'node:module'; import { spawnSync, type SpawnSyncReturns } from 'node:child_process'; import { escapeCypherString } from './cypher-escape.js'; -import { resolveVendoredFtsPath } from './vendored-extension-path.js'; +import { resolveVendoredFtsPath, resolveVendoredVectorPath } from './vendored-extension-path.js'; /** Cap the out-of-process native load probe so a hung filesystem cannot wedge a * CLI startup gate (same bounding rationale as the extension probe below). */ @@ -505,7 +505,7 @@ export async function probeFtsExtensionLoad( export async function probeVectorExtensionLoad( timeoutMs: number = DEFAULT_FTS_PROBE_TIMEOUT_MS, ): Promise { - return await probeExtensionLoad('vector', timeoutMs); + return await probeExtensionLoad('vector', timeoutMs, resolveVendoredVectorPath()); } /** @@ -529,7 +529,7 @@ async function probeExtensionLoad( }); const statements: string[] = []; - if (extension === 'fts' && vendoredPath) { + if (vendoredPath) { statements.push(`LOAD EXTENSION '${escapeCypherString(path.resolve(vendoredPath))}'`); } statements.push(`LOAD EXTENSION ${extension}`); diff --git a/gitnexus/src/core/lbug/vendored-extension-path.ts b/gitnexus/src/core/lbug/vendored-extension-path.ts index ce5706981..b18bb51f9 100644 --- a/gitnexus/src/core/lbug/vendored-extension-path.ts +++ b/gitnexus/src/core/lbug/vendored-extension-path.ts @@ -130,3 +130,21 @@ export const resolveVendoredFtsPath = (opts?: { if (!existsSync(candidate)) return null; return validateVendoredExtensionPath(candidate, vendorRoot); }; + +/** VECTOR builds must match the core pin; the CDN's compatibility path can drift. */ +export const resolveVendoredVectorPath = (opts?: { + tuple?: string; + vendorRoot?: string; +}): string | null => { + const vendorRoot = opts?.vendorRoot ?? defaultVendorRoot(); + const tuple = opts?.tuple ?? nodePlatformTuple(); + const candidate = path.resolve( + vendorRoot, + 'lbug-vector', + 'prebuilds', + tuple, + 'libvector.lbug_extension', + ); + if (!existsSync(candidate)) return null; + return validateVendoredExtensionPath(candidate, vendorRoot); +}; diff --git a/gitnexus/test/unit/lbug-extension-loader.test.ts b/gitnexus/test/unit/lbug-extension-loader.test.ts index 79e76e77e..7a245d225 100644 --- a/gitnexus/test/unit/lbug-extension-loader.test.ts +++ b/gitnexus/test/unit/lbug-extension-loader.test.ts @@ -135,9 +135,9 @@ describe('ExtensionManager — install policies', () => { const manager = new ExtensionManager({ policy: 'auto', installExtension, warn }); const query = vi.fn().mockRejectedValue(new Error('Extension "vector" not found')); - await expect(manager.ensure(query, 'vector', 'VECTOR', { installTimeoutMs: 10 })).resolves.toBe( - false, - ); + await expect( + manager.ensure(query, 'vector', 'VECTOR', { ...noVendored, installTimeoutMs: 10 }), + ).resolves.toBe(false); expect(query.mock.calls.map(([sql]) => sql)).toEqual(['LOAD EXTENSION vector']); expect(warn).toHaveBeenCalledWith( @@ -690,7 +690,54 @@ describe('ExtensionManager — vendored-first FTS (U2)', () => { expect(String(query.mock.calls[0][0])).not.toContain('vendor-evil'); }); - it('does not try a vendored path for VECTOR and records no tuple', async () => { + it.each(['vector', 'VECTOR'])( + 'loads packaged %s before a broken home-cache copy', + async (name) => { + const vendorRoot = makeRoot(); + const dir = path.join(vendorRoot, 'lbug-vector', 'prebuilds', 'linux-x64'); + mkdirSync(dir, { recursive: true }); + const artifact = path.join(dir, 'libvector.lbug_extension'); + writeFileSync(artifact, 'placeholder'); + const loadPackaged = `LOAD EXTENSION '${escapeCypherString(realpathSync(artifact))}'`; + const query = vi.fn(async (sql: string) => { + if (sql !== loadPackaged) throw new Error('cached VECTOR has an undefined native symbol'); + return {}; + }); + const installExtension = vi.fn(); + const manager = new ExtensionManager({ + policy: 'load-only', + installExtension, + warn: noopWarn, + }); + + await expect( + manager.ensure(query, name, 'VECTOR', { vendorRoot, platformTuple: 'linux-x64' }), + ).resolves.toBe(true); + expect(query.mock.calls.map(([sql]) => sql)).toEqual([loadPackaged]); + expect(installExtension).not.toHaveBeenCalled(); + expect(manager.getCapabilities()[0]?.attempts).toEqual([ + { source: 'vendored', tuple: 'linux-x64' }, + ]); + }, + ); + + it('does not load packaged VECTOR under the never policy', async () => { + const vendorRoot = makeRoot(); + const dir = path.join(vendorRoot, 'lbug-vector', 'prebuilds', 'linux-x64'); + mkdirSync(dir, { recursive: true }); + writeFileSync(path.join(dir, 'libvector.lbug_extension'), 'placeholder'); + const query = vi.fn(); + const installExtension = vi.fn(); + const manager = new ExtensionManager({ policy: 'never', installExtension, warn: noopWarn }); + + await expect( + manager.ensure(query, 'VECTOR', 'VECTOR', { vendorRoot, platformTuple: 'linux-x64' }), + ).resolves.toBe(false); + expect(query).not.toHaveBeenCalled(); + expect(installExtension).not.toHaveBeenCalled(); + }); + + it('falls back to named VECTOR when no packaged VECTOR artifact exists', async () => { const vendorRoot = makeRoot(); writeVendorArtifact(vendorRoot, 'linux-x64'); const query = vi.fn().mockResolvedValue({}); diff --git a/gitnexus/test/unit/native-check-probe.test.ts b/gitnexus/test/unit/native-check-probe.test.ts index 8cb6f5d9a..cfadc43cd 100644 --- a/gitnexus/test/unit/native-check-probe.test.ts +++ b/gitnexus/test/unit/native-check-probe.test.ts @@ -1,5 +1,7 @@ import path from 'node:path'; import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { resolveVendoredVectorPath } from '../../src/core/lbug/vendored-extension-path.js'; +import { escapeCypherString } from '../../src/core/lbug/cypher-escape.js'; /** * Unit coverage for probeFtsExtensionLoad (#2374, PR #2375): the doctor FTS @@ -136,12 +138,24 @@ describe('probeFtsExtensionLoad (#2374)', () => { }); describe('probeVectorExtensionLoad (#2623 follow-up)', () => { - it('issues LOAD EXTENSION vector and reports loaded on success — no platform short-circuit', async () => { + it('probes the same packaged VECTOR artifact as the runtime', async () => { h.query.mockResolvedValue(closeable()); await expect(probeVectorExtensionLoad()).resolves.toEqual({ loaded: true }); - // The probe must really attempt the LOAD (the old code refused Windows - // before ever touching the engine; the artifact ships for win_amd64 too). - expect(h.query).toHaveBeenCalledWith('LOAD EXTENSION vector'); + const vendoredPath = resolveVendoredVectorPath(); + expect(h.query).toHaveBeenCalledWith( + vendoredPath + ? `LOAD EXTENSION '${escapeCypherString(path.resolve(vendoredPath))}'` + : 'LOAD EXTENSION vector', + ); + }); + + it('falls back to named VECTOR when the packaged binary cannot load', async () => { + h.query.mockImplementation(async (sql) => { + if (sql !== 'LOAD EXTENSION vector') throw new Error('packaged binary unavailable'); + return closeable(); + }); + await expect(probeVectorExtensionLoad()).resolves.toEqual({ loaded: true }); + expect(h.query).toHaveBeenLastCalledWith('LOAD EXTENSION vector'); }); it('reports the collapsed reason when LOAD fails', async () => { diff --git a/gitnexus/test/unit/vector-artifact-coverage.test.ts b/gitnexus/test/unit/vector-artifact-coverage.test.ts new file mode 100644 index 000000000..9413db8d1 --- /dev/null +++ b/gitnexus/test/unit/vector-artifact-coverage.test.ts @@ -0,0 +1,37 @@ +import { createHash } from 'node:crypto'; +import { readFileSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { describe, expect, it } from 'vitest'; +import { resolveVendoredVectorPath } from '../../src/core/lbug/vendored-extension-path.js'; + +const vendorRoot = fileURLToPath(new URL('../../vendor/', import.meta.url)); +const manifest = JSON.parse( + readFileSync(new URL('../../vendor/lbug-vector/manifest.json', import.meta.url), 'utf8'), +) as { + coreVersion: string; + artifacts: Array<{ tuple: string; sha256: string }>; +}; +const pkg = JSON.parse(readFileSync(new URL('../../package.json', import.meta.url), 'utf8')) as { + dependencies: Record; + files: string[]; +}; + +describe('packaged VECTOR artifacts', () => { + it('pins the artifacts to the installed core version and includes their provenance in npm', () => { + expect(manifest.coreVersion).toBe(pkg.dependencies['@ladybugdb/core']); + expect(pkg.files).toContain('vendor/lbug-vector/manifest.json'); + expect(manifest.artifacts.map(({ tuple }) => tuple).sort()).toEqual([ + 'darwin-arm64', + 'darwin-x64', + 'linux-arm64', + 'linux-x64', + 'win32-x64', + ]); + }); + + it.each(manifest.artifacts)('ships the verified $tuple binary', ({ tuple, sha256 }) => { + const artifact = resolveVendoredVectorPath({ vendorRoot, tuple }); + if (artifact === null) throw new Error(`Missing packaged VECTOR artifact for ${tuple}`); + expect(createHash('sha256').update(readFileSync(artifact)).digest('hex')).toBe(sha256); + }); +}); diff --git a/gitnexus/test/unit/vendored-extension-path.test.ts b/gitnexus/test/unit/vendored-extension-path.test.ts index ca380f032..0c180e33c 100644 --- a/gitnexus/test/unit/vendored-extension-path.test.ts +++ b/gitnexus/test/unit/vendored-extension-path.test.ts @@ -9,6 +9,7 @@ import { readFtsArtifactManifest, resolveFtsVersionPair, resolveVendoredFtsPath, + resolveVendoredVectorPath, isUnsupportedFtsTuple, validateVendoredExtensionPath, } from '../../src/core/lbug/vendored-extension-path.js'; @@ -77,6 +78,28 @@ describe('resolveVendoredFtsPath', () => { }); }); +describe('resolveVendoredVectorPath', () => { + it('resolves only the requested platform artifact', () => { + const vendorRoot = makeVendorRoot(); + const dir = join(vendorRoot, 'lbug-vector', 'prebuilds', 'linux-x64'); + mkdirSync(dir, { recursive: true }); + const artifact = join(dir, 'libvector.lbug_extension'); + writeFileSync(artifact, 'placeholder'); + + expect(resolveVendoredVectorPath({ vendorRoot, tuple: 'linux-x64' })).toBe(artifact); + expect(resolveVendoredVectorPath({ vendorRoot, tuple: 'win32-arm64' })).toBeNull(); + }); + + it('rejects a tuple that escapes the vendor root', () => { + const parent = makeVendorRoot(); + const vendorRoot = join(parent, 'vendor'); + mkdirSync(vendorRoot); + writeFileSync(join(parent, 'libvector.lbug_extension'), 'outside'); + + expect(resolveVendoredVectorPath({ vendorRoot, tuple: '../../..' })).toBeNull(); + }); +}); + describe('resolveFtsVersionPair', () => { it('reads expected from the manifest and found from a Ladybug home path', () => { const vendorRoot = makeVendorRoot(); diff --git a/gitnexus/vendor/lbug-vector/LICENSE b/gitnexus/vendor/lbug-vector/LICENSE new file mode 100644 index 000000000..9bb12b246 --- /dev/null +++ b/gitnexus/vendor/lbug-vector/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2022-2025 Kùzu Inc. +Copyright (c) 2025-2026 Ladybug Memory Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/gitnexus/vendor/lbug-vector/README.md b/gitnexus/vendor/lbug-vector/README.md new file mode 100644 index 000000000..ea5e9e862 --- /dev/null +++ b/gitnexus/vendor/lbug-vector/README.md @@ -0,0 +1,32 @@ +# LadybugDB VECTOR artifacts + +These unmodified binaries come from the official LadybugDB +[v0.21.1 build](https://github.com/LadybugDB/ladybug/actions/runs/36647903773), +at core commit `17a70e51c31b50d30231da32154d9ff4bef0d95f` and extensions +commit `bf74ab654af6bd40a0e3208ac4e8bcf5cb45a7a0`. + +`manifest.json` records each GitHub artifact ID, the archive digest supplied by +GitHub, and the extracted binary's SHA-256. Every archive was checked against +that digest before extracting `vector/libvector.lbug_extension`. + +The core's `0.21.0` CDN compatibility path can serve a VECTOR binary built +against incompatible core symbols. Load the matching packaged artifact first +so vector indexes work without a network install or a mutable home-cache copy. +The existing `never` policy still disables the extension; missing artifacts +retain the normal named-load and install fallback. + +To refresh, select an official build matching the exact `@ladybugdb/core` pin, +download its platform artifacts, verify their GitHub archive digests, and +update the binaries and manifest together. Validate Linux, macOS, and Windows +native tests before changing the pin. Do not substitute a nightly binary. + +For example, the Linux x64 archive is available with: + +```sh +gh api repos/LadybugDB/ladybug/actions/artifacts/11069747578/zip > vector-linux.zip +``` + +GitHub Actions artifacts expire; the committed binaries and checksums preserve +the verified build. `test/unit/vector-artifact-coverage.test.ts` checks the core +pin, platform coverage, and binary digests. The upstream MIT license is included +in `LICENSE`. diff --git a/gitnexus/vendor/lbug-vector/manifest.json b/gitnexus/vendor/lbug-vector/manifest.json new file mode 100644 index 000000000..a0a75ee0c --- /dev/null +++ b/gitnexus/vendor/lbug-vector/manifest.json @@ -0,0 +1,46 @@ +{ + "coreVersion": "0.21.1", + "filename": "libvector.lbug_extension", + "upstreamRepository": "https://github.com/LadybugDB/ladybug", + "upstreamTag": "v0.21.1", + "upstreamCommit": "17a70e51c31b50d30231da32154d9ff4bef0d95f", + "extensionsCommit": "bf74ab654af6bd40a0e3208ac4e8bcf5cb45a7a0", + "workflowRun": "https://github.com/LadybugDB/ladybug/actions/runs/36647903773", + "artifacts": [ + { + "tuple": "linux-x64", + "artifactId": 11069747578, + "artifactName": "lbug-extensions-linux-x86_64", + "archiveSha256": "377be87f6cf0e56a38230a536e768a0914f273163f112b8101f69894a088777b", + "sha256": "571726cc2ea0d202df1909ae5a3b0528c9dea3ea8d40be6c16b310ec14aa8821" + }, + { + "tuple": "linux-arm64", + "artifactId": 11069462823, + "artifactName": "lbug-extensions-linux-aarch64", + "archiveSha256": "bec0b8c5eb7f75b1f448b1a10360dbbd82c4553e3514418e90a37065468cb4cd", + "sha256": "583101f5bf2d0e5d40de2ee8966018a3bdf0fb8ad8951ef51ef46cd59169445f" + }, + { + "tuple": "darwin-x64", + "artifactId": 11069679640, + "artifactName": "lbug-extensions-osx-x86_64", + "archiveSha256": "2ddd47cd3afb5a2bcdae37e928125a81a1aa73775bb2e5e9448033f51eb02c18", + "sha256": "7c0cea65d68c341453ce567e0d12897d0691b5f9ff01cff0fdf0db5756ab7851" + }, + { + "tuple": "darwin-arm64", + "artifactId": 11069049174, + "artifactName": "lbug-extensions-osx-arm64", + "archiveSha256": "5d004e4bb9e3dd6f6da7248135eba64998adca283390c88e95f17d46224bbf5c", + "sha256": "6f878f3c0a2320a34967ff568fcf6bbe9065666e95035f0eddfe28bbc73b53f4" + }, + { + "tuple": "win32-x64", + "artifactId": 11070343650, + "artifactName": "lbug-extensions-win-x86_64", + "archiveSha256": "cef691c45f28be517b703bfdfafdd66a7d30b7da236f96c4e57297f5e67cf9f2", + "sha256": "6a8878eb2c93400222187460f8fc20ffc9cda4fc2c382fcbdf88f72a350d5746" + } + ] +} diff --git a/gitnexus/vendor/lbug-vector/prebuilds/darwin-arm64/libvector.lbug_extension b/gitnexus/vendor/lbug-vector/prebuilds/darwin-arm64/libvector.lbug_extension new file mode 100644 index 000000000..09df253e5 Binary files /dev/null and b/gitnexus/vendor/lbug-vector/prebuilds/darwin-arm64/libvector.lbug_extension differ diff --git a/gitnexus/vendor/lbug-vector/prebuilds/darwin-x64/libvector.lbug_extension b/gitnexus/vendor/lbug-vector/prebuilds/darwin-x64/libvector.lbug_extension new file mode 100644 index 000000000..37c59b812 Binary files /dev/null and b/gitnexus/vendor/lbug-vector/prebuilds/darwin-x64/libvector.lbug_extension differ diff --git a/gitnexus/vendor/lbug-vector/prebuilds/linux-arm64/libvector.lbug_extension b/gitnexus/vendor/lbug-vector/prebuilds/linux-arm64/libvector.lbug_extension new file mode 100644 index 000000000..940de9cfa Binary files /dev/null and b/gitnexus/vendor/lbug-vector/prebuilds/linux-arm64/libvector.lbug_extension differ diff --git a/gitnexus/vendor/lbug-vector/prebuilds/linux-x64/libvector.lbug_extension b/gitnexus/vendor/lbug-vector/prebuilds/linux-x64/libvector.lbug_extension new file mode 100644 index 000000000..8f627b503 Binary files /dev/null and b/gitnexus/vendor/lbug-vector/prebuilds/linux-x64/libvector.lbug_extension differ diff --git a/gitnexus/vendor/lbug-vector/prebuilds/win32-x64/libvector.lbug_extension b/gitnexus/vendor/lbug-vector/prebuilds/win32-x64/libvector.lbug_extension new file mode 100644 index 000000000..1fa3e01b9 Binary files /dev/null and b/gitnexus/vendor/lbug-vector/prebuilds/win32-x64/libvector.lbug_extension differ