mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:10:44 +00:00
fix(memory): keep sqlite-vec optional
This commit is contained in:
@@ -52,6 +52,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Cron: preserve manual `cron.run` IDs in `cron.runs` history so manual run acknowledgements can be correlated with finished run records. Fixes #76276.
|
||||
- CLI/devices: request `operator.admin` for `openclaw devices approve <requestId>` only when the exact pending device request would mint or inherit admin-scoped operator access, while keeping lower-scope approvals on the pairing scope.
|
||||
- Memory/embedding: broaden the embedding reindex retry classifier to include transient socket-layer errors (`fetch failed`, `ECONNRESET`, `socket hang up`, `UND_ERR_*`, `closed`) so memory reindex survives provider network hiccups instead of aborting mid-run. Related #56815, #44166. (#76311) Thanks @buyitsydney.
|
||||
- Memory/search: keep sqlite-vec optional in packaged installs and point missing-extension recovery at the valid `agents.defaults.memorySearch.store.vector.extensionPath` setting. Thanks @vincentkoc.
|
||||
- Gateway: keep directly requested plugin tools invokable under restrictive tool profiles while preserving explicit deny lists and the HTTP safety deny list, preventing catalog/invoke mismatches that surface as "Tool not available". Thanks @BunsDev.
|
||||
- Gateway/update: allow beta binaries to refresh gateway services when the config was last written by the matching stable release version, avoiding false newer-config downgrade blocks during beta channel updates.
|
||||
- Channels: keep Matrix and Mattermost bundled in the core package instead of advertising external npm installs before those channels are cut over. Thanks @vincentkoc.
|
||||
|
||||
@@ -1697,7 +1697,6 @@
|
||||
"playwright-core": "1.59.1",
|
||||
"proxy-agent": "^8.0.1",
|
||||
"qrcode": "1.5.4",
|
||||
"sqlite-vec": "0.1.9",
|
||||
"tar": "7.5.13",
|
||||
"tokenjuice": "0.7.0",
|
||||
"tree-sitter-bash": "^0.25.1",
|
||||
@@ -1734,6 +1733,9 @@
|
||||
"typescript": "^6.0.3",
|
||||
"vitest": "^4.1.5"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"sqlite-vec": "0.1.9"
|
||||
},
|
||||
"overrides": {
|
||||
"@aws-sdk/client-bedrock-runtime": "$@aws-sdk/client-bedrock-runtime",
|
||||
"axios": "1.15.0",
|
||||
|
||||
@@ -1,13 +1,26 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
vi.mock("sqlite-vec", () => {
|
||||
throw new Error("bundled sqlite-vec should not load when extensionPath is explicit");
|
||||
function mockMissingSqliteVecPackage(): void {
|
||||
vi.doMock("sqlite-vec", () => {
|
||||
const err = new Error("Cannot find package 'sqlite-vec' imported from sqlite-vec.test.ts");
|
||||
Object.assign(err, { code: "ERR_MODULE_NOT_FOUND" });
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
async function importLoader() {
|
||||
return import("./sqlite-vec.js");
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
vi.doUnmock("sqlite-vec");
|
||||
vi.resetModules();
|
||||
});
|
||||
|
||||
import { loadSqliteVecExtension } from "./sqlite-vec.js";
|
||||
|
||||
describe("loadSqliteVecExtension", () => {
|
||||
it("loads explicit extensionPath without importing bundled sqlite-vec", async () => {
|
||||
mockMissingSqliteVecPackage();
|
||||
const { loadSqliteVecExtension } = await importLoader();
|
||||
const db = {
|
||||
enableLoadExtension: vi.fn(),
|
||||
loadExtension: vi.fn(),
|
||||
@@ -22,4 +35,23 @@ describe("loadSqliteVecExtension", () => {
|
||||
expect(db.enableLoadExtension).toHaveBeenCalledWith(true);
|
||||
expect(db.loadExtension).toHaveBeenCalledWith("/opt/openclaw/sqlite-vec.so");
|
||||
});
|
||||
|
||||
it("returns a valid memorySearch extensionPath hint when sqlite-vec is absent", async () => {
|
||||
mockMissingSqliteVecPackage();
|
||||
const { loadSqliteVecExtension } = await importLoader();
|
||||
const db = {
|
||||
enableLoadExtension: vi.fn(),
|
||||
loadExtension: vi.fn(),
|
||||
};
|
||||
|
||||
const result = await loadSqliteVecExtension({ db: db as never });
|
||||
|
||||
expect(result.ok).toBe(false);
|
||||
expect(result.error).toContain("sqlite-vec package is not installed.");
|
||||
expect(result.error).toContain("agents.defaults.memorySearch.store.vector.extensionPath");
|
||||
expect(result.error).toContain("agent-specific memorySearch.store.vector.extensionPath");
|
||||
expect(result.error).not.toContain("memory.store.vector.extensionPath");
|
||||
expect(db.enableLoadExtension).toHaveBeenCalledWith(true);
|
||||
expect(db.loadExtension).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -8,11 +8,24 @@ type SqliteVecModule = {
|
||||
};
|
||||
|
||||
const SQLITE_VEC_MODULE_ID = "sqlite-vec";
|
||||
const SQLITE_VEC_CONFIG_HINT =
|
||||
"Set agents.defaults.memorySearch.store.vector.extensionPath, or an agent-specific memorySearch.store.vector.extensionPath, to a sqlite-vec loadable extension path.";
|
||||
|
||||
async function loadSqliteVecModule(): Promise<SqliteVecModule> {
|
||||
return import(SQLITE_VEC_MODULE_ID) as Promise<SqliteVecModule>;
|
||||
}
|
||||
|
||||
function isMissingSqliteVecPackageError(err: unknown): boolean {
|
||||
const message = formatErrorMessage(err);
|
||||
const code =
|
||||
err && typeof err === "object" && "code" in err ? (err as { code?: unknown }).code : undefined;
|
||||
const missingSqliteVec = /Cannot find (?:package|module) ['"]sqlite-vec['"]/u.test(message);
|
||||
return (
|
||||
missingSqliteVec &&
|
||||
(code === undefined || code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND")
|
||||
);
|
||||
}
|
||||
|
||||
export async function loadSqliteVecExtension(params: {
|
||||
db: DatabaseSync;
|
||||
extensionPath?: string;
|
||||
@@ -31,6 +44,12 @@ export async function loadSqliteVecExtension(params: {
|
||||
return { ok: true, extensionPath };
|
||||
} catch (err) {
|
||||
const message = formatErrorMessage(err);
|
||||
if (isMissingSqliteVecPackageError(err)) {
|
||||
return {
|
||||
ok: false,
|
||||
error: `sqlite-vec package is not installed. ${SQLITE_VEC_CONFIG_HINT} Original error: ${message}`,
|
||||
};
|
||||
}
|
||||
return { ok: false, error: message };
|
||||
}
|
||||
}
|
||||
|
||||
7
pnpm-lock.yaml
generated
7
pnpm-lock.yaml
generated
@@ -184,9 +184,6 @@ importers:
|
||||
qrcode:
|
||||
specifier: 1.5.4
|
||||
version: 1.5.4
|
||||
sqlite-vec:
|
||||
specifier: 0.1.9
|
||||
version: 0.1.9
|
||||
tar:
|
||||
specifier: 7.5.13
|
||||
version: 7.5.13
|
||||
@@ -220,6 +217,10 @@ importers:
|
||||
zod:
|
||||
specifier: ^4.4.1
|
||||
version: 4.4.1
|
||||
optionalDependencies:
|
||||
sqlite-vec:
|
||||
specifier: 0.1.9
|
||||
version: 0.1.9
|
||||
devDependencies:
|
||||
'@copilotkit/aimock':
|
||||
specifier: 1.16.4
|
||||
|
||||
Reference in New Issue
Block a user