refactor(proxy): split the four god files into focused modules - #162
Merged
Merged
Conversation
…modules The proxy layer carried several independent copies of the same primitives: three stringifyContent implementations, three asRecord guards, twelve inline SSE response-header blocks, and fifteen spelled-out [DONE] frames. They had already drifted - one SSE block carried a CORS header the rest did not. Move each to lib/server/shared and point every caller at it.
web-search-loop.ts was 2143 lines holding eight unrelated concerns. Extract the wire types, declaration classification, argument parsing, turn folding, provider invocation, response buffering, stream probing and SSE synthesis into their own modules, leaving the two loops as the only thing the original file owns. Also drops an inlined copy of the invocation-building and dispatch logic that executeWebSearchLoop carried alongside the shared buildServerToolInvocation/executeServerToolInvocations helpers; the two were identical, including id format, key order and callback ordering.
anthropic.ts was 1734 lines mixing protocol types, content conversion, request and response translation, streaming and error shaping. Each of those now has its own module, leaving the route entry point and the re-exports that keep the public surface unchanged.
responses.ts was 2961 lines. Session persistence, tool translation, transcript construction, payload assembly and the SSE mapper are now separate modules; the entry point keeps only request dispatch and the three public exports. The id helpers move to responses-ids.ts so the transcript layer can mint an id without reaching back into the payload builder, which would otherwise make the two modules import each other. Also splits the streaming orchestrator out of the SSE mapper, so the file holding the mapper is 727 lines instead of 1016.
…modules codebuddy.ts was 3493 lines and the largest file in the repo. Wire types, credential-context resolution, usage tracking, upstream request building, the Responses translations, chat stream handling, server-tool detection and model discovery now each have their own module. The original keeps the three entry points plus the re-export block, so no importer changes.
The shared modules were assembled from code that lived inside files whose overall coverage hid which branches were untested. Now that they stand alone, the gaps are visible, so cover them directly.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #162 +/- ##
==========================================
+ Coverage 95.57% 95.73% +0.15%
==========================================
Files 37 70 +33
Lines 6738 6708 -30
Branches 1944 1927 -17
==========================================
- Hits 6440 6422 -18
+ Misses 298 286 -12
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
Grouping the modules extracted from each god file behind a folder -- proxy/codebuddy/, proxy/responses/, proxy/anthropic/ and proxy/server-tool/ -- and dropping the now-redundant filename prefixes, so codebuddy/models.ts reads as "the models module of codebuddy" rather than as a sibling of codebuddy.ts. The entry points stay at the proxy root with their import paths intact: TypeScript and the bundler resolve ./codebuddy to codebuddy.ts, not to the folder of the same name. No behaviour change; the module graph is identical, cycles included.
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.
Summary
The proxy layer had accumulated four files of 1,700–3,500 lines that mixed unrelated concerns and duplicated each other's machinery. This splits them into focused modules and lifts the truly shared primitives into
lib/server/shared/.proxy/codebuddy.tsproxy/responses.tsproxy/web-search-loop.tsproxy/anthropic.tsEach protocol's modules live in a folder of their own, so a module reads as "the models module of codebuddy" rather than as a sibling of
codebuddy.ts:The entry points stay at the proxy root with their import paths intact — TypeScript and the bundler resolve
./codebuddytocodebuddy.ts, not to the folder of the same name.Duplication consolidated
Several primitives were declared independently in two or three places each, and had already drifted — one of the twelve SSE header blocks carried a CORS header the others did not.
stringifyContent— three copies (anthropic,responses,codebuddy) →shared/content.tsasRecord— three copies (web-search-loop,account-status,debug) →shared/content.ts[DONE]frame — 12 and 15 inline copies →shared/sse.tsreadReasoning— thereasoning_content ?? reasoningidiom, in five variants →shared/content.tsexecuteWebSearchLoopcarried an inlined copy of the invocation-building and dispatch logic thatbuildServerToolInvocation/executeServerToolInvocationsalready provide. Identical in id format, key order and callback ordering, so replaced.Structure
Each split module owns one concern — session persistence, tool translation, transcript construction, stream mapping, model discovery, and so on. The original files keep only their entry points plus a re-export block, so no importer changes, and the public surface of every module is byte-identical to before.
responses/ids.tsexists specifically to break a cycle: the transcript layer needs to mint ids, and reaching back into the payload builder for them made the two import each other. The remaining cycles in the module graph areimport typeonly and predate this change.Verification
Behaviour-preserving throughout — pure code movement, verified by the existing suite.
lint,format:check,typecheck,buildall passtest:patch-branches: 92.30%, above the 90% gateThe new unit tests were needed because the shared helpers were previously untested branches hidden inside files whose overall coverage masked them; once extracted, the patch gate surfaced them.
Not included
app/page-shell.tsx(2,074 lines) is the largest remaining file, but it is a single React component — splitting it means extracting UI sub-components, which needs visual verification this change does not have. Flagging it, along withapp/debug/debug.tsxandlib/server/admin/session.ts, as follow-ups.