Skip to content

[codex] Fix native addon build and runtime metadata#5

Merged
anupammaurya6767 merged 5 commits into
mainfrom
codex-fix-native-addon-runtime-issues
Apr 12, 2026
Merged

[codex] Fix native addon build and runtime metadata#5
anupammaurya6767 merged 5 commits into
mainfrom
codex-fix-native-addon-runtime-issues

Conversation

@anupammaurya6767

@anupammaurya6767 anupammaurya6767 commented Apr 12, 2026

Copy link
Copy Markdown
Owner

Summary

  • fix the macOS native build by replacing stale Homebrew linker paths and adding the required Homebrew include/library search paths for FAISS, OpenBLAS, and libomp
  • report the actual index type from native code for FLAT_IP, IVF_FLAT, HNSW, and loaded/deserialized indexes instead of hardcoding FLAT_L2
  • wire HNSW efConstruction and efSearch through the JS and N-API layers, add consistent disposed guards in the JS facade, and align the TypeScript and API docs with the runtime behavior

Root Cause

  • the macOS binding configuration depended on a version-pinned OpenBLAS cellar path and was missing the libomp header/include wiring needed by FAISS HNSW headers
  • getStats() returned a hardcoded type string, HNSW tuning params were documented but never passed through, and several JS methods accessed a nulled native handle after dispose

Validation

  • npm run build
  • npm test -- --runInBand
  • manual end-to-end Node validation covering package load, FLAT_L2, FLAT_IP, IVF_FLAT training/search, HNSW search/save-load/range-search, save/load, toBuffer/fromBuffer, reset, mergeFrom, and disposed-index behavior

Summary by CodeRabbit

  • New Features

    • HNSW support with configurable efConstruction/efSearch; added train, batch search, save/toBuffer, mergeFrom, load/fromBuffer; getStats reports actual index type; operations now error if index is disposed.
  • Documentation

    • Constructor type now optional (default FLAT_L2) and FLAT_IP documented; clarified which params apply to each index type; setNprobe() doc updated to void; merge described as a transfer.
  • Bug Fixes

    • Stronger validation of numeric/index-specific options (positive integers, rejected where incompatible).
  • Chores

    • Package version bumped and publish files restricted.

@coderabbitai

coderabbitai Bot commented Apr 12, 2026

Copy link
Copy Markdown

Warning

.coderabbit.yml has a parsing error

The CodeRabbit configuration file in this repository has a parsing error and default settings were used instead. Please fix the error(s) in the configuration file. You can initialize chat with CodeRabbit to get help with the configuration file.

💥 Parsing errors (1)
Validation error: Expected object, received array at "knowledge_base.learnings"
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 138c8738-1ea3-4879-ad39-845c0109d1b4

📥 Commits

Reviewing files that changed from the base of the PR and between b01b217 and ce0b33d.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (1)
  • package.json
✅ Files skipped from review due to trivial changes (1)
  • package.json

📝 Walkthrough

Walkthrough

Adds HNSW support and runtime HNSW parameter configuration, exposes index type, tightens JS validation and lifecycle checks, makes config.type optional, documents setNprobe() as synchronous, updates macOS Homebrew build/link paths, and expands TypeScript types and JS API surface.

Changes

Cohort / File(s) Summary
Config & Docs
\.coderabbit.yml, API.md, README.md
Streamlined review config; documented FaissIndex.config.type as optional and added FLAT_IP; changed setNprobe() docs to void; reworded mergeFrom() to describe transfer semantics; trimmed comments.
macOS Build Configuration
binding.gyp
Added Homebrew include and lib search paths under /opt/homebrew/opt and /usr/local/opt; removed -lomp; added -Wl,-rpath entries for faiss/openblas; removed cellar-specific OpenBLAS/libomp entries.
C++ Core
src/cpp/faiss_index.h, src/cpp/faiss_index.cpp
Added GetIndexType() and SetHnswParams(int, int); MergeFrom() now throws on self-merge and uses std::scoped_lock; updated comments to reflect transfer semantics.
N-API Bindings
src/cpp/napi_bindings.cpp
Parse/validate HNSW params (efConstruction,efSearch) when type === "HNSW"; validate nlist/nprobe/M positivity; call SetHnswParams; getStats() now reports actual index type via wrapper.
JavaScript Implementation
src/js/index.js
Added validatePositiveInteger() and validateIndexSpecificOptions(); defaulted type to FLAT_L2; validate and pass efConstruction/efSearch; introduced _ensureActive() and centralized disposed checks; updated mergeFrom docs to “transfer.”
TypeScript Definitions
src/js/types.d.ts
Made FaissIndexConfig.type optional and added FLAT_IP; added BatchSearchResults; expanded FaissIndex declarations (train, searchBatch, setNprobe, save, toBuffer, mergeFrom, load, fromBuffer).
Packaging
package.json
Bumped version to 0.1.10; added files whitelist limiting published package contents.

Sequence Diagram

sequenceDiagram
    participant JS as JavaScript\nConstructor
    participant Val as Validation\nLayer
    participant Bind as C++ Bindings\n(napi)
    participant Wrap as C++ Wrapper\n(FaissIndexWrapper)
    participant FAISS as FAISS\nNative Library

    JS->>Val: normalize type, validate index-specific options
    Val->>Val: validatePositiveInteger(nlist,nprobe,M,efConstruction,efSearch)
    Val->>Bind: construct native with validated config
    Bind->>Wrap: create wrapper instance
    Wrap->>FAISS: instantiate concrete index (IndexHNSW / IndexFlat / IndexIVF)
    FAISS-->>Wrap: index instance
    Bind->>Wrap: SetHnswParams(efConstruction, efSearch) [if HNSW]
    Wrap->>FAISS: apply efConstruction / efSearch
    FAISS-->>Wrap: params set
    Bind-->>JS: native reference ready
    JS->>Bind: getStats() -> uses GetIndexType()
    Bind-->>JS: returns index type
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hop through code with careful paws,
HNSW springs open new route laws,
Params checked and types made plain,
Homebrew paths linked for the lane,
Vectors transfer — a quiet gain.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title '[codex] Fix native addon build and runtime metadata' directly addresses the main changes: fixing macOS build paths and improving runtime index type reporting and validation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex-fix-native-addon-runtime-issues

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Anupam and others added 2 commits April 12, 2026 17:58
Remove explicit libomp linking to prevent duplicate OpenMP runtime
initialization errors on macOS CI runners.

The issue was introduced by linking against libomp explicitly in the
addon binding configuration, which caused conflicts with libomp already
linked by the system's FAISS installation.

Fix: Remove all libomp linking directives from binding.gyp, allowing
FAISS to provide the OpenMP runtime as needed. This prevents the
"multiple copies of OpenMP runtime have been linked" error.

Changes:
- Removed -L.../libomp/lib library paths from libraries
- Removed -lomp from libraries
- Removed -L.../libomp/lib from ldflags
- Removed -Wl,-rpath,.../libomp/lib from ldflags

Testing: Should resolve macOS CI failures with
'OMP: Error #15: Initializing libomp.dylib'

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Simplify .coderabbit.yml to use valid structure and remove deprecated fields.

- Restructured to use proper path_based_instructions instead of path_instructions
- Removed deprecated knowledge_base section
- Simplified and validated configuration format
- Maintained all critical review rules for C++ and JS code

This fixes the parsing error that caused CodeRabbit to skip reviews.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@anupammaurya6767 anupammaurya6767 marked this pull request as ready for review April 12, 2026 12:56

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
API.md (1)

232-247: ⚠️ Potential issue | 🟡 Minor

The setNprobe() throws contract is still stale.

The return type/example now match runtime, but the Throws section still says this errors when the index is not IVF_FLAT. The current JS/native path does not enforce that; it validates positivity/disposal and otherwise no-ops on non-IVF indexes. Either make the implementation reject non-IVF usage or drop that throw from the docs.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@API.md` around lines 232 - 247, Update the setNprobe documentation to match
runtime behavior: remove the "Error if index is not IVF_FLAT" from the Throws
section and clarify that setNprobe(nprobe: number) only throws for invalid
(non-positive) nprobe values or if the index is disposed, and that calling it on
non-IVF indexes is a no-op. Ensure the example and return type remain unchanged
and reference the setNprobe method and IVF_FLAT term for clarity.
🧹 Nitpick comments (1)
src/js/index.js (1)

51-55: Fail fast for index-type-specific options instead of silently accepting no-op fields.

efConstruction/efSearch (and typically M) are HNSW-specific, while nlist/nprobe are IVF-specific. Right now, incompatible combinations are accepted and passed through; native side can no-op (see src/cpp/faiss_index.cpp:320-339), which is easy to misconfigure without noticing.

Suggested validation hardening
         const validTypes = ['FLAT_L2', 'FLAT_IP', 'IVF_FLAT', 'HNSW'];
+        const resolvedType = config.type || 'FLAT_L2';
         if (config.type && !validTypes.includes(config.type)) {
             throw new Error(`Index type '${config.type}' not supported. Supported types: ${validTypes.join(', ')}`);
         }

+        if ((config.nlist !== undefined || config.nprobe !== undefined) && resolvedType !== 'IVF_FLAT') {
+            throw new TypeError('nlist/nprobe are only supported for IVF_FLAT indexes');
+        }
+        if ((config.M !== undefined || config.efConstruction !== undefined || config.efSearch !== undefined) && resolvedType !== 'HNSW') {
+            throw new TypeError('M/efConstruction/efSearch are only supported for HNSW indexes');
+        }
+
         for (const key of ['nlist', 'nprobe', 'M', 'efConstruction', 'efSearch']) {
             if (config[key] !== undefined) {
                 validatePositiveInteger(key, config[key]);
             }
         }

Also applies to: 71-76

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/js/index.js` around lines 51 - 55, The loop that calls
validatePositiveInteger for keys
['nlist','nprobe','M','efConstruction','efSearch'] must reject
index-type-incompatible options instead of silently no-oping; update the
validation around where config and validatePositiveInteger are used (the block
iterating those keys and the similar block at 71-76) to first read the index
type (e.g., config.indexType or the variable that selects IVF vs HNSW) and then
throw or return a validation error when IVF-only options ('nlist','nprobe') are
provided for an HNSW index or when HNSW-only options
('M','efConstruction','efSearch') are provided for an IVF index; keep using
validatePositiveInteger for value checks but add explicit compatibility checks
and clear error messages referencing the offending key and the selected index
type.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.coderabbit.yml:
- Around line 43-45: Rename the YAML key path_based_instructions to
path_instructions so it matches the allowed schema (reviews.path_instructions);
update the block that currently reads "path_based_instructions:" and any
references to it to use "path_instructions:" and keep the existing path entries
(e.g., "**/*.cpp") unchanged.

In `@src/cpp/faiss_index.cpp`:
- Around line 193-205: The current type-detection block returns FLAT_L2/FLAT_IP
as a fallback for any unrecognized deserialized FAISS index, which misreports
wrapped/unsupported indexes; update the final fallback to return "UNKNOWN"
instead of using index_->metric_type so only explicit IndexFlat detection
(dynamic_cast<faiss::IndexFlat*>(index_.get())) yields FLAT_IP/FLAT_L2, and
leave the existing checks for dynamic_cast<faiss::IndexHNSW*> and
dynamic_cast<faiss::IndexIVF*> unchanged so getStats() reports "UNKNOWN" for any
unhandled index subclass.
- Around line 297-299: FaissIndexWrapper::MergeFrom must reject self-merge
before acquiring both mutexes to avoid double-lock hang; add an early identity
check (e.g., if (&other == this) { return/throw appropriate error }) at the
start of MergeFrom to detect index.mergeFrom(index) and return or raise, then
proceed to acquire std::scoped_lock(mutex_, other.mutex_) and call merge logic;
ensure the same check is used wherever MergeFrom is called if necessary.

In `@src/cpp/napi_bindings.cpp`:
- Around line 504-506: The HNSW parameter defaults are not applied because
efConstruction and efSearch are initialized to 0 and SetHnswParams only writes
values > 0; initialize efConstruction to 200 and efSearch to 50 (instead of 0)
where they are declared alongside isHnsw so omitted caller params use the
documented defaults, and ensure the same change is applied to the other HNSW
parameter block that uses SetHnswParams (referencing variables isHnsw,
efConstruction, efSearch and the SetHnswParams call).

In `@src/js/index.js`:
- Around line 153-156: The setNprobe method validates the nprobe argument before
checking whether the instance is disposed, causing parameter errors instead of
the expected disposed error; update setNprobe so it calls this._ensureActive()
before calling validatePositiveInteger('nprobe', nprobe) (mirror the order used
in other methods) so disposal is checked first and only then validate the
argument.

---

Outside diff comments:
In `@API.md`:
- Around line 232-247: Update the setNprobe documentation to match runtime
behavior: remove the "Error if index is not IVF_FLAT" from the Throws section
and clarify that setNprobe(nprobe: number) only throws for invalid
(non-positive) nprobe values or if the index is disposed, and that calling it on
non-IVF indexes is a no-op. Ensure the example and return type remain unchanged
and reference the setNprobe method and IVF_FLAT term for clarity.

---

Nitpick comments:
In `@src/js/index.js`:
- Around line 51-55: The loop that calls validatePositiveInteger for keys
['nlist','nprobe','M','efConstruction','efSearch'] must reject
index-type-incompatible options instead of silently no-oping; update the
validation around where config and validatePositiveInteger are used (the block
iterating those keys and the similar block at 71-76) to first read the index
type (e.g., config.indexType or the variable that selects IVF vs HNSW) and then
throw or return a validation error when IVF-only options ('nlist','nprobe') are
provided for an HNSW index or when HNSW-only options
('M','efConstruction','efSearch') are provided for an IVF index; keep using
validatePositiveInteger for value checks but add explicit compatibility checks
and clear error messages referencing the offending key and the selected index
type.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 60e6b61c-596c-4f06-9b50-c568e07b50be

📥 Commits

Reviewing files that changed from the base of the PR and between 0646e3f and c0a5d23.

📒 Files selected for processing (9)
  • .coderabbit.yml
  • API.md
  • README.md
  • binding.gyp
  • src/cpp/faiss_index.cpp
  • src/cpp/faiss_index.h
  • src/cpp/napi_bindings.cpp
  • src/js/index.js
  • src/js/types.d.ts

Comment thread .coderabbit.yml Outdated
Comment thread src/cpp/faiss_index.cpp Outdated
Comment thread src/cpp/faiss_index.cpp
Comment thread src/cpp/napi_bindings.cpp Outdated
Comment thread src/js/index.js
@anupammaurya6767

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Apr 12, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@anupammaurya6767 anupammaurya6767 merged commit a756692 into main Apr 12, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant