fix(agent-mode): minimize displayed file targets (#2681)

This commit is contained in:
Logan Yang 2026-07-16 14:44:34 -07:00 committed by GitHub
parent 0098ba5e2d
commit 418cb85dcd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 28 additions and 8 deletions

View file

@ -41,13 +41,26 @@ describe("lookupToolSummary", () => {
expect(lookupToolSummary(t).collapsedLine(t, CTX)).toBe("Read notes/music-theory.md");
});
it("falls back to the original path when the file is outside the vault", () => {
it("hides parent directories outside the vault without changing the navigation target", () => {
const t = tool({
vendorToolName: "Read",
title: "read",
locations: [{ path: "/etc/passwd" }],
});
expect(lookupToolSummary(t).collapsedLine(t, CTX)).toBe("Read /etc/passwd");
const summary = lookupToolSummary(t);
expect(summary.collapsedLine(t, CTX)).toBe("Read …/passwd");
expect(summary.targetPath?.(t, CTX)).toBe("/etc/passwd");
});
it("hides parent directories for ACP read paths without vault context", () => {
const t = tool({
toolKind: "read",
title: "Read",
input: { filePath: "/Users/me/private/draft.md" },
});
expect(lookupToolSummary(t).collapsedLine(t, { vaultBase: null })).toBe("Read …/draft.md");
const windows = { ...t, input: { filePath: "C:\\Users\\me\\private\\draft.md" } };
expect(lookupToolSummary(windows).collapsedLine(windows, CTX)).toBe("Read …/draft.md");
});
it("aggregates Edits with combined +/- line counts and counts notes", () => {

View file

@ -2,7 +2,7 @@ import type { LucideIcon } from "lucide-react";
import { Bot, MessageCircleQuestion } from "lucide-react";
import { pickToolIcon } from "@/agentMode/ui/toolIcons";
import type { ToolCallPart } from "@/agentMode/ui/agentTrail";
import { toVaultRelative } from "@/utils/vaultPath";
import { isAbsolutePath, toVaultRelative } from "@/utils/vaultPath";
/**
* Render-time context passed through to the summary callbacks that need
@ -202,6 +202,13 @@ function targetFromPath(part: ToolCallPart, vaultBase: string | null): string |
return null;
}
function displayTargetFromPath(part: ToolCallPart, vaultBase: string | null): string | null {
const path = targetFromPath(part, vaultBase);
if (!path || !isAbsolutePath(path)) return path;
const leaf = path.replace(/\\/g, "/").replace(/\/+$/, "").split("/").pop();
return leaf ? `…/${leaf}` : "…";
}
/**
* The skill identifier from a `Skill` tool call's input (Claude Code logs the
* slash-command name as `input.skill`, e.g. "copilot-read-pdf"). Returns the
@ -253,7 +260,7 @@ function approxTokens(part: ToolCallPart): number {
const READ_SUMMARY: ToolSummary = {
icon: pickToolIcon({ vendorToolName: "Read" }),
collapsedLine: (p, ctx) =>
`${verb(p, "Reading", "Read")} ${targetFromPath(p, ctx?.vaultBase ?? null) ?? targetFromTitle(p)}`,
`${verb(p, "Reading", "Read")} ${displayTargetFromPath(p, ctx?.vaultBase ?? null) ?? targetFromTitle(p)}`,
outcome: (p) => {
const t = approxTokens(p);
return t > 0 ? `~${formatTokens(t)} tokens` : null;
@ -272,7 +279,7 @@ const LIST_SUMMARY: ToolSummary = {
icon: pickToolIcon({ vendorToolName: "LS" }),
collapsedLine: (p, ctx) => {
const v = verb(p, "Listing", "Listed");
const path = targetFromPath(p, ctx?.vaultBase ?? null);
const path = displayTargetFromPath(p, ctx?.vaultBase ?? null);
return path ? `${v} ${path}` : `${v} vault root`;
},
outcome: () => null,
@ -285,7 +292,7 @@ const LIST_SUMMARY: ToolSummary = {
const EDIT_SUMMARY: ToolSummary = {
icon: pickToolIcon({ vendorToolName: "Edit" }),
collapsedLine: (p, ctx) =>
`${verb(p, "Editing", "Edited")} ${targetFromPath(p, ctx?.vaultBase ?? null) ?? targetFromTitle(p)}`,
`${verb(p, "Editing", "Edited")} ${displayTargetFromPath(p, ctx?.vaultBase ?? null) ?? targetFromTitle(p)}`,
outcome: (p) => {
const { added, removed } = diffStats(p);
if (added === 0 && removed === 0) return null;
@ -506,7 +513,7 @@ const KIND_FETCH_SUMMARY: ToolSummary = {
const KIND_DELETE_SUMMARY: ToolSummary = {
icon: pickToolIcon({ toolKind: "delete" }),
collapsedLine: (p, ctx) =>
`${verb(p, "Deleting", "Deleted")} ${targetFromPath(p, ctx?.vaultBase ?? null) ?? targetFromTitle(p)}`,
`${verb(p, "Deleting", "Deleted")} ${displayTargetFromPath(p, ctx?.vaultBase ?? null) ?? targetFromTitle(p)}`,
outcome: () => null,
aggregate: (parts) => ({
line: `Deleted ${pluralize(parts.length, "item")}${statusSuffix(parts)}`,
@ -516,7 +523,7 @@ const KIND_DELETE_SUMMARY: ToolSummary = {
const KIND_MOVE_SUMMARY: ToolSummary = {
icon: pickToolIcon({ toolKind: "move" }),
collapsedLine: (p, ctx) =>
`${verb(p, "Moving", "Moved")} ${targetFromPath(p, ctx?.vaultBase ?? null) ?? targetFromTitle(p)}`,
`${verb(p, "Moving", "Moved")} ${displayTargetFromPath(p, ctx?.vaultBase ?? null) ?? targetFromTitle(p)}`,
outcome: () => null,
aggregate: (parts) => ({
line: `Moved ${pluralize(parts.length, "item")}${statusSuffix(parts)}`,