mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-10-26 10:45:22 +00:00
从官方 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。
100 lines
4.0 KiB
JavaScript
Executable File
100 lines
4.0 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
/**
|
|
* Type-check the extension against the OLDEST Pi SDK we claim to support.
|
|
*
|
|
* Why this exists: `peerDependencies` is the only thing telling a user whether
|
|
* this extension works on their Pi, and nothing verified it. The declared floor
|
|
* had drifted to `>=0.74.0` while `src/handlers/review-memory-ops.ts` imports
|
|
* `@earendil-works/pi-ai/compat`, a subpath that does not exist before 0.80.1 —
|
|
* so anyone on 0.74-0.79.x got ERR_PACKAGE_PATH_NOT_EXPORTED and no extension
|
|
* at all, with nothing in CI to catch it.
|
|
*
|
|
* The regular `check` job structurally cannot catch this: it installs whatever
|
|
* the devDependency range resolves to, which is always new enough.
|
|
*
|
|
* Run: node scripts/check-min-sdk.mjs
|
|
*/
|
|
|
|
import { execFileSync } from "node:child_process";
|
|
import { existsSync, mkdtempSync, readFileSync, renameSync, rmSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import * as path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
const SCOPE = "@earendil-works";
|
|
// pi-tui is a direct dependency rather than a peer, but its types cross the
|
|
// boundary (ExtensionCommandContext.ui.custom takes a pi-tui TUI). Leaving it
|
|
// at a different version yields a duplicate-private-property error instead of
|
|
// a real finding, so it moves with the floor.
|
|
const FLOOR_PACKAGES = [`${SCOPE}/pi-coding-agent`, `${SCOPE}/pi-ai`, `${SCOPE}/pi-tui`];
|
|
|
|
const scopeDir = path.join(repoRoot, "node_modules", SCOPE);
|
|
const stashDir = path.join(repoRoot, "node_modules", `${SCOPE}.real`);
|
|
|
|
function restore() {
|
|
// Idempotent: safe to call from the finally block and from signal handlers.
|
|
try {
|
|
if (existsSync(stashDir)) {
|
|
if (existsSync(scopeDir)) unlinkSync(scopeDir);
|
|
renameSync(stashDir, scopeDir);
|
|
}
|
|
} catch (error) {
|
|
console.error(
|
|
`\nFAILED TO RESTORE node_modules/${SCOPE}. Run: mv "${stashDir}" "${scopeDir}"\n`,
|
|
error,
|
|
);
|
|
}
|
|
}
|
|
|
|
for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
process.on(signal, () => { restore(); process.exit(130); });
|
|
}
|
|
|
|
const pkg = JSON.parse(readFileSync(path.join(repoRoot, "package.json"), "utf-8"));
|
|
const range = pkg.peerDependencies?.[`${SCOPE}/pi-coding-agent`];
|
|
const floor = /(\d+\.\d+\.\d+)/.exec(range ?? "")?.[1];
|
|
if (!floor) {
|
|
console.error(`peerDependencies range "${range}" has no explicit floor — pin one like ">=0.80.1"`);
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log(`Minimum supported ${SCOPE}/pi-coding-agent: ${floor}`);
|
|
|
|
const scratch = mkdtempSync(path.join(tmpdir(), "pi-hermes-min-sdk-"));
|
|
let failed = false;
|
|
try {
|
|
writeFileSync(path.join(scratch, "package.json"), `${JSON.stringify({ name: "min-sdk-probe", private: true })}\n`);
|
|
const specs = FLOOR_PACKAGES.map((name) => `${name}@${floor}`);
|
|
console.log(`Installing ${specs.join(" ")} ...`);
|
|
execFileSync("npm", ["install", "--silent", "--no-audit", "--no-fund", "--no-package-lock", ...specs], {
|
|
cwd: scratch,
|
|
stdio: ["ignore", "ignore", "inherit"],
|
|
});
|
|
|
|
// Swap the scope in place so the project's own tsconfig applies unchanged —
|
|
// no divergent probe config that could drift from what `npm run check` uses.
|
|
renameSync(scopeDir, stashDir);
|
|
symlinkSync(path.join(scratch, "node_modules", SCOPE), scopeDir);
|
|
|
|
console.log("Type-checking src against the minimum SDK ...");
|
|
execFileSync(path.join(repoRoot, "node_modules", ".bin", "tsc"), ["--noEmit"], {
|
|
cwd: repoRoot,
|
|
stdio: "inherit",
|
|
});
|
|
console.log(`OK — src type-checks against ${SCOPE}/pi-coding-agent@${floor}`);
|
|
} catch (error) {
|
|
failed = true;
|
|
if (!/Command failed/.test(String(error?.message))) console.error(error);
|
|
console.error(
|
|
`\nsrc does NOT type-check against the declared minimum (${floor}).\n`
|
|
+ "Either raise the peerDependencies floor in package.json to a version that works,\n"
|
|
+ "or stop using the SDK API that is missing at that version.\n",
|
|
);
|
|
} finally {
|
|
restore();
|
|
rmSync(scratch, { recursive: true, force: true });
|
|
}
|
|
|
|
process.exit(failed ? 1 : 0);
|