mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-10-26 10:45:22 +00:00
feat(pi-hermes-memory): 导入上游 v0.9.10 源码快照
从官方 Git 仓库导入 chandra447/pi-hermes-memory 在 tag v0.9.10 (df624056a2e8c68bc89ba0a81e1c120856ec9665,2026-10-02)的源码快照。 本次仅导入源码,尚未接入组合包:package.json、加载顺序、依赖与权限策略 均未改动。 - 原样导入 src/、tests/、docs/、scripts/、README、CHANGELOG、PLAN、 AGENTS 与 LICENSE;该快照共 156 个上游文件。 - 剔除嵌套 .git、上游 .github 工作流、.ralph/、.claude/、node_modules、 覆盖率与构建产物。 - 新增中文 UPSTREAM.md,记录来源,以及启用前必须完成的待决事项: 在 pi-compaction 之前注册加载顺序、better-sqlite3 版本与根 allowScripts 对齐、strip-ansi 解析确认。 - 说明选择 tag 而非 main 的原因:导入时上游 main 已领先至 24fcd8ad26fc27badb8d7dbaf8034645de07b893(2026-10-11),选 tag 是为 对应一个已发布、可复现的版本。 尚未接线。启用前还需反转 tests/extension-load.test.ts 中"不得加载 Hermes"的断言,并同步 pi-tool-search 分组、权限策略与文档。 验证:快照 156 个上游文件全部导入,目录内仅多出 UPSTREAM.md 一份; 已确认与上游 main 内容存在差异,证明取的是 tag 而非 main。
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
import { describe, it } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { createRequire } from "node:module";
|
||||
import path from "node:path";
|
||||
import {
|
||||
BetterSqlite3LoadError,
|
||||
formatBetterSqlite3AbiError,
|
||||
isNativeModuleAbiMismatch,
|
||||
loadBetterSqlite3,
|
||||
resolveBetterSqlite3PackageRoot,
|
||||
} from "../../src/store/sqlite-native.js";
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
type RequireCache = Record<string, unknown>;
|
||||
|
||||
function fakeRequire(
|
||||
impl: (id: string) => unknown,
|
||||
resolveImpl: (id: string) => string,
|
||||
): NodeRequire {
|
||||
return Object.assign(impl, {
|
||||
resolve: resolveImpl,
|
||||
cache: {} as RequireCache,
|
||||
}) as NodeRequire;
|
||||
}
|
||||
|
||||
describe("sqlite-native loader", () => {
|
||||
it("detects NODE_MODULE_VERSION ABI mismatch errors", () => {
|
||||
assert.equal(
|
||||
isNativeModuleAbiMismatch(
|
||||
new Error(
|
||||
"The module '/tmp/better_sqlite3.node' was compiled against a different Node.js version using NODE_MODULE_VERSION 115",
|
||||
),
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(isNativeModuleAbiMismatch(new Error("SQLITE_BUSY")), false);
|
||||
});
|
||||
|
||||
it("detects ERR_DLOPEN_FAILED codes", () => {
|
||||
const err = Object.assign(new Error("dlopen failed"), { code: "ERR_DLOPEN_FAILED" });
|
||||
assert.equal(isNativeModuleAbiMismatch(err), true);
|
||||
});
|
||||
|
||||
it("resolves the installed better-sqlite3 package root", () => {
|
||||
const root = resolveBetterSqlite3PackageRoot(require);
|
||||
assert.ok(root);
|
||||
assert.equal(path.basename(root!), "better-sqlite3");
|
||||
});
|
||||
|
||||
it("loads better-sqlite3 successfully in the current runtime", () => {
|
||||
const Database = loadBetterSqlite3({ requireImpl: require, allowRebuild: false });
|
||||
const db = new (Database as new (path: string) => {
|
||||
exec: (sql: string) => void;
|
||||
close: () => void;
|
||||
})(":memory:");
|
||||
db.exec("SELECT 1");
|
||||
db.close();
|
||||
});
|
||||
|
||||
it("rebuilds once on ABI mismatch then succeeds", () => {
|
||||
let calls = 0;
|
||||
const ctor = class FakeDb {
|
||||
constructor(_path: string) {}
|
||||
};
|
||||
const req = fakeRequire(
|
||||
(id: string) => {
|
||||
assert.equal(id, "better-sqlite3");
|
||||
calls += 1;
|
||||
if (calls === 1) {
|
||||
throw new Error(
|
||||
"was compiled against a different Node.js version using NODE_MODULE_VERSION 115. Please try re-compiling",
|
||||
);
|
||||
}
|
||||
return ctor;
|
||||
},
|
||||
(id: string) => {
|
||||
assert.equal(id, "better-sqlite3");
|
||||
return path.join("/tmp/fake-npm/node_modules/better-sqlite3/lib/index.js");
|
||||
},
|
||||
);
|
||||
|
||||
let rebuilt = false;
|
||||
const Database = loadBetterSqlite3({
|
||||
requireImpl: req,
|
||||
rebuild: (packageRoot) => {
|
||||
rebuilt = true;
|
||||
assert.equal(packageRoot, "/tmp/fake-npm/node_modules/better-sqlite3");
|
||||
return { ok: true, detail: "rebuilt" };
|
||||
},
|
||||
});
|
||||
|
||||
assert.equal(Database, ctor);
|
||||
assert.equal(rebuilt, true);
|
||||
assert.equal(calls, 2);
|
||||
});
|
||||
|
||||
it("throws BetterSqlite3LoadError with recovery guidance when rebuild fails", () => {
|
||||
const req = fakeRequire(
|
||||
(_id: string) => {
|
||||
throw new Error(
|
||||
"The module 'x.node' was compiled against a different Node.js version using NODE_MODULE_VERSION 108",
|
||||
);
|
||||
},
|
||||
() => path.join("/tmp/fake-npm/node_modules/better-sqlite3/lib/index.js"),
|
||||
);
|
||||
|
||||
assert.throws(
|
||||
() =>
|
||||
loadBetterSqlite3({
|
||||
requireImpl: req,
|
||||
rebuild: () => ({ ok: false, detail: "npm missing" }),
|
||||
}),
|
||||
(error: unknown) => {
|
||||
assert.ok(error instanceof BetterSqlite3LoadError);
|
||||
const message = error.message;
|
||||
assert.match(message, /pi-hermes-memory could not load the native better-sqlite3 module/);
|
||||
assert.match(message, /npm rebuild better-sqlite3/);
|
||||
assert.match(message, /Homebrew/);
|
||||
assert.match(message, /npm missing/);
|
||||
assert.equal(error.packageRoot, "/tmp/fake-npm/node_modules/better-sqlite3");
|
||||
return true;
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it("formats actionable ABI recovery text", () => {
|
||||
const message = formatBetterSqlite3AbiError({
|
||||
originalError: new Error("NODE_MODULE_VERSION 115"),
|
||||
packageRoot: "/Users/me/.pi/agent/npm/node_modules/better-sqlite3",
|
||||
rebuildAttempted: true,
|
||||
rebuildDetail: "exit 1",
|
||||
});
|
||||
assert.match(message, /NODE_MODULE_VERSION/);
|
||||
assert.match(message, /\/Users\/me\/\.pi\/agent\/npm\/node_modules\/better-sqlite3/);
|
||||
assert.match(message, /npm rebuild better-sqlite3/);
|
||||
assert.match(message, /Homebrew/);
|
||||
});
|
||||
|
||||
it("does not rebuild for non-ABI load failures", () => {
|
||||
let rebuilt = false;
|
||||
const req = fakeRequire(
|
||||
() => {
|
||||
throw new Error("Cannot find module 'better-sqlite3'");
|
||||
},
|
||||
() => {
|
||||
throw new Error("not found");
|
||||
},
|
||||
);
|
||||
|
||||
assert.throws(
|
||||
() =>
|
||||
loadBetterSqlite3({
|
||||
requireImpl: req,
|
||||
rebuild: () => {
|
||||
rebuilt = true;
|
||||
return { ok: true, detail: "should not run" };
|
||||
},
|
||||
}),
|
||||
/Cannot find module 'better-sqlite3'/,
|
||||
);
|
||||
assert.equal(rebuilt, false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user