llama-cpp-capacitor 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,20 @@
1
+ require 'json'
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = 'LlamaCppCapacitor'
7
+ s.version = package['version']
8
+ s.summary = package['description']
9
+ s.license = package['license']
10
+ s.homepage = package['repository']['url']
11
+ s.author = package['author']
12
+ s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
13
+ s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
14
+ s.ios.deployment_target = '15.0'
15
+ s.dependency 'Capacitor'
16
+ s.swift_version = '5.1'
17
+
18
+ # Include the native llama-cpp framework
19
+ s.vendored_frameworks = 'ios/Frameworks/llama-cpp.framework'
20
+ end
package/README.md CHANGED
@@ -121,6 +121,21 @@ cd android
121
121
  - **iOS**: `ios/build/LlamaCpp.framework/`
122
122
  - **Android**: `android/src/main/jniLibs/{arch}/libllama-cpp-{arch}.so`
123
123
 
124
+ ### **Updating the native source (e.g. for vision model support)**
125
+
126
+ The native `cpp/` layer is based on [llama.cpp](https://github.com/ggerganov/llama.cpp). To pull in a newer upstream version (e.g. for vision model support) **without overwriting** the Capacitor adapter code, use the **bootstrap script** (included in this repo):
127
+
128
+ ```bash
129
+ ./scripts/bootstrap.sh [branch-or-tag-or-commit]
130
+ # Example: ./scripts/bootstrap.sh master
131
+ ```
132
+
133
+ This syncs upstream into `cpp/` and keeps project-specific files (`cap-*.cpp/h`, `tools/mtmd/`, etc.) intact. After running it, reconcile any API changes in the adapter code, then rebuild with `npm run build:native` or `./build-native.sh`. See [cpp/README.md](cpp/README.md) and [docs/IOS_IMPLEMENTATION_GUIDE.md](docs/IOS_IMPLEMENTATION_GUIDE.md).
134
+
135
+ ### **iOS implementation (step-by-step)**
136
+
137
+ For a **step-by-step guide** on how methods are implemented on the iOS side (Swift bridge → native framework, adding/updating C symbols, and updating the native layer for vision), see **[docs/IOS_IMPLEMENTATION_GUIDE.md](docs/IOS_IMPLEMENTATION_GUIDE.md)**.
138
+
124
139
  ### iOS Setup
125
140
 
126
141
  1. Install the plugin:
@@ -696,6 +711,17 @@ const logListener = addNativeLogListener((level, text) => {
696
711
  });
697
712
  ```
698
713
 
714
+ ## 📦 Publishing
715
+
716
+ To publish the package to npm:
717
+
718
+ 1. **Build** (runs automatically on `npm publish` via `prepublishOnly`): `npm run build` — produces `dist/` (plugin bundles, ESM, docs).
719
+ 2. **Optional — include native libs in the tarball**: `npm run build:all` (requires macOS/NDK) — builds iOS framework and Android `.so` into `ios/Frameworks` and `android/src/main/jniLibs`.
720
+ 3. **Verify pack**: `npm run pack` (JS only) or `npm run pack:full` (JS + native) — lists files that would be published.
721
+ 4. **Publish**: `npm publish`.
722
+
723
+ See [NPM_PUBLISH_GUIDE.md](NPM_PUBLISH_GUIDE.md) for 2FA/token setup and troubleshooting.
724
+
699
725
  ## 🤝 Contributing
700
726
 
701
727
  We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
@@ -0,0 +1,229 @@
1
+ #!/bin/bash
2
+
3
+ # Build script for llama-cpp Capacitor plugin
4
+ # This script compiles the native llama.cpp library for iOS and Android
5
+
6
+ set -e
7
+
8
+ # Colors for output
9
+ RED='\033[0;31m'
10
+ GREEN='\033[0;32m'
11
+ YELLOW='\033[1;33m'
12
+ BLUE='\033[0;34m'
13
+ NC='\033[0m' # No Color
14
+
15
+ # Function to print colored output
16
+ print_status() {
17
+ echo -e "${BLUE}[INFO]${NC} $1"
18
+ }
19
+
20
+ print_success() {
21
+ echo -e "${GREEN}[SUCCESS]${NC} $1"
22
+ }
23
+
24
+ print_warning() {
25
+ echo -e "${YELLOW}[WARNING]${NC} $1"
26
+ }
27
+
28
+ print_error() {
29
+ echo -e "${RED}[ERROR]${NC} $1"
30
+ }
31
+
32
+ # Check if we're on macOS for iOS builds
33
+ check_macos() {
34
+ if [[ "$OSTYPE" != "darwin"* ]]; then
35
+ print_warning "iOS builds require macOS. Skipping iOS build."
36
+ return 1
37
+ fi
38
+ return 0
39
+ }
40
+
41
+ # Check if Android SDK is available
42
+ check_android_sdk() {
43
+ if [ -z "$ANDROID_HOME" ] && [ -z "$ANDROID_SDK_ROOT" ]; then
44
+ print_warning "Android SDK not found. Please set ANDROID_HOME or ANDROID_SDK_ROOT."
45
+ print_warning "Skipping Android build."
46
+ return 1
47
+ fi
48
+ return 0
49
+ }
50
+
51
+ # Detect NDK path: ndk/<version>/build/cmake/android.toolchain.cmake
52
+ # Uses latest versioned NDK under $ANDROID_SDK/ndk/ (e.g. ndk/29.0.13113456).
53
+ detect_ndk() {
54
+ local sdk="${ANDROID_HOME:-$ANDROID_SDK_ROOT}"
55
+ local ndk_root="$sdk/ndk"
56
+ if [ ! -d "$ndk_root" ]; then
57
+ echo ""
58
+ return 1
59
+ fi
60
+ local latest=""
61
+ local latest_ver=0
62
+ for v in "$ndk_root"/*; do
63
+ [ -d "$v" ] || continue
64
+ local base=$(basename "$v")
65
+ if [[ "$base" =~ ^[0-9] ]]; then
66
+ local ver=$(echo "$base" | sed 's/[^0-9]//g' | head -c 10)
67
+ ver=${ver:-0}
68
+ if [ "$ver" -gt "$latest_ver" ] 2>/dev/null; then
69
+ latest_ver=$ver
70
+ latest=$v
71
+ fi
72
+ fi
73
+ done
74
+ if [ -n "$latest" ] && [ -f "$latest/build/cmake/android.toolchain.cmake" ]; then
75
+ echo "$latest"
76
+ return 0
77
+ fi
78
+ echo ""
79
+ return 1
80
+ }
81
+
82
+ # Build iOS library
83
+ build_ios() {
84
+ print_status "Building iOS library..."
85
+
86
+ if ! check_macos; then
87
+ return 1
88
+ fi
89
+
90
+ # Always start from a clean iOS build directory to avoid stale Xcode settings
91
+ rm -rf ios/build
92
+ mkdir -p ios/build
93
+ cd ios/build
94
+
95
+ # Configure with CMake
96
+ # IMPORTANT: build iOS framework as **ARM64-only**.
97
+ # Including x86_64 here makes CMake/Xcode try to link an x86_64 slice,
98
+ # but we only compile ARM-specific kernels (arch/arm), which leads to
99
+ # undefined symbols like lm_ggml_gemm_* for x86_64.
100
+ cmake .. \
101
+ -DCMAKE_BUILD_TYPE=Release \
102
+ -DCMAKE_OSX_ARCHITECTURES="arm64" \
103
+ -DCMAKE_OSX_DEPLOYMENT_TARGET=13.0 \
104
+ -DCMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE=NO
105
+
106
+ # Build
107
+ cmake --build . --config Release
108
+
109
+ # CMake builds the framework directly (FRAMEWORK TRUE in CMakeLists.txt)
110
+ # Verify the framework was created
111
+ if [ -d "llama-cpp.framework" ]; then
112
+ print_success "iOS framework built successfully at: $(pwd)/llama-cpp.framework"
113
+
114
+ # Strip debug symbols to reduce app store size (~0.5–1 MB)
115
+ BINARY="llama-cpp.framework/Versions/A/llama-cpp"
116
+ if [ -f "$BINARY" ]; then
117
+ if xcrun strip -x -S "$BINARY" 2>/dev/null; then
118
+ print_status "Stripped debug symbols from iOS framework"
119
+ fi
120
+ fi
121
+
122
+ # Copy framework to package location for npm publishing
123
+ mkdir -p ../Frameworks
124
+ cp -R llama-cpp.framework ../Frameworks/
125
+ print_success "iOS framework copied to ios/Frameworks/ for npm package"
126
+ else
127
+ print_error "iOS framework not found after build"
128
+ cd ../..
129
+ return 1
130
+ fi
131
+
132
+ cd ../..
133
+ }
134
+
135
+ # Build Android library
136
+ build_android() {
137
+ print_status "Building Android library..."
138
+
139
+ if ! check_android_sdk; then
140
+ return 1
141
+ fi
142
+
143
+ ANDROID_NDK=$(detect_ndk)
144
+ if [ -z "$ANDROID_NDK" ]; then
145
+ print_error "Android NDK not found. Install NDK via Android Studio (SDK Manager → NDK)."
146
+ print_error "Expected: \$ANDROID_HOME/ndk/<version>/build/cmake/android.toolchain.cmake"
147
+ return 1
148
+ fi
149
+ print_status "Using NDK: $ANDROID_NDK"
150
+
151
+ TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake"
152
+ if [ ! -f "$TOOLCHAIN_FILE" ]; then
153
+ print_error "Toolchain file not found: $TOOLCHAIN_FILE"
154
+ return 1
155
+ fi
156
+
157
+ rm -rf android/build
158
+ mkdir -p android/build
159
+ cd android/build
160
+
161
+ # Build only arm64-v8a to minimize app store size.
162
+ # build.gradle uses abiFilters 'arm64-v8a'; armeabi-v7a is not included in the app.
163
+ # Skipping armeabi-v7a saves ~25–48 MB in package and keeps app size minimal.
164
+ arch="arm64-v8a"
165
+ print_status "Building for $arch (only ABI shipped in app)..."
166
+ rm -rf CMakeCache.txt CMakeFiles Makefile cmake_install.cmake 2>/dev/null || true
167
+ find . -maxdepth 1 -name '*.so' -delete 2>/dev/null || true
168
+
169
+ cmake ../src/main \
170
+ -DCMAKE_BUILD_TYPE=Release \
171
+ -DANDROID_ABI=$arch \
172
+ -DANDROID_PLATFORM=android-21 \
173
+ -DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN_FILE" \
174
+ -DANDROID_STL=c++_shared
175
+
176
+ cmake --build . --config Release
177
+
178
+ mkdir -p ../src/main/jniLibs/$arch
179
+ if [ -f "libllama-cpp-arm64.so" ]; then
180
+ PREBUILT="$ANDROID_NDK/toolchains/llvm/prebuilt"
181
+ if [ -d "$PREBUILT/darwin-x86_64" ]; then
182
+ STRIP_TOOL="$PREBUILT/darwin-x86_64/bin/llvm-strip"
183
+ elif [ -d "$PREBUILT/darwin-aarch64" ]; then
184
+ STRIP_TOOL="$PREBUILT/darwin-aarch64/bin/llvm-strip"
185
+ else
186
+ STRIP_TOOL=$(find "$ANDROID_NDK/toolchains" -name "llvm-strip" -type f 2>/dev/null | head -1)
187
+ fi
188
+ if [ -f "$STRIP_TOOL" ]; then
189
+ "$STRIP_TOOL" --strip-debug libllama-cpp-arm64.so
190
+ print_status "Stripped debug symbols from library"
191
+ fi
192
+ cp "libllama-cpp-arm64.so" "../src/main/jniLibs/$arch/"
193
+ fi
194
+ print_success "Built for $arch"
195
+
196
+ print_success "Android library built successfully"
197
+ cd ../..
198
+ }
199
+
200
+ # Main build function
201
+ main() {
202
+ print_status "Starting llama-cpp Capacitor plugin build..."
203
+
204
+ # Check dependencies
205
+ if ! command -v cmake &> /dev/null; then
206
+ print_error "CMake is required but not installed"
207
+ exit 1
208
+ fi
209
+
210
+ if ! command -v make &> /dev/null; then
211
+ print_error "Make is required but not installed"
212
+ exit 1
213
+ fi
214
+
215
+ # Build iOS
216
+ if check_macos; then
217
+ build_ios
218
+ fi
219
+
220
+ # Build Android
221
+ if check_android_sdk; then
222
+ build_android
223
+ fi
224
+
225
+ print_success "Build completed successfully!"
226
+ }
227
+
228
+ # Run main function
229
+ main "$@"
package/cpp/README.md CHANGED
@@ -1,4 +1,15 @@
1
1
  # Note
2
2
 
3
- - Only `rn-tts.h`, `rn-tts.cpp`, `rn-mtmd.hpp`, `rn-mtmd.cpp`, `rn-llama.h` and `rn-llama.cpp` are the specific files for this folder, others are sync from [llama.cpp](https://github.com/ggerganov/llama.cpp).
4
- - We can update the native source by using the [bootstrap](../scripts/bootstrap.sh) script.
3
+ - The **project-specific** files in this folder (never overwritten by bootstrap) are:
4
+ - `cap-llama.cpp` / `cap-llama.h` Capacitor bridge (context, model load)
5
+ - `cap-completion.cpp` / `cap-completion.h` – completion
6
+ - `cap-tts.cpp` / `cap-tts.h` – TTS
7
+ - `cap-embedding.cpp` / `cap-embedding.h` – embeddings
8
+ - `cap-mtmd.hpp` – multimodal/vision
9
+ - `tools/mtmd/` – multimodal/vision tooling
10
+ - All other sources are synced from [llama.cpp](https://github.com/ggerganov/llama.cpp).
11
+ - **Update native source** (e.g. for a newer llama.cpp or vision support): run from repo root:
12
+ ```bash
13
+ ./scripts/bootstrap.sh [branch-or-tag-or-commit]
14
+ ```
15
+ See [scripts/bootstrap.sh](../scripts/bootstrap.sh) and [docs/IOS_IMPLEMENTATION_GUIDE.md](../docs/IOS_IMPLEMENTATION_GUIDE.md).