115 lines
3.2 KiB
JavaScript
115 lines
3.2 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { mkdtempSync, rmSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import path from "node:path";
|
|
|
|
import { Command } from "commander";
|
|
import jitiFactory from "jiti";
|
|
|
|
const jiti = jitiFactory(import.meta.url, { interopDefault: true });
|
|
|
|
async function createSourceDb(sourceDbPath) {
|
|
// Create a minimal LanceDB database with a `memories` table and 1 row.
|
|
const { loadLanceDB } = jiti("../src/store.ts");
|
|
const lancedb = await loadLanceDB();
|
|
const db = await lancedb.connect(sourceDbPath);
|
|
|
|
// Create table if missing.
|
|
// LanceDB JS API supports createTable(name, data).
|
|
const row = {
|
|
id: "test_smoke_1",
|
|
text: "hello from smoke test",
|
|
category: "other",
|
|
scope: "global",
|
|
importance: 0.7,
|
|
timestamp: Date.now(),
|
|
metadata: "{}",
|
|
vector: [0, 0, 0, 0],
|
|
};
|
|
|
|
try {
|
|
await db.createTable("memories", [row]);
|
|
} catch {
|
|
// If already exists, ignore.
|
|
const table = await db.openTable("memories");
|
|
await table.add([row]);
|
|
}
|
|
}
|
|
|
|
async function runCliSmoke() {
|
|
const workDir = mkdtempSync(path.join(tmpdir(), "memory-lancedb-pro-smoke-"));
|
|
const sourceDbPath = path.join(workDir, "source-db");
|
|
|
|
await createSourceDb(sourceDbPath);
|
|
|
|
const { createMemoryCLI } = jiti("../cli.ts");
|
|
|
|
const program = new Command();
|
|
program.exitOverride();
|
|
|
|
const context = {
|
|
// Minimal store interface for reembed dry-run.
|
|
store: { dbPath: path.join(workDir, "target-db") },
|
|
retriever: {},
|
|
scopeManager: {},
|
|
migrator: {},
|
|
// Presence required, but dry-run exits before embeddings.
|
|
embedder: {},
|
|
};
|
|
|
|
// Register commands under `memory-pro`
|
|
createMemoryCLI(context)({ program });
|
|
|
|
// 1) version command should not throw
|
|
await program.parseAsync(["node", "openclaw", "memory-pro", "version"]);
|
|
|
|
// 2) reembed dry-run should not crash (regression test for clampInt)
|
|
await program.parseAsync([
|
|
"node",
|
|
"openclaw",
|
|
"memory-pro",
|
|
"reembed",
|
|
"--source-db",
|
|
sourceDbPath,
|
|
"--limit",
|
|
"1",
|
|
"--batch-size",
|
|
"999",
|
|
"--dry-run",
|
|
]);
|
|
|
|
// 3) Access reinforcement formula smoke test
|
|
const { parseAccessMetadata, buildUpdatedMetadata, computeEffectiveHalfLife } =
|
|
jiti("../src/access-tracker.ts");
|
|
|
|
// Verify formula basics
|
|
const hl0 = computeEffectiveHalfLife(60, 0, 0, 0.5, 3);
|
|
assert.equal(hl0, 60, "zero access = base half-life");
|
|
|
|
const hl10 = computeEffectiveHalfLife(60, 10, Date.now(), 0.5, 3);
|
|
assert.ok(hl10 > 60 && hl10 < 180, `10 accesses: ${hl10} should be between 60 and 180`);
|
|
|
|
const hlCapped = computeEffectiveHalfLife(60, 100000, Date.now(), 0.5, 3);
|
|
assert.equal(hlCapped, 180, "capped at 3x");
|
|
|
|
// Verify metadata round-trip
|
|
const meta = buildUpdatedMetadata("{}", 5);
|
|
const parsed = parseAccessMetadata(meta);
|
|
assert.equal(parsed.accessCount, 5);
|
|
assert.ok(parsed.lastAccessedAt > 0);
|
|
|
|
console.log("OK: Access reinforcement formula verified");
|
|
|
|
rmSync(workDir, { recursive: true, force: true });
|
|
}
|
|
|
|
runCliSmoke()
|
|
.then(() => {
|
|
console.log("OK: CLI smoke test passed");
|
|
})
|
|
.catch((err) => {
|
|
console.error("FAIL: CLI smoke test failed");
|
|
console.error(err);
|
|
process.exit(1);
|
|
});
|