docs(agent-mode): note AgentDiffView + edit-diff sourcing; formatting

Phase 6: document the read-only AgentDiffView and where edit diffs are sourced
in agentMode/AGENTS.md, and apply prettier formatting. Full jest suite (4384
tests), eslint (incl. boundaries), and the production build are all green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Zero Liu 2026-07-03 12:53:47 +08:00
parent e4b4e08409
commit daab29af46
No known key found for this signature in database
4 changed files with 30 additions and 12 deletions

View file

@ -94,6 +94,12 @@ Then in either case:
- "Knows about a specific binary, install path, BYOK keys, vendor models" → `backends/<id>/`
- "React component or modal" → `ui/` (generic) or `backends/<id>/`
(backend-specific)
- "Read-only `AgentDiffView` (editor pane, view type
`copilot-agent-diff-view`, opened via `openAgentDiffView`) rendering an
agent edit diff — sourced from the Claude SDK's `tool_use_result`
(`structuredPatch`/`originalFile`, parsed in `sdk/sdkEditResult.ts`) for
completed edits, from ACP `{type:"diff"}` content otherwise, and
synthesized from tool input for permission-card previews" → `ui/`
- "Canonical-store skill discovery, symlink lifecycle, SKILL.md
parser/serializer, Skills settings tab (reads `backends/registry.ts`
for the brand list)" → `skills/`

View file

@ -52,7 +52,13 @@ describe("readSdkFileEditResult", () => {
newString: "$& $$ $` $1",
originalFile: "before TOKEN after",
structuredPatch: [
{ oldStart: 1, oldLines: 1, newStart: 1, newLines: 1, lines: ["-before TOKEN after", "+before $& $$ $` $1 after"] },
{
oldStart: 1,
oldLines: 1,
newStart: 1,
newLines: 1,
lines: ["-before TOKEN after", "+before $& $$ $` $1 after"],
},
],
userModified: false,
replaceAll: false,
@ -71,7 +77,13 @@ describe("readSdkFileEditResult", () => {
newString: "X",
originalFile: "dup then dup",
structuredPatch: [
{ oldStart: 1, oldLines: 1, newStart: 1, newLines: 1, lines: ["-dup then dup", "+X then dup"] },
{
oldStart: 1,
oldLines: 1,
newStart: 1,
newLines: 1,
lines: ["-dup then dup", "+X then dup"],
},
],
userModified: false,
replaceAll: false,
@ -106,7 +118,13 @@ describe("readSdkFileEditResult", () => {
filePath: "/vault/note.md",
content: "the full new file body",
structuredPatch: [
{ oldStart: 1, oldLines: 1, newStart: 1, newLines: 1, lines: ["-old", "+the full new file body"] },
{
oldStart: 1,
oldLines: 1,
newStart: 1,
newLines: 1,
lines: ["-old", "+the full new file body"],
},
],
originalFile: "old",
};

View file

@ -35,8 +35,7 @@ export const ActionCard: React.FC<ActionCardProps> = ({ part, inline }) => {
// A completed edit whose before/after we can resolve gets the pane treatment:
// an inline +/ chip and a whole-row click that opens the diff view. Non-edit
// tools yield null here, so they keep the classic expand/file-open behavior.
const editDiff =
part.status === "completed" ? deriveEditDiff(part, summaryCtx) : null;
const editDiff = part.status === "completed" ? deriveEditDiff(part, summaryCtx) : null;
const isEditWithDiff = editDiff !== null;
const stats = editDiff ? diffStats(editDiff) : null;
@ -57,9 +56,7 @@ export const ActionCard: React.FC<ActionCardProps> = ({ part, inline }) => {
? (summary.targetPath?.(part, summaryCtx) ?? null)
: null;
const openDiff = editDiff
? () => openAgentDiffView(app, editDiff)
: undefined;
const openDiff = editDiff ? () => openAgentDiffView(app, editDiff) : undefined;
const rowInteractive = isEditWithDiff || expandable;
const headerClasses = cn(

View file

@ -26,10 +26,7 @@ interface EditInput {
* with `toolSummaries` so the alias list can't drift between the two.
*/
export function rawEditPath(input: unknown): string | null {
const i = input as
| { file_path?: unknown; filePath?: unknown; path?: unknown }
| null
| undefined;
const i = input as { file_path?: unknown; filePath?: unknown; path?: unknown } | null | undefined;
if (typeof i?.file_path === "string") return i.file_path;
if (typeof i?.filePath === "string") return i.filePath;
if (typeof i?.path === "string") return i.path;