Skip to content

Commit d6c6485

Browse files
committed
feat(packages): add @sqliteai/sqlite-ai Node package
1 parent 96f8134 commit d6c6485

File tree

14 files changed

+1030
-12
lines changed

14 files changed

+1030
-12
lines changed

.github/workflows/main.yml

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
build:
1111
runs-on: ${{ matrix.os }}
1212
container: ${{ matrix.container && matrix.container || '' }}
13-
name: ${{ matrix.name }}${{ matrix.arch && format('-{0}', matrix.arch) || '' }} build${{ matrix.arch != 'arm64-v8a' && matrix.name != 'ios-sim' && matrix.name != 'ios' && matrix.name != 'apple-xcframework' && matrix.name != 'android-aar' && ' + test' || ''}}
13+
name: ${{ matrix.name }}${{ matrix.arch && format('-{0}', matrix.arch) || '' }} build${{ matrix.arch != 'arm64-v8a' && matrix.name != 'ios-sim' && matrix.name != 'ios' && matrix.name != 'apple-xcframework' && matrix.name != 'android-aar' && ( matrix.name != 'macos' || matrix.arch != 'x86_64' ) && ' + test' || ''}}
1414
timeout-minutes: 120
1515
strategy:
1616
fail-fast: false
@@ -19,6 +19,14 @@ jobs:
1919
- os: macos-15
2020
name: macos
2121
make: LLAMA="-DGGML_NATIVE=OFF -DGGML_METAL=ON -DGGML_ACCELERATE=ON -DGGML_BLAS=ON -DGGML_BLAS_VENDOR=Apple" WHISPER="-DWHISPER_COREML=ON -DWHISPER_COREML_ALLOW_FALLBACK=ON"
22+
- os: macos-15
23+
arch: x86_64
24+
name: macos
25+
make: ARCH=x86_64 LLAMA="-DGGML_NATIVE=OFF -DGGML_METAL=ON -DGGML_ACCELERATE=ON -DGGML_BLAS=ON -DGGML_BLAS_VENDOR=Apple" WHISPER="-DWHISPER_COREML=ON -DWHISPER_COREML_ALLOW_FALLBACK=ON"
26+
- os: macos-15
27+
arch: arm64
28+
name: macos
29+
make: ARCH=arm64 LLAMA="-DGGML_NATIVE=OFF -DGGML_METAL=ON -DGGML_ACCELERATE=ON -DGGML_BLAS=ON -DGGML_BLAS_VENDOR=Apple" WHISPER="-DWHISPER_COREML=ON -DWHISPER_COREML_ALLOW_FALLBACK=ON"
2230
- os: ubuntu-22.04
2331
arch: x86_64
2432
name: linux-cpu
@@ -363,7 +371,7 @@ jobs:
363371
VULKAN_SDK: "C:/msys64/mingw64"
364372

365373
- name: unix test sqlite-ai
366-
if: contains(matrix.name, 'linux') || matrix.name == 'macos'
374+
if: contains(matrix.name, 'linux') || ( matrix.name == 'macos' && matrix.arch != 'x86_64' )
367375
run: ${{ contains(matrix.name, 'linux-musl') && matrix.arch == 'arm64' && 'docker exec alpine' || '' }} make test ${{ matrix.make && matrix.make || ''}}
368376

369377
- uses: actions/[email protected]
@@ -465,9 +473,82 @@ jobs:
465473
if: steps.tag.outputs.version != ''
466474
run: cd packages/android && ./gradlew publishAggregationToCentralPortal -PSIGNING_KEY="${{ secrets.SIGNING_KEY }}" -PSIGNING_PASSWORD="${{ secrets.SIGNING_PASSWORD }}" -PSONATYPE_USERNAME="${{ secrets.MAVEN_CENTRAL_USERNAME }}" -PSONATYPE_PASSWORD="${{ secrets.MAVEN_CENTRAL_TOKEN }}" -PVERSION="${{ steps.tag.outputs.version }}" -PAAR_PATH="../../artifacts/ai-android-aar/ai.aar"
467475

476+
- uses: actions/setup-node@v4
477+
if: steps.tag.outputs.version != ''
478+
with:
479+
node-version: '20'
480+
registry-url: 'https://registry.npmjs.org'
481+
482+
- name: build and publish npm packages
483+
if: steps.tag.outputs.version != ''
484+
env:
485+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
486+
run: |
487+
cd packages/node
488+
489+
# Update version in package.json
490+
echo "Updating versions to ${{ steps.tag.outputs.version }}..."
491+
492+
# Update package.json
493+
jq --arg version "${{ steps.tag.outputs.version }}" \
494+
'.version = $version | .optionalDependencies = (.optionalDependencies | with_entries(.value = $version))' \
495+
package.json > package.tmp.json && mv package.tmp.json package.json
496+
497+
echo "✓ Updated package.json to version ${{ steps.tag.outputs.version }}"
498+
499+
# Generate platform packages
500+
echo "Generating platform packages..."
501+
node generate-platform-packages.js "${{ steps.tag.outputs.version }}" "../../artifacts" "./platform-packages"
502+
echo "✓ Generated 7 platform packages"
503+
ls -la platform-packages/
504+
505+
# Build main package
506+
echo "Building main package..."
507+
npm install
508+
npm run build
509+
npm test
510+
echo "✓ Main package built and tested"
511+
512+
# Publish platform packages
513+
echo "Publishing platform packages to npm..."
514+
cd platform-packages
515+
for platform_dir in */; do
516+
platform_name=$(basename "$platform_dir")
517+
echo " Publishing @sqliteai/sqlite-ai-${platform_name}..."
518+
cd "$platform_dir"
519+
npm publish --access public
520+
# TODO: Add --provenance flag after switching to OIDC (requires package to exist first)
521+
cd ..
522+
echo " ✓ Published @sqliteai/sqlite-ai-${platform_name}"
523+
done
524+
cd ..
525+
526+
# Publish main package
527+
echo "Publishing main package to npm..."
528+
npm publish --access public
529+
# TODO: Add --provenance flag after switching to OIDC (requires package to exist first)
530+
echo "✓ Published @sqliteai/sqlite-ai@${{ steps.tag.outputs.version }}"
531+
532+
echo ""
533+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
534+
echo "✅ Successfully published 8 packages to npm"
535+
echo " Main: @sqliteai/sqlite-ai@${{ steps.tag.outputs.version }}"
536+
echo " Platform packages: 7"
537+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
538+
468539
- uses: softprops/[email protected]
469540
if: steps.tag.outputs.version != ''
470541
with:
542+
body: |
543+
# Packages
544+
545+
[**Node**](https://www.npmjs.com/package/@sqliteai/sqlite-ai): `npm install @sqliteai/sqlite-ai`
546+
[**Android**](https://central.sonatype.com/artifact/ai.sqlite/ai): `ai.sqlite:ai:${{ steps.tag.outputs.version }}`
547+
[**Python**](https://pypi.org/project/sqlite-ai): `pip install sqlite-ai`
548+
[**Swift**](https://github.com/sqliteai/sqlite-ai#swift-package): [Installation Guide](https://github.com/sqliteai/sqlite-ai#swift-package)
549+
550+
---
551+
471552
generate_release_notes: true
472553
tag_name: ${{ steps.tag.outputs.version }}
473554
files: ai-*-${{ steps.tag.outputs.version }}.*

.gitignore

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Build artifacts
22
build/
3-
/dist
3+
dist/
44
.build
55
*.a
66
*.sqlite
@@ -21,10 +21,27 @@ jniLibs/
2121
*.ap_
2222
*.dex
2323

24+
# Node.js
25+
node_modules/
26+
package-lock.json
27+
*.tsbuildinfo
28+
coverage/
29+
*.log
30+
npm-debug.log*
31+
yarn-debug.log*
32+
yarn-error.log*
33+
packages/node/platform-packages/
34+
packages/node/test-artifacts/
35+
packages/node/test-output/
36+
packages/node/test-platform-packages/
37+
2438
# IDE
2539
.vscode
2640
.idea/
2741
*.iml
42+
*.swp
43+
*.swo
2844

2945
# System
30-
.DS_Store
46+
.DS_Store
47+
Thumbs.db

Makefile

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,20 @@ ifeq ($(PLATFORM),windows)
7272
else ifeq ($(PLATFORM),macos)
7373
TARGET := $(DIST_DIR)/ai.dylib
7474
LLAMA_LIBS += $(BUILD_GGML)/lib/libggml-metal.a
75-
LDFLAGS += -arch x86_64 -arch arm64 -L./$(BUILD_GGML)/lib -lggml-metal -L./$(BUILD_GGML)/lib -framework Metal -framework Foundation -framework CoreFoundation -framework QuartzCore -dynamiclib -undefined dynamic_lookup
76-
CFLAGS += -arch x86_64 -arch arm64
77-
LLAMA_OPTIONS += -DGGML_OPENMP=OFF -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0
78-
WHISPER_OPTIONS += -DGGML_OPENMP=OFF -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0
79-
MINIAUDIO_OPTIONS += -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0
75+
ifndef ARCH
76+
LDFLAGS += -arch x86_64 -arch arm64
77+
CFLAGS += -arch x86_64 -arch arm64
78+
LLAMA_OPTIONS += -DGGML_OPENMP=OFF -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0
79+
WHISPER_OPTIONS += -DGGML_OPENMP=OFF -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0
80+
MINIAUDIO_OPTIONS += -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0
81+
else
82+
LDFLAGS += -arch $(ARCH)
83+
CFLAGS += -arch $(ARCH)
84+
LLAMA_OPTIONS += -DGGML_OPENMP=OFF -DCMAKE_OSX_ARCHITECTURES="$(ARCH)" -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0
85+
WHISPER_OPTIONS += -DGGML_OPENMP=OFF -DCMAKE_OSX_ARCHITECTURES="$(ARCH)" -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0
86+
MINIAUDIO_OPTIONS += -DCMAKE_OSX_ARCHITECTURES="$(ARCH)" -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0
87+
endif
88+
LDFLAGS += -L./$(BUILD_GGML)/lib -lggml-metal -L./$(BUILD_GGML)/lib -framework Metal -framework Foundation -framework CoreFoundation -framework QuartzCore -dynamiclib -undefined dynamic_lookup -headerpad_max_install_names
8089
STRIP = strip -x -S $@
8190
else ifeq ($(PLATFORM),android)
8291
ifndef ARCH # Set ARCH to find Android NDK's Clang compiler, the user should set the ARCH
@@ -106,7 +115,7 @@ else ifeq ($(PLATFORM),ios)
106115
TARGET := $(DIST_DIR)/ai.dylib
107116
SDK := -isysroot $(shell xcrun --sdk iphoneos --show-sdk-path) -miphoneos-version-min=14.0
108117
LLAMA_LIBS += $(BUILD_GGML)/lib/libggml-metal.a
109-
LDFLAGS += -L./$(BUILD_GGML)/lib -lggml-metal -L./$(BUILD_GGML)/lib -framework Accelerate -framework Metal -framework Foundation -framework AVFoundation -framework AudioToolbox -framework CoreAudio -framework CoreFoundation -framework Security -ldl -lpthread -lm -dynamiclib $(SDK)
118+
LDFLAGS += -L./$(BUILD_GGML)/lib -lggml-metal -L./$(BUILD_GGML)/lib -framework Accelerate -framework Metal -framework Foundation -framework AVFoundation -framework AudioToolbox -framework CoreAudio -framework CoreFoundation -framework Security -ldl -lpthread -lm -dynamiclib $(SDK) -headerpad_max_install_names
110119
CFLAGS += -arch arm64 -x objective-c $(SDK)
111120
LLAMA_OPTIONS += -DGGML_OPENMP=OFF -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_DEPLOYMENT_TARGET=14.0
112121
WHISPER_OPTIONS += -DGGML_OPENMP=OFF -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_DEPLOYMENT_TARGET=14.0
@@ -116,7 +125,7 @@ else ifeq ($(PLATFORM),ios-sim)
116125
TARGET := $(DIST_DIR)/ai.dylib
117126
SDK := -isysroot $(shell xcrun --sdk iphonesimulator --show-sdk-path) -miphonesimulator-version-min=14.0
118127
LLAMA_LIBS += $(BUILD_GGML)/lib/libggml-metal.a
119-
LDFLAGS += -arch x86_64 -arch arm64 -L./$(BUILD_GGML)/lib -lggml-metal -L./$(BUILD_GGML)/lib -framework Accelerate -framework Metal -framework Foundation -framework AVFoundation -framework AudioToolbox -framework CoreAudio -framework CoreFoundation -framework Security -ldl -lpthread -lm -dynamiclib $(SDK)
128+
LDFLAGS += -arch x86_64 -arch arm64 -L./$(BUILD_GGML)/lib -lggml-metal -L./$(BUILD_GGML)/lib -framework Accelerate -framework Metal -framework Foundation -framework AVFoundation -framework AudioToolbox -framework CoreAudio -framework CoreFoundation -framework Security -ldl -lpthread -lm -dynamiclib $(SDK) -headerpad_max_install_names
120129
CFLAGS += -arch x86_64 -arch arm64 -x objective-c $(SDK)
121130
LLAMA_OPTIONS += -DGGML_OPENMP=OFF -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=14.0 -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
122131
WHISPER_OPTIONS += -DGGML_OPENMP=OFF -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=14.0 -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"

packages/node/.npmignore

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Development and build files
2+
src/
3+
*.test.ts
4+
*.test.js
5+
tsconfig.json
6+
tsup.config.ts
7+
8+
# Scripts (only for repo/CI)
9+
generate-platform-packages.js
10+
11+
# Development files
12+
node_modules/
13+
package-lock.json
14+
coverage/
15+
*.log
16+
17+
# Git
18+
.git/
19+
.gitignore

packages/node/LICENSE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../LICENSE.md

packages/node/README.md

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# @sqliteai/sqlite-ai
2+
3+
[![npm version](https://badge.fury.io/js/@sqliteai%2Fsqlite-ai.svg)](https://www.npmjs.com/package/@sqliteai/sqlite-ai)
4+
[![License](https://img.shields.io/badge/license-Elastic%202.0-blue.svg)](LICENSE.md)
5+
6+
> SQLite AI extension packaged for Node.js
7+
8+
**SQLite-AI** is an extension for SQLite that brings artificial intelligence capabilities directly into the database. It enables developers to run, fine-tune, and serve AI models from within SQLite using simple SQL queries — ideal for on-device and edge applications where low-latency and offline inference are critical. The extension is actively developed by [SQLite AI](https://sqlite.ai), some API and features are still evolving.
9+
10+
## Features
11+
12+
-**LLaMA Integration** - Run LLaMA models directly in SQLite
13+
-**Whisper Speech Recognition** - Transcribe audio with Whisper
14+
-**Embedding Generation** - Generate vector embeddings for semantic search
15+
-**Cross-platform** - Works on macOS, Linux (glibc/musl), and Windows
16+
-**Zero configuration** - Automatically detects and loads the correct binary for your platform
17+
-**TypeScript native** - Full type definitions included
18+
-**Modern ESM + CJS** - Works with both ES modules and CommonJS
19+
-**Offline-ready** - No external services required
20+
21+
## Installation
22+
23+
```bash
24+
npm install @sqliteai/sqlite-ai
25+
```
26+
27+
The package automatically downloads the correct native extension for your platform during installation.
28+
29+
### Supported Platforms
30+
31+
| Platform | Architecture | Package |
32+
|----------|-------------|---------|
33+
| macOS | ARM64 (Apple Silicon) | `@sqliteai/sqlite-ai-darwin-arm64` |
34+
| macOS | x86_64 (Intel) | `@sqliteai/sqlite-ai-darwin-x86_64` |
35+
| Linux | ARM64 (glibc) | `@sqliteai/sqlite-ai-linux-arm64` |
36+
| Linux | ARM64 (musl/Alpine) | `@sqliteai/sqlite-ai-linux-arm64-musl` |
37+
| Linux | x86_64 (glibc) | `@sqliteai/sqlite-ai-linux-x86_64` |
38+
| Linux | x86_64 (musl/Alpine) | `@sqliteai/sqlite-ai-linux-x86_64-musl` |
39+
| Windows | x86_64 | `@sqliteai/sqlite-ai-win32-x86_64` |
40+
41+
## sqlite-ai API
42+
43+
For detailed information on how to use the AI extension features, see the [main documentation](https://github.com/sqliteai/sqlite-ai/blob/main/API.md).
44+
45+
## Usage
46+
47+
```typescript
48+
import { getExtensionPath } from '@sqliteai/sqlite-ai';
49+
import Database from 'better-sqlite3';
50+
51+
const db = new Database(':memory:');
52+
db.loadExtension(getExtensionPath());
53+
54+
// Ready to use
55+
const version = db.prepare('SELECT ai_version()').pluck().get();
56+
console.log('AI extension version:', version);
57+
```
58+
59+
## Examples
60+
61+
For complete, runnable examples, see the [sqlite-extensions-guide](https://github.com/sqliteai/sqlite-extensions-guide/tree/main/examples/node).
62+
63+
These examples are generic and work with all SQLite extensions: `sqlite-vector`, `sqlite-sync`, `sqlite-js`, and `sqlite-ai`.
64+
65+
## API Reference
66+
67+
### `getExtensionPath(): string`
68+
69+
Returns the absolute path to the SQLite AI extension binary for the current platform.
70+
71+
**Returns:** `string` - Absolute path to the extension file (`.so`, `.dylib`, or `.dll`)
72+
73+
**Throws:** `ExtensionNotFoundError` - If the extension binary cannot be found for the current platform
74+
75+
**Example:**
76+
```typescript
77+
import { getExtensionPath } from '@sqliteai/sqlite-ai';
78+
79+
const path = getExtensionPath();
80+
// => '/path/to/node_modules/@sqliteai/sqlite-ai-darwin-arm64/ai.dylib'
81+
```
82+
83+
---
84+
85+
### `getExtensionInfo(): ExtensionInfo`
86+
87+
Returns detailed information about the extension for the current platform.
88+
89+
**Returns:** `ExtensionInfo` object with the following properties:
90+
- `platform: Platform` - Current platform identifier (e.g., `'darwin-arm64'`)
91+
- `packageName: string` - Name of the platform-specific npm package
92+
- `binaryName: string` - Filename of the binary (e.g., `'ai.dylib'`)
93+
- `path: string` - Full path to the extension binary
94+
95+
**Throws:** `ExtensionNotFoundError` - If the extension binary cannot be found
96+
97+
**Example:**
98+
```typescript
99+
import { getExtensionInfo } from '@sqliteai/sqlite-ai';
100+
101+
const info = getExtensionInfo();
102+
console.log(`Running on ${info.platform}`);
103+
console.log(`Extension path: ${info.path}`);
104+
```
105+
106+
---
107+
108+
### `getCurrentPlatform(): Platform`
109+
110+
Returns the current platform identifier.
111+
112+
**Returns:** `Platform` - One of:
113+
- `'darwin-arm64'` - macOS ARM64
114+
- `'darwin-x86_64'` - macOS x86_64
115+
- `'linux-arm64'` - Linux ARM64 (glibc)
116+
- `'linux-arm64-musl'` - Linux ARM64 (musl)
117+
- `'linux-x86_64'` - Linux x86_64 (glibc)
118+
- `'linux-x86_64-musl'` - Linux x86_64 (musl)
119+
- `'win32-x86_64'` - Windows x86_64
120+
121+
**Throws:** `Error` - If the platform is unsupported
122+
123+
---
124+
125+
### `isMusl(): boolean`
126+
127+
Detects if the system uses musl libc (Alpine Linux, etc.).
128+
129+
**Returns:** `boolean` - `true` if musl is detected, `false` otherwise
130+
131+
---
132+
133+
### `class ExtensionNotFoundError extends Error`
134+
135+
Error thrown when the SQLite AI extension cannot be found for the current platform.
136+
137+
## Related Projects
138+
139+
- **[@sqliteai/sqlite-vector](https://www.npmjs.com/package/@sqliteai/sqlite-vector)** - Vector search and similarity matching
140+
- **[@sqliteai/sqlite-sync](https://www.npmjs.com/package/@sqliteai/sqlite-sync)** - Sync on-device databases with the cloud
141+
- **[@sqliteai/sqlite-js](https://www.npmjs.com/package/@sqliteai/sqlite-js)** - Define SQLite functions in JavaScript
142+
143+
## License
144+
145+
This project is licensed under the [Elastic License 2.0](LICENSE.md).
146+
147+
For production or managed service use, please [contact SQLite Cloud, Inc](mailto:[email protected]) for a commercial license.
148+
149+
## Contributing
150+
151+
Contributions are welcome! Please see the [main repository](https://github.com/sqliteai/sqlite-ai) to open an issue.
152+
153+
## Support
154+
155+
- 📖 [Documentation](https://github.com/sqliteai/sqlite-ai/blob/main/API.md)
156+
- 🐛 [Report Issues](https://github.com/sqliteai/sqlite-ai/issues)

0 commit comments

Comments
 (0)