Skip to content

Add a FreeBSD core runtime path#535

Open
lin72h wants to merge 3 commits intotobi:mainfrom
lin72h:freebsd-core/qmd
Open

Add a FreeBSD core runtime path#535
lin72h wants to merge 3 commits intotobi:mainfrom
lin72h:freebsd-core/qmd

Conversation

@lin72h
Copy link
Copy Markdown

@lin72h lin72h commented Apr 8, 2026

Summary

This PR adds the first upstreamable Node.js path for running QMD core search on FreeBSD.

The implementation keeps the existing supported-platform behavior in place, uses a real vec0.so loadable extension for FreeBSD, and avoids depending on a downstream-vendored node-llama-cpp patch.

What changed

  • added a local sqlite-vec resolver that supports QMD_SQLITE_VEC_PATH
  • updated the DB loading path to use a real loadable extension on FreeBSD
  • made sqlite-vec diagnostics platform-aware instead of Homebrew-only
  • made node-llama-cpp optional and conservative on FreeBSD so LLM commands fail fast instead of trying to auto-build through an unsupported path
  • added FreeBSD docs and a smoke harness that distinguishes the immediate --quick core path from the later --full LLM follow-up

Why this shape

FreeBSD is closer to the existing macOS system-library path than to the Linux prebuilt-binary path. The immediate upstream lane therefore prefers:

  • a real system SQLite extension (vec0.so)
  • source installs instead of a FreeBSD npm binary matrix
  • graceful LLM unavailability until upstream node-llama-cpp support lands cleanly
  • isolated platform handling instead of scattering process.platform === "freebsd" checks

Validation

Validated on a real FreeBSD 15.0 amd64 host:

  • clean pnpm install --frozen-lockfile
  • sqlite3 loading a FreeBSD-built vec0.so
  • qmd status
  • test/freebsd-smoke.sh --quick
  • clean-room replay through the local review-kit and handoff scripts
  • qmd embed failing with node-llama-cpp is unavailable instead of falling through to spawn npm ENOENT

Known limits

  • FreeBSD is Node-only for now
  • this immediate upstream lane supports BM25 and sqlite-vec features now
  • embeddings, query expansion, reranking, and full test/freebsd-smoke.sh --full remain gated on the adjacent upstream node-llama-cpp FreeBSD fix
  • the initial packaging posture is source-install-first rather than a published FreeBSD binary matrix

Related upstream dependency: asg017/sqlite-vec#282

FreeBSD Port Tooling added 3 commits April 8, 2026 12:39
Add a local sqlite-vec resolver that can load a real vec0 shared object
through QMD instead of assuming the upstream sqlite-vec npm package supports
the host platform directly.

This keeps the existing supported-platform path intact while opening a
system-library path for FreeBSD. It also makes sqlite-vec failures actionable
by routing the unavailable state through platform-aware diagnostics and tests.
Stop hard-coupling node-llama-cpp into install-time and import-time paths.

This keeps non-LLM commands usable on FreeBSD even when the native backend is
unavailable, allows runtime-specific error messages, and keeps the immediate
upstream lane conservative by defaulting FreeBSD to a non-building
node-llama-cpp policy until the adjacent upstream fix lands.
Add FreeBSD operator documentation and a host-side smoke harness that covers
both first-run bring-up and ongoing maintenance flows.

This records the validated source-checkout path explicitly and gives the port a
repeatable verification entrypoint instead of relying on manual shell history.
Copilot AI review requested due to automatic review settings April 8, 2026 01:28
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces an upstream-friendly FreeBSD runtime path for QMD’s “core” search workflow by switching sqlite-vec loading to a real loadable extension (vec0.so) and making the node-llama-cpp backend optional/conservative on FreeBSD.

Changes:

  • Add a platform-aware sqlite-vec resolver (QMD_SQLITE_VEC_PATH, FreeBSD system probing, npm binary fallback) plus improved diagnostics.
  • Make node-llama-cpp optional and add a runtime loader + error type so LLM features fail fast (especially on FreeBSD).
  • Add FreeBSD documentation, smoke harness, and new/updated tests around sqlite-vec resolution and LLM backend availability.

Reviewed changes

Copilot reviewed 12 out of 13 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
test/sqlite-vec.test.ts Adds unit tests for sqlite-vec resolution, FreeBSD probe paths, and diagnostic/error formatting.
test/llm.test.ts Adds tests for node-llama-cpp availability/error surfacing and gates integration tests behind an opt-in runtime check.
test/freebsd-smoke.sh Adds a FreeBSD smoke script with --quick vs --full validation paths.
src/store.ts Switches sqlite-vec error creation to platform-aware diagnostics.
src/platform/sqlite-vec.ts New platform helper to resolve vec0 loadable extension paths and produce platform-specific hints/errors.
src/platform/node-llama-cpp.ts New optional runtime loader + error type for node-llama-cpp.
src/llm.ts Refactors to use the runtime loader and adds FreeBSD-specific build policy behavior.
src/db.ts Switches sqlite-vec loading to loadable-extension paths and improves error reporting.
src/cli/qmd.ts Skips device probing by default on FreeBSD and makes pull fail cleanly when LLM backend is unavailable.
README.md Documents FreeBSD support posture and points to the FreeBSD guide.
pnpm-lock.yaml Moves node-llama-cpp under optionalDependencies and updates lock metadata accordingly.
package.json Makes node-llama-cpp an optional dependency.
docs/FREEBSD.md Adds FreeBSD bring-up instructions, vec0.so build steps, and smoke test guidance.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/llm.ts
build: process.platform === "freebsd" ? "never" : "autoAttempt",
logLevel: nodeLlamaCpp.LlamaLogLevel.error,
gpu,
skipDownload: process.platform !== "freebsd",
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

skipDownload is currently set to process.platform !== "freebsd", which makes it true on macOS/Linux/Windows. That appears inverted (and it conflicts with the new unit test expecting skipDownload to be false). This could prevent node-llama-cpp from performing its normal download behavior on supported platforms. Flip the condition (or omit skipDownload so the library default applies), and keep the FreeBSD behavior aligned with the intended “no auto-build” policy.

Suggested change
skipDownload: process.platform !== "freebsd",
skipDownload: process.platform === "freebsd",

Copilot uses AI. Check for mistakes.
Comment on lines +148 to +153
override readonly cause: unknown;

constructor(cause?: unknown) {
super(formatNodeLlamaCppUnavailableMessage(cause));
this.name = "NodeLlamaCppUnavailableError";
this.cause = cause;
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

NodeLlamaCppUnavailableError declares override readonly cause, but Error.cause is not readonly in the standard lib typings. This is likely to fail TypeScript structural compatibility checks under strict mode. Make cause writable (drop readonly), or rely on the built-in Error cause by calling super(message, { cause }) and not redeclaring the property.

Suggested change
override readonly cause: unknown;
constructor(cause?: unknown) {
super(formatNodeLlamaCppUnavailableMessage(cause));
this.name = "NodeLlamaCppUnavailableError";
this.cause = cause;
constructor(cause?: unknown) {
super(formatNodeLlamaCppUnavailableMessage(cause), { cause });
this.name = "NodeLlamaCppUnavailableError";

Copilot uses AI. Check for mistakes.
Comment thread test/freebsd-smoke.sh
Comment on lines +54 to +57
for cmd in node corepack git cmake ninja python3 gmake bash sqlite3 envsubst; do
require_cmd "$cmd"
done

Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

The script requires cmake and ninja unconditionally, even in --quick mode. That contradicts the stated goal of --quick being BM25 + sqlite-vec only (and the FreeBSD docs list cmake/ninja as needed only for the later LLM follow-up). Consider only requiring cmake/ninja when MODE=full (or when an LLM backend is actually needed).

Suggested change
for cmd in node corepack git cmake ninja python3 gmake bash sqlite3 envsubst; do
require_cmd "$cmd"
done
for cmd in node corepack git python3 gmake bash sqlite3 envsubst; do
require_cmd "$cmd"
done
if [ "$MODE" = "full" ]; then
for cmd in cmake ninja; do
require_cmd "$cmd"
done
fi

Copilot uses AI. Check for mistakes.
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.

2 participants