fix(coding-agent): self-update binary install when its dir overlaps npm/bun bin dir

resolveUpdateMethod classified the install purely by directory containment,
so a standalone binary placed where `npm prefix -g` / `bun pm bin -g` also
points (e.g. ~/.local/bin) was misrouted to `npm install -g`, which then
aborted with EEXIST refusing to overwrite the existing regular file. Now a
plain executable (not a symlink) inside a package-manager bin dir is treated
as the standalone binary and self-updated in place.
This commit is contained in:
mr-r0b0t
2026-07-24 10:40:15 -05:00
parent a38cd95d7d
commit 82e2a9fd63
3 changed files with 67 additions and 4 deletions
@@ -90,6 +90,36 @@ describe("update-cli install target detection", () => {
expect(method).toBe("npm");
});
it("uses binary update when a plain file in the npm global bin dir is the standalone binary, not an npm symlink", () => {
// Regression: with `npm prefix -g` pointed at the installer's default
// (~/.local), directory containment alone misclassified the standalone
// binary as npm-managed, so `npm install -g` failed with EEXIST refusing
// to overwrite the existing executable.
const method = resolveUpdateMethodForTest("/home/u/.local/bin/omp", undefined, {
npmBinDir: "/home/u/.local/bin",
ompIsRegularFile: true,
});
expect(method).toBe("binary");
});
it("uses binary update when a plain file in the bun global bin dir is the standalone binary", () => {
const method = resolveUpdateMethodForTest("/home/u/.local/bin/omp", "/home/u/.local/bin", {
ompIsRegularFile: true,
});
expect(method).toBe("binary");
});
it("still uses npm update when the npm global bin entry is a package-manager symlink, not a plain file", () => {
const method = resolveUpdateMethodForTest("/home/u/.local/bin/omp", undefined, {
npmBinDir: "/home/u/.local/bin",
ompIsRegularFile: false,
});
expect(method).toBe("npm");
});
it("uses binary update when prioritized omp is outside bun global bin", () => {
const method = resolveUpdateMethodForTest("/Users/test/.local/bin/omp", "/Users/test/.bun/bin");