From 1448c184680551249c685e0f1652b8d9d299711a Mon Sep 17 00:00:00 2001 From: Brad Harris Date: Fri, 21 Aug 2026 03:04:27 -0600 Subject: [PATCH] Import the agent-diff wire types from the server MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit apps/web/src/hooks/use-agent-diff.ts hand-restated four types that apps/server/src/shared/git/agent-diff.ts already declares. This is sub-item (f) of the server<->web wire-type duplication cluster; (a)-(e) landed in #965, #971, #976, #981 and #985. DiffFileStatus, DiffFile and FileDiffResponse were byte-identical and are now type-only imports re-exported under their existing names, so every consumer import is unchanged. DiffResponse had genuinely drifted — the first real drift this cluster has turned up in six consolidations. The web copy declared `baseRef: string | null` and omitted the server's `truncatedFileCount?: number`. Both halves of that are explained by the route rather than by a mistake in either type: the GET /api/v1/agents/:id/diff handler substitutes `{ baseRef: null, files: [] }` when getAgentDiff returns null, so nullability is real on the wire even though the server's own DiffResponse always carries a merge-base SHA. The web type is now derived — Omit plus the nullable baseRef — so the nullability stays documented while truncatedFileCount and any future field come across for free. Type-only change; esbuild erases the imports, so nothing from the server reaches the web bundle. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_014PHD7HNfqtZHTXTLWwxxWo --- apps/web/src/hooks/use-agent-diff.ts | 40 +++++++++++++--------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/apps/web/src/hooks/use-agent-diff.ts b/apps/web/src/hooks/use-agent-diff.ts index ffda6554..edf4071a 100644 --- a/apps/web/src/hooks/use-agent-diff.ts +++ b/apps/web/src/hooks/use-agent-diff.ts @@ -2,33 +2,29 @@ import { useCallback } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { useAtomValue } from "jotai"; +// The diff shapes are defined once on the server and imported type-only — +// esbuild erases these imports, so nothing from the server reaches the web +// bundle. +import type { + DiffFile, + DiffFileStatus, + DiffResponse as AgentDiffResult, + FileDiffResponse, +} from "../../../server/src/shared/git/agent-diff"; + import { api } from "@/lib/api"; import { diffIncludeUncommittedAtom } from "@/lib/store"; -export type DiffFileStatus = "modified" | "added" | "deleted" | "renamed"; - -export type DiffFile = { - path: string; - status: DiffFileStatus; - oldPath?: string; - added: number; - deleted: number; - diff: string | null; - truncated: boolean; -}; +export type { DiffFile, DiffFileStatus, FileDiffResponse }; -export type DiffResponse = { +/** + * Wire shape of GET /api/v1/agents/:id/diff. The server's own DiffResponse + * always carries a merge-base SHA, but the route substitutes + * `{ baseRef: null, files: [] }` when the diff cannot be computed, so baseRef + * is nullable over the wire. + */ +export type DiffResponse = Omit & { baseRef: string | null; - files: DiffFile[]; -}; - -export type FileDiffResponse = { - path: string; - status: DiffFileStatus; - oldPath?: string; - added: number; - deleted: number; - diff: string; }; export function agentDiffQueryKey(agentId: string): [string, string] {