fix(coding-agent): avoid invalid footer home abbreviation

closes #4878
This commit is contained in:
Mario Zechner
2026-05-23 09:53:36 +02:00
parent c85dbb1620
commit 2e1f07bac2
3 changed files with 29 additions and 6 deletions

View File

@@ -22,6 +22,7 @@
- Published a 0.74.2 rescue release that tells Node 20 users to upgrade Node before updating to newer Pi versions ([#4876](https://github.com/earendil-works/pi/issues/4876)).
- Fixed final bash tool cards to avoid rendering duplicate full-output truncation paths ([#4819](https://github.com/earendil-works/pi/issues/4819)).
- Fixed bash tool truncation line counts to ignore the trailing newline as an extra output line ([#4818](https://github.com/earendil-works/pi/issues/4818)).
- Fixed footer home-directory abbreviation to avoid shortening sibling paths that only share the same prefix ([#4878](https://github.com/earendil-works/pi/issues/4878)).
## [0.75.4] - 2026-05-20

View File

@@ -1,3 +1,4 @@
import { isAbsolute, relative, resolve, sep } from "node:path";
import { type Component, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
import type { AgentSession } from "../../../core/agent-session.ts";
import type { ReadonlyFooterDataProvider } from "../../../core/footer-data-provider.ts";
@@ -26,6 +27,20 @@ function formatTokens(count: number): string {
return `${Math.round(count / 1000000)}M`;
}
export function formatCwdForFooter(cwd: string, home: string | undefined): string {
if (!home) return cwd;
const resolvedCwd = resolve(cwd);
const resolvedHome = resolve(home);
const relativeToHome = relative(resolvedHome, resolvedCwd);
const isInsideHome =
relativeToHome === "" ||
(relativeToHome !== ".." && !relativeToHome.startsWith(`..${sep}`) && !isAbsolute(relativeToHome));
if (!isInsideHome) return cwd;
return relativeToHome === "" ? "~" : `~${sep}${relativeToHome}`;
}
/**
* Footer component that shows pwd, token stats, and context usage.
* Computes token/context stats from session, gets git branch and extension statuses from provider.
@@ -92,11 +107,7 @@ export class FooterComponent implements Component {
const contextPercent = contextUsage?.percent !== null ? contextPercentValue.toFixed(1) : "?";
// Replace home directory with ~
let pwd = this.session.sessionManager.getCwd();
const home = process.env.HOME || process.env.USERPROFILE;
if (home && pwd.startsWith(home)) {
pwd = `~${pwd.slice(home.length)}`;
}
let pwd = formatCwdForFooter(this.session.sessionManager.getCwd(), process.env.HOME || process.env.USERPROFILE);
// Add git branch if available
const branch = this.footerData.getGitBranch();

View File

@@ -2,7 +2,7 @@ import { visibleWidth } from "@earendil-works/pi-tui";
import { beforeAll, describe, expect, it } from "vitest";
import type { AgentSession } from "../src/core/agent-session.ts";
import type { ReadonlyFooterDataProvider } from "../src/core/footer-data-provider.ts";
import { FooterComponent } from "../src/modes/interactive/components/footer.ts";
import { FooterComponent, formatCwdForFooter } from "../src/modes/interactive/components/footer.ts";
import { initTheme } from "../src/modes/interactive/theme/theme.ts";
type AssistantUsage = {
@@ -73,6 +73,17 @@ function createFooterData(providerCount: number): ReadonlyFooterDataProvider {
return provider;
}
describe("formatCwdForFooter", () => {
it("does not abbreviate sibling paths that share the home prefix", () => {
expect(formatCwdForFooter("/home/user2", "/home/user")).toBe("/home/user2");
});
it("abbreviates the home directory and descendants", () => {
expect(formatCwdForFooter("/home/user", "/home/user")).toBe("~");
expect(formatCwdForFooter("/home/user/project", "/home/user")).toBe("~/project");
});
});
describe("FooterComponent width handling", () => {
beforeAll(() => {
initTheme(undefined, false);