Import the agent-diff wire types from the server - #989
Merged
Conversation
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<DiffResponse, "baseRef"> 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) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014PHD7HNfqtZHTXTLWwxxWo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
apps/web/src/hooks/use-agent-diff.tshand-restated four types thatapps/server/src/shared/git/agent-diff.tsalready declares. It now type-imports them. One file, +18/-22.This is sub-item (f) of the server↔web wire-type duplication cluster — (a)–(e) landed in #965, #971, #976, #981 and #985. Only (g) (
messages/store.tsvsuse-agent-messages.ts) remains.Headline: this one had real drift
Five of the six prior consolidations found zero drift. This one did not.
The web copy of
DiffResponsewas:The server's is:
Both halves of that gap are explained by the route, not by a mistake in either type:
apps/server/src/routes/agents/lifecycle-routes.ts:394substitutes{ baseRef: null, files: [] }whengetAgentDiffreturns null. SobaseRefreally is nullable on the wire, even though the server's ownDiffResponse(a function return type) always carries a merge-base SHA. The web type was right; the server type simply isn't the wire type here.truncatedFileCountis set atagent-diff.ts:308when a diff exceedsMAX_FILES(1000) and is sent over the wire. Web's copy dropped it.So instead of a flat alias, the web type is derived:
The nullability stays documented at the one place it's true, and
truncatedFileCount— plus any future field — comes across for free.DiffFileStatus,DiffFileandFileDiffResponsewere byte-identical and are plain type-only imports re-exported under their existing names, so every consumer import (changes-file-tree.tsx,changes-diff-section.tsx,changes-tab.test.tsx) is unchanged.Not fixed here (noted, not in scope)
Nothing in the web app reads
truncatedFileCounttoday, so the "diff truncated at 1000 files" signal is silently dropped by the UI. That's a feature gap, not debt — surfacing it is a UI change and belongs in its own PR. Backlogged.Deliberate exclusions (near-miss lookalikes left alone)
agent-diff.ts:55NumstatEntryand:82's inline{ status; oldPath? }map value both share fields withDiffFile, but they are file-private parser intermediates on one side of the boundary — not wire shapes. Left alone./diff-statsfamily (use-agent-diff-stats.ts,shared/git/diff-stats.ts) is a separate route and a separate type tree. Untouched.Why it's tech debt
Two declarations of one wire contract, already measurably drifted apart, with no compiler link between them.
Verification
pnpm run check:webrun before anything createdapps/server/src/generated(that directory is absent on a clean tree) — the web program type-checks against the server source without the generated-file side effect. This is the Alias web release/assisted-update wire types to the server definitions #863 trap and it does not apply here.pnpm run check,pnpm run finalize:web,pnpm run test:e2e(181 passed),apps/webvitest (1064 passed / 71 files) — all green.oldPath?: stringnow has 4 declarations, all insideagent-diff.ts(2 wire + 2 parser internals, above);truncated: booleanandtruncatedFileCountare 1 declaration each. Zero web copies remain.Next run
Sub-item (g):
apps/server/src/messages/store.tsvsapps/web/src/hooks/use-agent-messages.ts— the last of the cluster.