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:
Can Bölük
2026-06-23 20:21:08 +02:00
committed by GitHub
3 changed files with 62 additions and 8 deletions
+3
View File
@@ -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"));