fix(coding-agent): sync pi-natives on omp update
bun install -g <pkg>@<v> did not reliably re-resolve transitive optionalDependencies, so @oh-my-pi/pi-natives and the platform leaf @oh-my-pi/pi-natives-<tag> stayed at the previous version while @oh-my-pi/pi-coding-agent moved. The loader’s validateLoadedBindings then aborted because the .node file exposed the old __piNativesV<old> sentinel instead of __piNativesV<new>. buildBunInstallArgs now pins @oh-my-pi/pi-natives and (when the running tag is one the release pipeline publishes) the platform leaf to the same version it installs for @oh-my-pi/pi-coding-agent, so bun replaces all three in lock-step. The leaf is gated by the same SUPPORTED_PLATFORMS set the loader uses, so unsupported tags still surface the original 'no matching version' diagnostic instead of EBADPLATFORM. Fixes #1824
This commit is contained in:
@@ -2,6 +2,10 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed `omp update` leaving `@oh-my-pi/pi-natives` and the platform-specific `@oh-my-pi/pi-natives-<tag>` leaf at the previous version on `bun install -g` updates, so the next launch loaded a stale `.node` file and aborted at `validateLoadedBindings` with `The .node file on disk is from a different release than this loader`. `omp update` now pins the native addon core and the platform leaf to the same version it installs for `@oh-my-pi/pi-coding-agent` ([#1824](https://github.com/can1357/oh-my-pi/issues/1824)).
|
||||
|
||||
## [15.9.0] - 2026-06-04
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
@@ -27,6 +27,33 @@ const PACKAGE = "@oh-my-pi/pi-coding-agent";
|
||||
*/
|
||||
const NPM_REGISTRY = "https://registry.npmjs.org/";
|
||||
|
||||
/**
|
||||
* Core native addon package. Bumped in lock-step with {@link PACKAGE} so the
|
||||
* version sentinel the loader looks up at runtime matches the `.node` on
|
||||
* disk; see {@link buildBunInstallArgs} for why this must be installed
|
||||
* explicitly rather than inherited as a transitive dependency.
|
||||
*/
|
||||
const NATIVES_PACKAGE = "@oh-my-pi/pi-natives";
|
||||
|
||||
/**
|
||||
* Platform tags the release pipeline publishes as
|
||||
* `@oh-my-pi/pi-natives-<tag>` leaves. Mirrors `SUPPORTED_PLATFORMS` in
|
||||
* `packages/natives/native/loader-state.js` and `LEAF_TARGETS` in
|
||||
* `packages/natives/scripts/gen-npm-packages.ts`; kept here as the local
|
||||
* source of truth so the update path stays free of cross-package imports.
|
||||
*/
|
||||
const SUPPORTED_NATIVE_TAGS: ReadonlySet<string> = new Set([
|
||||
"linux-x64",
|
||||
"linux-arm64",
|
||||
"darwin-x64",
|
||||
"darwin-arm64",
|
||||
"win32-x64",
|
||||
]);
|
||||
|
||||
function currentNativeTag(): string {
|
||||
return `${process.platform}-${process.arch}`;
|
||||
}
|
||||
|
||||
interface ReleaseInfo {
|
||||
tag: string;
|
||||
version: string;
|
||||
@@ -319,9 +346,37 @@ export async function replaceBinaryForUpdate(options: BinaryReplacementOptions):
|
||||
*
|
||||
* Together these two flags make `omp update` produce exactly the registry
|
||||
* lookup the version check just performed. See #1686.
|
||||
*
|
||||
* Also pins {@link NATIVES_PACKAGE} and the platform-specific
|
||||
* `@oh-my-pi/pi-natives-<tag>` leaf to `expectedVersion`. `bun install -g`
|
||||
* does not reliably refresh transitive `optionalDependencies` when the
|
||||
* top-level package is the only one bumped, so the native addon and its
|
||||
* version sentinel can drift out of sync with the freshly installed
|
||||
* `@oh-my-pi/pi-coding-agent` and the loader aborts at
|
||||
* `validateLoadedBindings` on the next launch
|
||||
* (`The .node file on disk is from a different release than this loader`).
|
||||
* Listing the natives explicitly forces bun to replace them in lock-step.
|
||||
* The leaf is added only on tags the release pipeline actually publishes
|
||||
* ({@link SUPPORTED_NATIVE_TAGS}) so unsupported platforms still fail with
|
||||
* the original "no matching version" message instead of `EBADPLATFORM`.
|
||||
* See #1824.
|
||||
*/
|
||||
export function buildBunInstallArgs(expectedVersion: string): string[] {
|
||||
return ["install", "-g", "--no-cache", `--registry=${NPM_REGISTRY}`, `${PACKAGE}@${expectedVersion}`];
|
||||
export function buildBunInstallArgs(
|
||||
expectedVersion: string,
|
||||
nativeTag: string = currentNativeTag(),
|
||||
): string[] {
|
||||
const args = [
|
||||
"install",
|
||||
"-g",
|
||||
"--no-cache",
|
||||
`--registry=${NPM_REGISTRY}`,
|
||||
`${PACKAGE}@${expectedVersion}`,
|
||||
`${NATIVES_PACKAGE}@${expectedVersion}`,
|
||||
];
|
||||
if (SUPPORTED_NATIVE_TAGS.has(nativeTag)) {
|
||||
args.push(`${NATIVES_PACKAGE}-${nativeTag}@${expectedVersion}`);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -45,7 +45,8 @@ describe("update-cli bun install command", () => {
|
||||
// is already pointed at the official registry but its cache predates
|
||||
// the release.
|
||||
// See https://github.com/can1357/oh-my-pi/issues/1686.
|
||||
expect(buildBunInstallArgs("15.7.6")).toEqual([
|
||||
const args = buildBunInstallArgs("15.7.6", "linux-x64");
|
||||
expect(args.slice(0, 5)).toEqual([
|
||||
"install",
|
||||
"-g",
|
||||
"--no-cache",
|
||||
@@ -53,6 +54,31 @@ describe("update-cli bun install command", () => {
|
||||
"@oh-my-pi/pi-coding-agent@15.7.6",
|
||||
]);
|
||||
});
|
||||
|
||||
it("pins the native addon core and the platform-specific leaf to the same version so the loader sentinel cannot drift on supported tags", () => {
|
||||
// Regression: bun install -g <pkg>@<v> would update only the top-level
|
||||
// package, leaving @oh-my-pi/pi-natives and @oh-my-pi/pi-natives-<tag>
|
||||
// at their previous version. The next launch then loaded a stale .node
|
||||
// file and aborted at validateLoadedBindings with `The .node file on
|
||||
// disk is from a different release than this loader`. See
|
||||
// https://github.com/can1357/oh-my-pi/issues/1824.
|
||||
for (const tag of ["linux-x64", "linux-arm64", "darwin-x64", "darwin-arm64", "win32-x64"]) {
|
||||
const args = buildBunInstallArgs("15.9.0", tag);
|
||||
expect(args).toContain("@oh-my-pi/pi-natives@15.9.0");
|
||||
expect(args).toContain(`@oh-my-pi/pi-natives-${tag}@15.9.0`);
|
||||
}
|
||||
});
|
||||
|
||||
it("omits the leaf on unsupported platform tags so an EBADPLATFORM swap does not mask the underlying `no matching version` error", () => {
|
||||
// Defensive: an unsupported tag (e.g. linux-arm32) still installs the
|
||||
// core natives package — which will fail at module load if the platform
|
||||
// truly is unsupported — but we never request a leaf the release
|
||||
// pipeline doesn't publish, otherwise bun aborts with EBADPLATFORM
|
||||
// and hides the real diagnostic from `loadNative`'s aggregated error.
|
||||
const args = buildBunInstallArgs("15.9.0", "linux-arm");
|
||||
expect(args).toContain("@oh-my-pi/pi-natives@15.9.0");
|
||||
expect(args.some(arg => arg.startsWith("@oh-my-pi/pi-natives-"))).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("update-cli binary replacement", () => {
|
||||
|
||||
Reference in New Issue
Block a user