Merge pull request #3330 from can1357/farm/4a0fd941/fix-bunfs-root-homebrew-arm64
fix(coding-agent): handled `<bunfs-root>/<binary>` in __computeBunfsPackageRoot
This commit is contained in:
@@ -2,6 +2,9 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed all extension loading silently failing on the cross-compiled `omp-darwin-arm64` release binary (downloaded directly or via a Homebrew tap wrapper) because `__computeBunfsPackageRoot` mis-handled `import.meta.dir = "//root/omp-darwin-arm64"`. Bun 1.3.14 reports `<bunfs-root>/<binary-name>` for the compiled entry's `import.meta.dir`, but the pre-fix function joined `metaDir + "packages"` and produced `/root/omp-darwin-arm64/packages` — the binary basename was baked into every bunfs path, so the TypeBox/legacy-pi shims and every `@oh-my-pi/pi-*` package-root override failed `existsSync` validation and `resolveCanonicalPiSpecifier` fell through to a bunfs `Bun.resolveSync` that also could not find the module. The function now detects the bunfs-root + binary-basename shape (`path.basename(path.dirname(metaDir)) === "root"`) and strips the trailing binary segment by slicing the original `metaDir`; the production bunfs shim join path also preserves Bun's bunfs-native `//root` / `B:\~BUN\root` prefix that `path.join` would otherwise collapse. ([#3329](https://github.com/can1357/oh-my-pi/issues/3329))
|
||||
## [16.1.16] - 2026-06-23
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
@@ -93,14 +93,22 @@ const TYPEBOX_SPECIFIER_FILTER = /^(?:@sinclair\/typebox|typebox)$/;
|
||||
// so they keep working when on-disk layout differs from the monorepo tree.
|
||||
/**
|
||||
* Compute the bunfs package root from the compiled binary's `import.meta.dir`
|
||||
* (or any stand-in supplied by tests). Bun 1.3 reports the bunfs mount root
|
||||
* (`/$bunfs/root` or `<drive>:\~BUN\root`) for imported modules as well as the
|
||||
* entrypoint, so the normal path is `<root>/packages`.
|
||||
* (or any stand-in supplied by tests). Bun compiled binaries report one of:
|
||||
*
|
||||
* The suffix branch preserves correctness if a future Bun release switches to
|
||||
* module-specific `import.meta.dir` values inside compiled binaries, matching
|
||||
* the source layout:
|
||||
* `<bunfs>/packages/coding-agent/src/extensibility/plugins`.
|
||||
* - the bunfs mount root itself — `/$bunfs/root` or `<drive>:\~BUN\root` (Bun
|
||||
* 1.2.x and early 1.3.x). Append `packages` for the canonical layout.
|
||||
* - the bunfs mount root followed by the binary's basename — `//root/<bin>`
|
||||
* on POSIX or `<drive>:\~BUN\root\<bin>.exe` on Windows (observed on Bun
|
||||
* 1.3.14 with the cross-compiled `omp-darwin-arm64` release asset — issue
|
||||
* #3329). The trailing segment is stripped so the result still lands on
|
||||
* `<root>/packages`.
|
||||
* - the module's own source directory if a future Bun release switches to
|
||||
* module-specific `import.meta.dir` values:
|
||||
* `<bunfs>/packages/coding-agent/src/extensibility/plugins`.
|
||||
* The bunfs-root-with-binary branch slices the original `metaDir`, and
|
||||
* `bunfsPath` uses a matching double-slash-preserving join, so the bunfs-native
|
||||
* prefix is preserved verbatim — `path.posix.join` collapses `//root` to
|
||||
* `/root`, but Bun's bunfs lookup is keyed on the exact `//root` form.
|
||||
*
|
||||
* Exported for tests; production callers use `BUNFS_PACKAGE_ROOT` below.
|
||||
*/
|
||||
@@ -110,6 +118,10 @@ export function __computeBunfsPackageRoot(metaDir: string, pathImpl: typeof path
|
||||
if (normalizedMetaDir.endsWith(pluginsDirSuffix)) {
|
||||
return pathImpl.resolve(metaDir, "..", "..", "..", "..");
|
||||
}
|
||||
const parent = pathImpl.dirname(metaDir);
|
||||
if (pathImpl.basename(pathImpl.normalize(parent)) === "root") {
|
||||
return `${parent + pathImpl.sep}packages`;
|
||||
}
|
||||
return pathImpl.join(metaDir, "packages");
|
||||
}
|
||||
|
||||
@@ -137,11 +149,31 @@ export function __computeBundledSelfPackageRoot(metaDir: string, pathImpl: typeo
|
||||
|
||||
const BUNFS_PACKAGE_ROOT = IS_COMPILED_BINARY ? __computeBunfsPackageRoot(import.meta.dir) : null;
|
||||
|
||||
/**
|
||||
* Join a computed bunfs package root with descendants without collapsing
|
||||
* Bun's POSIX `//root` mount prefix.
|
||||
*
|
||||
* Exported for tests; production callers use `bunfsPath` below.
|
||||
*/
|
||||
export function __joinBunfsPath(root: string, segments: readonly string[], pathImpl: typeof path = path): string {
|
||||
const joined = pathImpl.join(root, ...segments);
|
||||
const doubleRootPrefix = pathImpl.sep + pathImpl.sep;
|
||||
const tripleRootPrefix = doubleRootPrefix + pathImpl.sep;
|
||||
if (
|
||||
root.startsWith(doubleRootPrefix) &&
|
||||
!root.startsWith(tripleRootPrefix) &&
|
||||
!joined.startsWith(doubleRootPrefix)
|
||||
) {
|
||||
return pathImpl.sep + joined;
|
||||
}
|
||||
return joined;
|
||||
}
|
||||
|
||||
function bunfsPath(...segments: string[]): string {
|
||||
if (!BUNFS_PACKAGE_ROOT) {
|
||||
throw new Error("bunfsPath is only valid in compiled-binary mode");
|
||||
}
|
||||
return path.join(BUNFS_PACKAGE_ROOT, ...segments);
|
||||
return __joinBunfsPath(BUNFS_PACKAGE_ROOT, segments);
|
||||
}
|
||||
|
||||
function resolveBundledSelfPackageRoot(): string | undefined {
|
||||
|
||||
@@ -3,6 +3,7 @@ import * as path from "node:path";
|
||||
import {
|
||||
__computeBundledSelfPackageRoot,
|
||||
__computeBunfsPackageRoot,
|
||||
__joinBunfsPath,
|
||||
} from "@oh-my-pi/pi-coding-agent/extensibility/plugins/legacy-pi-compat";
|
||||
|
||||
// Regression for issue #1514: legacy pi compat shim paths were built from a
|
||||
@@ -35,6 +36,24 @@ describe("legacy pi compat bunfs root computation (issue #1514)", () => {
|
||||
expect(__computeBunfsPackageRoot(posixMetaDir, path.posix)).toBe("/$bunfs/root/packages");
|
||||
});
|
||||
|
||||
it("preserves the double-slash bunfs prefix through production shim path joins (issue #3329)", () => {
|
||||
// Bun 1.3.14 on the cross-compiled `omp-darwin-arm64` release asset
|
||||
// reports `import.meta.dir` as `//root/omp-darwin-arm64`. The leading
|
||||
// `//` is part of Bun's bunfs identifier, so both the root computation
|
||||
// and the production shim-path join must preserve it.
|
||||
const root = __computeBunfsPackageRoot("//root/omp-darwin-arm64", path.posix);
|
||||
expect(root).toBe("//root/packages");
|
||||
expect(__joinBunfsPath(root, ["coding-agent", "src", "extensibility", "typebox.js"], path.posix)).toBe(
|
||||
"//root/packages/coding-agent/src/extensibility/typebox.js",
|
||||
);
|
||||
|
||||
// `$bunfs`-prefixed variant is also handled.
|
||||
expect(__computeBunfsPackageRoot("/$bunfs/root/omp", path.posix)).toBe("/$bunfs/root/packages");
|
||||
// Windows variant: bunfs mount at `<drive>:\~BUN\root` with the binary
|
||||
// basename appended.
|
||||
expect(__computeBunfsPackageRoot("B:\\~BUN\\root\\omp.exe", path.win32)).toBe("B:\\~BUN\\root\\packages");
|
||||
});
|
||||
|
||||
it("uses the current host path implementation for production calls", () => {
|
||||
const metaDir = path.join("/", "anywhere", "root");
|
||||
expect(__computeBunfsPackageRoot(metaDir)).toBe(path.join("/", "anywhere", "root", "packages"));
|
||||
|
||||
Reference in New Issue
Block a user