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
106 changes: 106 additions & 0 deletions .github/workflows/openclaw-plugin-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
name: OpenClaw Plugin — Build Prebuilds & Publish

on:
workflow_dispatch:
inputs:
version:
description: "Version to publish (e.g. 1.0.4 or 1.0.4-beta.1)"
required: true
tag:
description: "npm dist-tag (latest for production, beta/next/alpha for testing)"
required: true
default: "latest"

defaults:
run:
working-directory: apps/memos-local-openclaw

permissions:
contents: write

jobs:
build-prebuilds:
strategy:
matrix:
include:
- os: macos-14
platform: darwin-arm64
- os: macos-13
platform: darwin-x64
- os: ubuntu-latest
platform: linux-x64
- os: windows-latest
platform: win32-x64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: 22

- name: Install dependencies
run: npm install

- name: Collect prebuild
shell: bash
run: |
mkdir -p prebuilds/${{ matrix.platform }}
cp node_modules/better-sqlite3/build/Release/better_sqlite3.node prebuilds/${{ matrix.platform }}/

- name: Upload prebuild artifact
uses: actions/upload-artifact@v4
with:
name: prebuild-${{ matrix.platform }}
path: apps/memos-local-openclaw/prebuilds/${{ matrix.platform }}/better_sqlite3.node

publish:
needs: build-prebuilds
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: 22
registry-url: https://registry.npmjs.org

- name: Download all prebuilds
uses: actions/download-artifact@v4
with:
path: apps/memos-local-openclaw/prebuilds
pattern: prebuild-*
merge-multiple: false

- name: Organize prebuilds
run: |
cd prebuilds
for dir in prebuild-*; do
platform="${dir#prebuild-}"
mkdir -p "$platform"
mv "$dir/better_sqlite3.node" "$platform/"
rmdir "$dir"
done
echo "Prebuilds collected:"
find . -name "*.node" -exec ls -lh {} \;

- name: Install dependencies (skip native build)
run: npm install --ignore-scripts

- name: Bump version
run: npm version ${{ inputs.version }} --no-git-tag-version

- name: Publish to npm
run: npm publish --access public --tag ${{ inputs.tag }}
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Create git tag and push
working-directory: .
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add apps/memos-local-openclaw/package.json
git commit -m "release: openclaw-plugin v${{ inputs.version }}"
git tag "openclaw-plugin-v${{ inputs.version }}"
git push origin HEAD --tags
3 changes: 3 additions & 0 deletions apps/memos-local-openclaw/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ www/
docs/
ppt/

# Prebuilt native binaries (included in npm package via `files`, not in git)
prebuilds/

# Database files
*.sqlite
*.sqlite-journal
Expand Down
3 changes: 3 additions & 0 deletions apps/memos-local-openclaw/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Type } from "@sinclair/typebox";
import * as fs from "fs";
import * as path from "path";
import { buildContext } from "./src/config";
import { ensureSqliteBinding } from "./src/storage/ensure-binding";
import { SqliteStore } from "./src/storage/sqlite";
import { Embedder } from "./src/embedding";
import { IngestWorker } from "./src/ingest/worker";
Expand Down Expand Up @@ -165,6 +166,8 @@ const memosLocalPlugin = {
error: (msg: string) => api.logger.warn(`[error] ${msg}`),
});

ensureSqliteBinding(ctx.log);

const store = new SqliteStore(ctx.config.storage!.dbPath!, ctx.log);
const embedder = new Embedder(ctx.config.embedding, ctx.log);
const worker = new IngestWorker(store, embedder, ctx);
Expand Down
1 change: 1 addition & 0 deletions apps/memos-local-openclaw/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"src",
"dist",
"skill",
"prebuilds",
"scripts/postinstall.cjs",
"openclaw.plugin.json",
"README.md",
Expand Down
3 changes: 3 additions & 0 deletions apps/memos-local-openclaw/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { v4 as uuid } from "uuid";
import { buildContext } from "./config";
import { ensureSqliteBinding } from "./storage/ensure-binding";
import { SqliteStore } from "./storage/sqlite";
import { Embedder } from "./embedding";
import { IngestWorker } from "./ingest/worker";
Expand Down Expand Up @@ -54,6 +55,8 @@ export function initPlugin(opts: PluginInitOptions = {}): MemosLocalPlugin {

ctx.log.info("Initializing memos-local plugin...");

ensureSqliteBinding(ctx.log);

const store = new SqliteStore(ctx.config.storage!.dbPath!, ctx.log);
const embedder = new Embedder(ctx.config.embedding, ctx.log);
const worker = new IngestWorker(store, embedder, ctx);
Expand Down
53 changes: 53 additions & 0 deletions apps/memos-local-openclaw/src/storage/ensure-binding.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { existsSync, mkdirSync, copyFileSync } from "fs";
import { execSync } from "child_process";
import path from "path";
import { createRequire } from "module";

const require = createRequire(import.meta.url);

/**
* Ensure the better-sqlite3 native binary is available.
*
* OpenClaw installs plugins with `--ignore-scripts`, which skips
* the native compilation step. This function checks for the binary
* and restores it from bundled prebuilds if missing.
*/
export function ensureSqliteBinding(log?: { info: (msg: string) => void; warn: (msg: string) => void }): void {
const bsqlPkg = require.resolve("better-sqlite3/package.json");
const bsqlDir = path.dirname(bsqlPkg);
const bindingPath = path.join(bsqlDir, "build", "Release", "better_sqlite3.node");

if (existsSync(bindingPath)) return;

const platform = `${process.platform}-${process.arch}`;
const pluginRoot = path.resolve(path.dirname(new URL(import.meta.url).pathname), "..", "..");
const prebuildSrc = path.join(pluginRoot, "prebuilds", platform, "better_sqlite3.node");

if (existsSync(prebuildSrc)) {
log?.info(`[ensure-binding] Copying prebuild for ${platform}...`);
mkdirSync(path.dirname(bindingPath), { recursive: true });
copyFileSync(prebuildSrc, bindingPath);
log?.info(`[ensure-binding] Prebuild installed successfully.`);
return;
}

log?.warn(`[ensure-binding] No prebuild for ${platform}, attempting npm rebuild...`);
try {
const installDir = path.resolve(bsqlDir, "..", "..");
execSync("npm rebuild better-sqlite3", {
cwd: installDir,
stdio: "pipe",
timeout: 180_000,
});
if (existsSync(bindingPath)) {
log?.info(`[ensure-binding] Rebuilt better-sqlite3 successfully.`);
return;
}
} catch { /* fall through */ }

throw new Error(
`better-sqlite3 native binary not found for ${platform}.\n` +
`Prebuild not bundled and npm rebuild failed.\n` +
`Fix: cd ${path.resolve(bsqlDir, "..", "..")} && npm rebuild better-sqlite3`,
);
}
Loading