From 5497079ab202d45061bce1b265645f31ec6f19fd Mon Sep 17 00:00:00 2001 From: azizur100389 Date: Fri, 8 May 2026 17:05:18 +0100 Subject: [PATCH 1/2] fix(search): surface warning when FTS indexes are missing (#1418) --- gitnexus/src/core/augmentation/engine.ts | 2 +- gitnexus/src/core/search/bm25-index.ts | 47 ++++++++++++++----- gitnexus/src/core/search/hybrid-search.ts | 11 +++-- gitnexus/src/mcp/local/local-backend.ts | 9 ++-- gitnexus/src/server/api.ts | 23 ++++++--- gitnexus/test/integration/search-core.test.ts | 24 +++++----- gitnexus/test/integration/search-pool.test.ts | 16 +++---- gitnexus/test/unit/bm25-search.test.ts | 26 +++++----- gitnexus/test/unit/calltool-dispatch.test.ts | 23 ++++++++- .../test/unit/mcp/group-repo-routing.test.ts | 2 +- 10 files changed, 121 insertions(+), 62 deletions(-) diff --git a/gitnexus/src/core/augmentation/engine.ts b/gitnexus/src/core/augmentation/engine.ts index 896813c22..f97415cc9 100644 --- a/gitnexus/src/core/augmentation/engine.ts +++ b/gitnexus/src/core/augmentation/engine.ts @@ -104,7 +104,7 @@ export async function augment(pattern: string, cwd?: string): Promise { } // Step 1: BM25 search (fast, no embeddings) - const bm25Results = await searchFTSFromLbug(pattern, 10, repoId); + const { results: bm25Results } = await searchFTSFromLbug(pattern, 10, repoId); if (bm25Results.length === 0) return ''; diff --git a/gitnexus/src/core/search/bm25-index.ts b/gitnexus/src/core/search/bm25-index.ts index 58c0343c9..27a7b9d8d 100644 --- a/gitnexus/src/core/search/bm25-index.ts +++ b/gitnexus/src/core/search/bm25-index.ts @@ -15,9 +15,16 @@ export interface BM25SearchResult { nodeIds?: string[]; } +export interface FTSSearchResponse { + results: BM25SearchResult[]; + /** True when at least one FTS index query succeeded (index exists). */ + ftsAvailable: boolean; +} + /** * Execute a single FTS query via a custom executor (for MCP connection pool). - * Returns the same shape as core queryFTS (from LadybugDB adapter). + * Returns `null` when the query fails (e.g. FTS index does not exist) so the + * caller can distinguish "zero matches" from "index missing". */ async function queryFTSViaExecutor( executor: (cypher: string) => Promise, @@ -25,7 +32,7 @@ async function queryFTSViaExecutor( indexName: string, query: string, limit: number, -): Promise> { +): Promise | null> { // Escape single quotes and backslashes to prevent Cypher injection const escapedQuery = query.replace(/\\/g, '\\\\').replace(/'/g, "''"); const cypher = ` @@ -46,7 +53,7 @@ async function queryFTSViaExecutor( }; }); } catch { - return []; + return null; } } @@ -65,8 +72,9 @@ export const searchFTSFromLbug = async ( query: string, limit: number = 20, repoId?: string, -): Promise => { +): Promise => { const resultsByIndex: any[][] = []; + let queriesSucceeded = 0; if (repoId) { // Use MCP connection pool via dynamic import @@ -77,15 +85,27 @@ export const searchFTSFromLbug = async ( const executor = (cypher: string) => executeQuery(repoId, cypher); for (const { table, indexName } of FTS_INDEXES) { - resultsByIndex.push(await queryFTSViaExecutor(executor, table, indexName, query, limit)); + const result = await queryFTSViaExecutor(executor, table, indexName, query, limit); + if (result !== null) { + queriesSucceeded++; + resultsByIndex.push(result); + } } } else { // Use core lbug adapter (CLI / pipeline context) — also sequential for safety. for (const { table, indexName } of FTS_INDEXES) { - resultsByIndex.push(await queryFTS(table, indexName, query, limit, false).catch(() => [])); + try { + const result = await queryFTS(table, indexName, query, limit, false); + queriesSucceeded++; + resultsByIndex.push(result); + } catch { + // FTS index may not exist — count as failed + } } } + const ftsAvailable = queriesSucceeded > 0; + // Collect all node scores per filePath to track which nodes actually matched const fileNodeScores = new Map>(); @@ -116,10 +136,13 @@ export const searchFTSFromLbug = async ( .sort((a, b) => b.score - a.score) .slice(0, limit); - return sorted.map((r, index) => ({ - filePath: r.filePath, - score: r.score, - rank: index + 1, - nodeIds: r.nodeIds, - })); + return { + results: sorted.map((r, index) => ({ + filePath: r.filePath, + score: r.score, + rank: index + 1, + nodeIds: r.nodeIds, + })), + ftsAvailable, + }; }; diff --git a/gitnexus/src/core/search/hybrid-search.ts b/gitnexus/src/core/search/hybrid-search.ts index 72dd1c9b5..b76a9f5e9 100644 --- a/gitnexus/src/core/search/hybrid-search.ts +++ b/gitnexus/src/core/search/hybrid-search.ts @@ -113,12 +113,13 @@ export const mergeWithRRF = ( }; /** - * Check if hybrid search is available - * LadybugDB FTS is always available once the database is initialized. - * Semantic search is optional - hybrid works with just FTS if embeddings aren't ready. + * Check if hybrid search is available. + * FTS indexes may be missing on read-only MCP connections (see #1403); + * callers should inspect `ftsAvailable` from searchFTSFromLbug for + * per-query availability. This helper is a coarse gate only. */ export const isHybridSearchReady = (): boolean => { - return true; // FTS is always available via LadybugDB when DB is open + return true; // FTS is attempted on every query; ftsAvailable signals actual availability }; /** @@ -160,7 +161,7 @@ export const hybridSearch = async ( ) => Promise, ): Promise => { // Use LadybugDB FTS for always-fresh BM25 results - const bm25Results = await searchFTSFromLbug(query, limit); + const { results: bm25Results } = await searchFTSFromLbug(query, limit); const semanticResults = await semanticSearch(executeQuery, query, limit); return mergeWithRRF(bm25Results, semanticResults, limit); }; diff --git a/gitnexus/src/mcp/local/local-backend.ts b/gitnexus/src/mcp/local/local-backend.ts index 2f16c1fb2..6175af875 100644 --- a/gitnexus/src/mcp/local/local-backend.ts +++ b/gitnexus/src/mcp/local/local-backend.ts @@ -979,7 +979,7 @@ export class LocalBackend { timing, ...(!ftsUsed && { warning: - 'FTS extension unavailable - keyword search degraded. Run: gitnexus analyze --force to rebuild indexes.', + 'FTS indexes missing — keyword search degraded. Run: gitnexus analyze --force to rebuild indexes.', }), }; } @@ -993,9 +993,9 @@ export class LocalBackend { limit: number, ): Promise<{ results: any[]; ftsUsed: boolean }> { const { searchFTSFromLbug } = await import('../../core/search/bm25-index.js'); - let bm25Results; + let ftsResponse; try { - bm25Results = await searchFTSFromLbug(query, limit, repo.id); + ftsResponse = await searchFTSFromLbug(query, limit, repo.id); } catch (err: any) { logger.error( { err: err.message }, @@ -1004,7 +1004,8 @@ export class LocalBackend { return { results: [], ftsUsed: false }; } - const ftsUsed = bm25Results.length === 0 || bm25Results[0]?.ftsUsed !== false; + const bm25Results = ftsResponse.results; + const ftsUsed = ftsResponse.ftsAvailable; const results: any[] = []; diff --git a/gitnexus/src/server/api.ts b/gitnexus/src/server/api.ts index 773190785..cc65daa3d 100644 --- a/gitnexus/src/server/api.ts +++ b/gitnexus/src/server/api.ts @@ -1060,11 +1060,12 @@ export const createServer = async (port: number, host: string = '127.0.0.1') => const results = await withLbugDb(lbugPath, async () => { let searchResults: any[]; + let ftsAvailable: boolean | undefined; if (mode === 'semantic') { const { isEmbedderReady } = await import('../core/embeddings/embedder.js'); if (!isEmbedderReady()) { - return [] as any[]; + return { searchResults: [] as any[], ftsAvailable: undefined }; } const { semanticSearch: semSearch } = await import('../core/embeddings/embedding-pipeline.js'); @@ -1077,8 +1078,9 @@ export const createServer = async (port: number, host: string = '127.0.0.1') => sources: ['semantic'], })); } else if (mode === 'bm25') { - searchResults = await searchFTSFromLbug(query, limit); - searchResults = searchResults.map((r: any, i: number) => ({ + const ftsResponse = await searchFTSFromLbug(query, limit); + ftsAvailable = ftsResponse.ftsAvailable; + searchResults = ftsResponse.results.map((r: any, i: number) => ({ ...r, rank: i + 1, sources: ['bm25'], @@ -1091,11 +1093,13 @@ export const createServer = async (port: number, host: string = '127.0.0.1') => await import('../core/embeddings/embedding-pipeline.js'); searchResults = await hybridSearch(query, limit, executeQuery, semSearch); } else { - searchResults = await searchFTSFromLbug(query, limit); + const ftsResponse = await searchFTSFromLbug(query, limit); + ftsAvailable = ftsResponse.ftsAvailable; + searchResults = ftsResponse.results; } } - if (!enrich) return searchResults; + if (!enrich) return { searchResults, ftsAvailable }; // Server-side enrichment: add connections, cluster, processes per result // Uses parameterized queries to prevent Cypher injection via nodeId @@ -1177,9 +1181,14 @@ export const createServer = async (port: number, host: string = '127.0.0.1') => }), ); - return enriched; + return { searchResults: enriched, ftsAvailable }; }); - res.json({ results }); + const response: any = { results: results.searchResults ?? results }; + if (results.ftsAvailable === false) { + response.warning = + 'FTS indexes missing — keyword search degraded. Run: gitnexus analyze --force to rebuild indexes.'; + } + res.json(response); } catch (err: any) { res.status(500).json({ error: err.message || 'Search failed' }); } diff --git a/gitnexus/test/integration/search-core.test.ts b/gitnexus/test/integration/search-core.test.ts index 2ccc14706..e49169b30 100644 --- a/gitnexus/test/integration/search-core.test.ts +++ b/gitnexus/test/integration/search-core.test.ts @@ -19,7 +19,7 @@ withTestLbugDB( (_handle) => { describe('searchFTSFromLbug — core adapter (no repoId)', () => { it('returns ranked results for a matching query', async () => { - const results = await searchFTSFromLbug('user authentication', 10); + const { results } = await searchFTSFromLbug('user authentication', 10); expect(results.length).toBeGreaterThan(0); @@ -40,7 +40,7 @@ withTestLbugDB( }); it('results are ordered by descending score', async () => { - const results = await searchFTSFromLbug('user authentication', 10); + const { results } = await searchFTSFromLbug('user authentication', 10); for (let i = 1; i < results.length; i++) { expect(results[i - 1].score).toBeGreaterThanOrEqual(results[i].score); @@ -48,7 +48,7 @@ withTestLbugDB( }); it('auth-related files rank higher than unrelated files', async () => { - const results = await searchFTSFromLbug('user authentication', 10); + const { results } = await searchFTSFromLbug('user authentication', 10); const filePaths = results.map((r) => r.filePath); expect(filePaths).toContain('src/auth.ts'); @@ -61,7 +61,7 @@ withTestLbugDB( }); it('merges scores from multiple node types for the same filePath', async () => { - const results = await searchFTSFromLbug('user authentication', 20); + const { results } = await searchFTSFromLbug('user authentication', 20); const authResult = results.find((r) => r.filePath === 'src/auth.ts'); expect(authResult).toBeDefined(); @@ -73,12 +73,12 @@ withTestLbugDB( }); it('respects limit parameter', async () => { - const results = await searchFTSFromLbug('user authentication', 2); + const { results } = await searchFTSFromLbug('user authentication', 2); expect(results.length).toBeLessThanOrEqual(2); }); it('returns empty array for a non-matching query', async () => { - const results = await searchFTSFromLbug('xyzzyplughtwisty', 10); + const { results } = await searchFTSFromLbug('xyzzyplughtwisty', 10); expect(results).toEqual([]); }); }); @@ -87,32 +87,32 @@ withTestLbugDB( describe('unhappy paths', () => { it('returns empty array for empty query string', async () => { - const results = await searchFTSFromLbug('', 10); + const { results } = await searchFTSFromLbug('', 10); expect(results).toEqual([]); }); it('returns empty array for whitespace-only query', async () => { - const results = await searchFTSFromLbug(' ', 10); + const { results } = await searchFTSFromLbug(' ', 10); expect(results).toEqual([]); }); it('handles special characters in query gracefully', async () => { - const results = await searchFTSFromLbug('user* OR auth+', 10); + const { results } = await searchFTSFromLbug('user* OR auth+', 10); expect(Array.isArray(results)).toBe(true); }); it('handles limit of 0', async () => { - const results = await searchFTSFromLbug('user authentication', 0); + const { results } = await searchFTSFromLbug('user authentication', 0); expect(results).toEqual([]); }); it('handles negative limit gracefully', async () => { - const results = await searchFTSFromLbug('user authentication', -1); + const { results } = await searchFTSFromLbug('user authentication', -1); expect(Array.isArray(results)).toBe(true); }); it('handles very large limit', async () => { - const results = await searchFTSFromLbug('user authentication', 100000); + const { results } = await searchFTSFromLbug('user authentication', 100000); expect(results.length).toBeLessThanOrEqual(100000); expect(results.length).toBeGreaterThan(0); }); diff --git a/gitnexus/test/integration/search-pool.test.ts b/gitnexus/test/integration/search-pool.test.ts index c0943483b..88128fcfa 100644 --- a/gitnexus/test/integration/search-pool.test.ts +++ b/gitnexus/test/integration/search-pool.test.ts @@ -19,7 +19,7 @@ withTestLbugDB( (handle) => { describe('searchFTSFromLbug — MCP pool adapter (with repoId)', () => { it('returns ranked results via pool adapter', async () => { - const results = await searchFTSFromLbug('user authentication', 10, handle.repoId); + const { results } = await searchFTSFromLbug('user authentication', 10, handle.repoId); expect(results.length).toBeGreaterThan(0); @@ -35,7 +35,7 @@ withTestLbugDB( }); it('results are ordered by descending score via pool adapter', async () => { - const results = await searchFTSFromLbug('user authentication', 10, handle.repoId); + const { results } = await searchFTSFromLbug('user authentication', 10, handle.repoId); for (let i = 1; i < results.length; i++) { expect(results[i - 1].score).toBeGreaterThanOrEqual(results[i].score); @@ -43,12 +43,12 @@ withTestLbugDB( }); it('returns empty array for non-matching query via pool adapter', async () => { - const results = await searchFTSFromLbug('xyzzyplughtwisty', 10, handle.repoId); + const { results } = await searchFTSFromLbug('xyzzyplughtwisty', 10, handle.repoId); expect(results).toEqual([]); }); it('respects limit parameter via pool adapter', async () => { - const results = await searchFTSFromLbug('user authentication', 1, handle.repoId); + const { results } = await searchFTSFromLbug('user authentication', 1, handle.repoId); expect(results.length).toBeLessThanOrEqual(1); }); }); @@ -57,22 +57,22 @@ withTestLbugDB( describe('unhappy paths', () => { it('returns empty array for empty query via pool', async () => { - const results = await searchFTSFromLbug('', 10, handle.repoId); + const { results } = await searchFTSFromLbug('', 10, handle.repoId); expect(results).toEqual([]); }); it('returns empty array for whitespace-only query via pool', async () => { - const results = await searchFTSFromLbug(' ', 10, handle.repoId); + const { results } = await searchFTSFromLbug(' ', 10, handle.repoId); expect(results).toEqual([]); }); it('handles special characters in query via pool', async () => { - const results = await searchFTSFromLbug('user* OR auth+', 10, handle.repoId); + const { results } = await searchFTSFromLbug('user* OR auth+', 10, handle.repoId); expect(Array.isArray(results)).toBe(true); }); it('handles limit of 0 via pool', async () => { - const results = await searchFTSFromLbug('user authentication', 0, handle.repoId); + const { results } = await searchFTSFromLbug('user authentication', 0, handle.repoId); expect(results).toEqual([]); }); }); diff --git a/gitnexus/test/unit/bm25-search.test.ts b/gitnexus/test/unit/bm25-search.test.ts index 9b232688f..03a591599 100644 --- a/gitnexus/test/unit/bm25-search.test.ts +++ b/gitnexus/test/unit/bm25-search.test.ts @@ -42,20 +42,24 @@ describe('BM25 search', () => { }); describe('searchFTSFromLbug', () => { - it('returns empty array when LadybugDB is not initialized', async () => { - // Without LadybugDB init, search should return empty (not crash) - const results = await searchFTSFromLbug('test query'); + it('returns empty results when LadybugDB is not initialized', async () => { + // Simulate an uninitialized DB: queryFTS throws instead of returning rows + const { queryFTS } = await import('../../src/core/lbug/lbug-adapter.js'); + vi.mocked(queryFTS).mockRejectedValue(new Error('DB not initialized')); + + const { results, ftsAvailable } = await searchFTSFromLbug('test query'); expect(Array.isArray(results)).toBe(true); expect(results).toHaveLength(0); + expect(ftsAvailable).toBe(false); }); it('handles empty query', async () => { - const results = await searchFTSFromLbug(''); + const { results } = await searchFTSFromLbug(''); expect(Array.isArray(results)).toBe(true); }); it('accepts custom limit parameter', async () => { - const results = await searchFTSFromLbug('test', 5); + const { results } = await searchFTSFromLbug('test', 5); expect(Array.isArray(results)).toBe(true); }); }); @@ -105,7 +109,7 @@ describe('BM25 search', () => { .mockResolvedValueOnce([]) // Method .mockResolvedValueOnce([]); // Interface - const results = await searchFTSFromLbug('queryset'); + const { results } = await searchFTSFromLbug('queryset'); expect(results).toHaveLength(1); expect(results[0].filePath).toBe('src/views.py'); @@ -127,7 +131,7 @@ describe('BM25 search', () => { .mockResolvedValueOnce([]) // Method .mockResolvedValueOnce([]); // Interface - const results = await searchFTSFromLbug('model'); + const { results } = await searchFTSFromLbug('model'); expect(results).toHaveLength(1); expect(results[0].score).toBe(8); // 5+3 @@ -147,7 +151,7 @@ describe('BM25 search', () => { .mockResolvedValueOnce([]) // Method .mockResolvedValueOnce([]); // Interface - const results = await searchFTSFromLbug('util'); + const { results } = await searchFTSFromLbug('util'); expect(results).toHaveLength(1); expect(results[0].nodeIds).toEqual([]); @@ -171,7 +175,7 @@ describe('BM25 search', () => { .mockResolvedValueOnce([]) // Method .mockResolvedValueOnce([]); // Interface - const results = await searchFTSFromLbug('auth'); + const { results } = await searchFTSFromLbug('auth'); expect(results).toHaveLength(1); // All 3 hits (scores 9+7+4=20) — each from a different table, all top-3 @@ -192,7 +196,7 @@ describe('BM25 search', () => { .mockResolvedValueOnce([]) // Method .mockResolvedValueOnce([]); // Interface - const results = await searchFTSFromLbug('fn'); + const { results } = await searchFTSFromLbug('fn'); expect(results[0].filePath).toBe('src/high.py'); expect(results[1].filePath).toBe('src/low.py'); @@ -220,7 +224,7 @@ describe('BM25 search', () => { return []; }); - const results = await searchFTSFromLbug('login', 5, REPO); + const { results } = await searchFTSFromLbug('login', 5, REPO); expect(results).toEqual([ { filePath: 'src/auth.ts', score: 8, rank: 1, nodeIds: ['func:login'] }, diff --git a/gitnexus/test/unit/calltool-dispatch.test.ts b/gitnexus/test/unit/calltool-dispatch.test.ts index 6b13cacfa..45e1b71d2 100644 --- a/gitnexus/test/unit/calltool-dispatch.test.ts +++ b/gitnexus/test/unit/calltool-dispatch.test.ts @@ -62,7 +62,7 @@ vi.mock('../../src/core/platform/capabilities.js', async (importOriginal) => { // Also mock the search modules to avoid loading onnxruntime vi.mock('../../src/core/search/bm25-index.js', () => ({ - searchFTSFromLbug: vi.fn().mockResolvedValue([]), + searchFTSFromLbug: vi.fn().mockResolvedValue({ results: [], ftsAvailable: true }), })); vi.mock('../../src/mcp/core/embedder.js', () => ({ @@ -195,6 +195,27 @@ describe('LocalBackend.callTool', () => { expect(result).toHaveProperty('definitions'); }); + it('includes FTS-unavailable warning when ftsAvailable is false (#1403)', async () => { + const { searchFTSFromLbug } = await import('../../src/core/search/bm25-index.js'); + vi.mocked(searchFTSFromLbug).mockResolvedValueOnce({ results: [], ftsAvailable: false }); + (executeParameterized as any).mockResolvedValue([]); + + const result = await backend.callTool('query', { query: 'ProcessActivity' }); + + expect(result).toHaveProperty('warning'); + expect((result as any).warning).toMatch(/gitnexus analyze --force/); + }); + + it('does not include warning when ftsAvailable is true with zero results', async () => { + const { searchFTSFromLbug } = await import('../../src/core/search/bm25-index.js'); + vi.mocked(searchFTSFromLbug).mockResolvedValueOnce({ results: [], ftsAvailable: true }); + (executeParameterized as any).mockResolvedValue([]); + + const result = await backend.callTool('query', { query: 'nonexistent' }); + + expect(result).not.toHaveProperty('warning'); + }); + it('skips vector index query when VECTOR is unsupported by the platform', async () => { const cap = _captureLogger(); platformMocks.isVectorExtensionSupportedByPlatform.mockReturnValue(false); diff --git a/gitnexus/test/unit/mcp/group-repo-routing.test.ts b/gitnexus/test/unit/mcp/group-repo-routing.test.ts index ddf7d03a5..474abeaa8 100644 --- a/gitnexus/test/unit/mcp/group-repo-routing.test.ts +++ b/gitnexus/test/unit/mcp/group-repo-routing.test.ts @@ -32,7 +32,7 @@ vi.mock('../../../src/storage/repo-manager.js', () => ({ })); vi.mock('../../../src/core/search/bm25-index.js', () => ({ - searchFTSFromLbug: vi.fn().mockResolvedValue([]), + searchFTSFromLbug: vi.fn().mockResolvedValue({ results: [], ftsAvailable: true }), })); vi.mock('../../../src/mcp/core/embedder.js', () => ({ From 5bfe0c5222de711a9f85f5872bdfac860df4a1e3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 9 May 2026 05:53:16 +0100 Subject: [PATCH 2/2] chore(deps)(deps): bump onnxruntime-node in /gitnexus (#1435) --- gitnexus/package-lock.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/gitnexus/package-lock.json b/gitnexus/package-lock.json index b07ccd7cb..57fe4169e 100644 --- a/gitnexus/package-lock.json +++ b/gitnexus/package-lock.json @@ -4282,15 +4282,15 @@ } }, "node_modules/onnxruntime-common": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.25.1.tgz", - "integrity": "sha512-kKvYQFdos4LWJqhZ+nmKu3NT8NXzw8I5x9fNUKe1rNKcPfNKnYXUtW7JBpcKFsvLtrJashRgVYSbFap4cHxvNg==", + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.26.0.tgz", + "integrity": "sha512-qVyMR4lcWgbkc4getFV+GQijsTnbg/siteoqcDwa3sI/LxbrMSNw4ePyvCq/ymdQaRomCA7YuWmhzsswxvymdw==", "license": "MIT" }, "node_modules/onnxruntime-node": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/onnxruntime-node/-/onnxruntime-node-1.25.1.tgz", - "integrity": "sha512-N0M58CGTiTsLkPpx9bxmRFi24GT6r67Qei/GrBEIiDyntcYdXU5vQZp112ypydG9vEKRFgbgUYQJnEi+jll8dg==", + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/onnxruntime-node/-/onnxruntime-node-1.26.0.tgz", + "integrity": "sha512-OHl6PiOEOqxaLHL0N9eFrbzS7IGmu3BtJNH3RTEnRAheCIkfc3gjcjl4sGcjp9C22ZC9YTquDOxSdT/stBQ6BQ==", "hasInstallScript": true, "license": "MIT", "os": [ @@ -4301,7 +4301,7 @@ "dependencies": { "adm-zip": "^0.5.16", "global-agent": "^4.1.3", - "onnxruntime-common": "1.25.1" + "onnxruntime-common": "1.26.0" } }, "node_modules/onnxruntime-web": {