Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ jobs:

# Inspect the artifact we just shipped. This is the check that was missing
# when v1.2.0 went out ad-hoc signed, hardened-runtime, and unable to load
# better_sqlite3.node.
# its native module.
- name: Verify macOS artifact (signature, entitlements, native modules)
if: matrix.os == 'macos-latest'
run: |
Expand Down Expand Up @@ -220,7 +220,7 @@ jobs:
echo "::warning title=Unsigned macOS build::No identity was available, so the bundle carries no entitlements. This build is not notarized and cannot be launched on Apple Silicon until the user clears the quarantine flag; README.md documents the command."
else
echo "::error::shipped app is missing com.apple.security.cs.disable-library-validation."
echo "::error::It will crash on launch when the main process loads better_sqlite3.node."
echo "::error::It will crash on launch when the main process loads better-sqlite3's native module."
exit 1
fi

Expand All @@ -236,8 +236,11 @@ jobs:
echo
done

if ! echo "$NATIVES" | grep -q 'better_sqlite3.node'; then
echo "::error::better_sqlite3.node was not unpacked; the database will fail to open"
# better-sqlite3 >= 13 is N-API and ships its binary as
# `prebuilds/<platform>-<arch>.node`, not the old
# `build/Release/better_sqlite3.node`, and nothing rebuilds it.
if ! echo "$NATIVES" | grep -qE 'better-sqlite3/prebuilds/.+\.node'; then
echo "::error::a better-sqlite3 prebuild was not unpacked; the database will fail to open"
exit 1
fi

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ name: Verify
# it, so it is the step that actually catches those. It runs on all three
# platforms because the native addons are arch-specific:
#
# better_sqlite3.node, vec0.so/.dylib/.dll, skia.*.node
# better-sqlite3 (prebuilds/<platform>-<arch>.node), vec0.so/.dylib/.dll, skia.*.node
#
# `lint` is deliberately not part of this gate: it reports no errors but still
# carries a large pre-existing `@typescript-eslint/no-explicit-any` baseline,
Expand Down
9 changes: 5 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ Requirements:
`electron-builder` is built around npm's `node_modules` layout and silently
drops transitive dependencies under pnpm. See the `//dependencies` comment in
`package.json` for the full story.
- A working native build toolchain. `npm install` runs
`electron-builder install-app-deps` as a `postinstall` step, which compiles
the native addons (`better-sqlite3`, `sqlite-vec`), so the first install
takes a while.
- **No native build toolchain.** Every native dependency is N-API and ships
prebuilt binaries, most of them inside the npm package itself
(`better-sqlite3` >= 13 carries `prebuilds/` for every supported
platform/arch), so `npm install` compiles nothing and `npmRebuild` is off.
See the `npmRebuild` note in `electron-builder.yml`.

```bash
git clone https://github.com/MrSibe/KnowNote.git
Expand Down
3 changes: 2 additions & 1 deletion build/entitlements.mac.plist
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
<true/>
<!--
REQUIRED. The main process dlopen()s third-party prebuilt native modules
(better_sqlite3.node, vec0.dylib, skia.darwin-arm64.node) that are not
(better-sqlite3's prebuilds/darwin-arm64.node, vec0.dylib,
skia.darwin-arm64.node) that are not
signed by the same team as this app. Hardened Runtime enforces that every
loaded library shares the process Team ID, so without this entitlement the
app aborts at launch with:
Expand Down
28 changes: 20 additions & 8 deletions docs/dependency-audit.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ Consequences that matter:
`sharp` and `@mixmark-io/domino` are transitive dependencies of `@huggingface/transformers` and
`turndown` respectively that are **deliberately promoted so they ship**; neither is imported by
this repository's source.
3. `better-sqlite3` is rebuilt against the Electron ABI during packaging. It **cannot be loaded
from plain Node** (`require('better-sqlite3')` fails), so any question about the shipped SQLite
has to be answered inside Electron — see the FTS5 section.
3. `better-sqlite3` (>= 13) is N-API and ships a prebuild per platform/arch inside its own npm
package, so nothing compiles it and the same binary loads in plain Node and in Electron.
`npmRebuild` is off in `electron-builder.yml` and there is no `postinstall` rebuild step;
see the `npmRebuild` note there for why that is now the correct setting.

## 1. `sqlite-vec` — KEEP

Expand Down Expand Up @@ -160,9 +161,18 @@ harness runs real retrieval against a real model, so this is exercised rather th
| `onnxruntime-node` | **155 MB**, of which **152.7 MB is binaries** |
| `@napi-rs` | 32 MB |
| `@img` (sharp/libvips) | 19 MB |
| `better-sqlite3` | 13 MB |
| `better-sqlite3` | 27 MB |
| `sqlite-vec` | 156 KB |

`better-sqlite3` grew from 13 MB to 27 MB with 13.x: it is N-API now and ships a prebuild for
**every** supported platform/arch inside the npm package instead of one ABI-specific binary. That is
the trade that removes the Electron-ABI rebuild, so the size is expected, not a regression.

The `onnxruntime-node` row above is stale and predates the payload this build now carries:
`libonnxruntime_providers_cuda.so` alone is ~260 MB on linux/x64, taking the package to ~416 MB
packed. That is the same "ships binaries for the wrong platform" problem this section already
describes, only larger, and pruning it remains its own follow-up.

Of the 152.7 MB of onnxruntime binaries, only `linux/x64/libonnxruntime.so.1` (**43.7 MB**) is
usable by this build. The remaining **~109 MB (72%) is for other platforms and architectures**:

Expand Down Expand Up @@ -192,8 +202,10 @@ in `dependencies`.

#77 wants BM25/hybrid retrieval, and SQLite's BM25 lives in the FTS5 module. Whether FTS5 exists is
a property of the SQLite that `better-sqlite3` bundles, not of anything this repository compiles, so
it had to be answered against the **shipped** build. It cannot be answered from plain Node at all:
`better-sqlite3` is rebuilt for the Electron ABI and fails to load there.
it had to be answered against the **shipped** build. It used to have to run inside Electron
because `better-sqlite3` was compiled against the Electron ABI and refused to load in plain Node;
since `better-sqlite3` 13 (N-API) the same prebuild loads in both. The check still runs in the
packaged app, because that is the build users actually run.

The check now lives in the packaged smoke test (`src/main/smokeTest.ts`) and inserts, matches and
ranks rather than only reading a compile flag, because a flag is not proof that `MATCH` and `bm25()`
Expand All @@ -203,13 +215,13 @@ Result from `npm run build:unpack && npm run smoke:packaged`:

```text
[SmokeTest] ok sqlite-vec reports version v0.1.9
[SmokeTest] ok FTS5 is available and ranks: sqlite 3.53.2, ENABLE_FTS5 flag present,
[SmokeTest] ok FTS5 is available and ranks: sqlite 3.53.4, ENABLE_FTS5 flag present,
bm25() = -9.447852760736198e-7
[SmokeTest] PASS - 29 checks passed
```

**FTS5 is available: `ENABLE_FTS5` is compiled in, `MATCH` returned the expected row, and `bm25()`
produced a usable rank on SQLite 3.53.2.** #77 therefore has no blocker from the SQLite side, and
produced a usable rank on SQLite 3.53.4.** #77 therefore has no blocker from the SQLite side, and
BM25/hybrid is a design choice rather than a build constraint.

## How to reproduce
Expand Down
27 changes: 21 additions & 6 deletions electron-builder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,27 @@ appImage:
# electron-builder >= 26.16.0. Missing *optional* dependencies (e.g. fsevents on
# Linux/Windows) are still allowed and never fail the build.
allowMissingDependencies: false
# `npmRebuild` is intentionally left at its default (true) so electron-builder
# rebuilds better-sqlite3 against the target Electron ABI and target
# architecture while packaging. Turning it off, as this project previously did,
# makes the shipped binary depend on whatever ABI `postinstall` happened to
# produce on the build host, which breaks cross-arch builds such as
# `build:mac --arm64`. The postinstall hook is kept for `dev`/`preview`.
# Every native dependency here is N-API, so electron-builder has nothing to
# rebuild: `better-sqlite3` (>= 13) ships a prebuild per platform/arch inside its
# own npm package, `onnxruntime-node` ships `bin/napi-v6/<platform>/<arch>`, and
# `sharp` / `@napi-rs/canvas` ship platform packages. N-API binaries are stable
# across Node and Electron versions, so rebuilding cannot improve them and can
# only replace a correct prebuild with a locally compiled one.
#
# Leaving this at the default (true) is what broke `npm install` on a plain
# Windows machine once the runtime moved to Electron 44 (ABI 149): published
# better-sqlite3 12.x prebuilds stop at ABI 146, so @electron/rebuild fell back
# to `node-gyp rebuild --build-from-source` and demanded Python + MSVC.
#
# Cross-arch still works because the prebuilds are shipped for every supported
# target: `better-sqlite3` carries darwin/linux/win32 prebuilds for x64 and
# arm64, and `onnxruntime-node` carries every platform in one package. The
# release matrix builds each artifact on its own architecture.
#
# `postinstall` no longer runs `electron-builder install-app-deps`: that command
# ignores this flag and always rebuilds, which would reintroduce the toolchain
# requirement for `npm install` even though nothing needs compiling.
npmRebuild: false
# Published as a DRAFT: electron-builder uploads the artifacts, but the release
# only becomes public after every platform built and the macOS artifact passed
# the verification step in .github/workflows/release.yml.
Expand Down
Loading
Loading