12 KiB
Single Source Consolidation PR1 Implementation Plan
For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
Goal: Land PR1 for the highest-value duplication and double-source issues around responses normalization, shared proxy surface orchestration, provider runtime headers, token-route contract sharing, account mutation workflow, and standard API platform helpers.
Architecture: Keep PR1 focused on extracting shared single-source modules and rewiring existing callers to consume them. Do not expand this PR into schema metamodel rewrites, chatFormatsCore breakup, or mobile page scaffold work; those remain follow-up PR scope once the highest-risk protocol and workflow duplications are removed.
Tech Stack: TypeScript, Fastify, Vitest, shared server/web modules under src/shared, server proxy-core surfaces/providers/services, React admin pages.
Task 1: Savepoint Commit
Files:
- Commit:
src/server/config.ts - Commit:
src/server/config.test.ts - Commit:
src/server/db/proxyFileSchemaCompatibility.ts - Commit:
src/server/db/proxyFileSchemaCompatibility.test.ts
Step 1: Verify the savepoint changes
Run: npm test -- src/server/config.test.ts src/server/db/proxyFileSchemaCompatibility.test.ts
Expected: PASS
Step 2: Commit the savepoint
Run:
git add src/server/config.ts src/server/config.test.ts src/server/db/proxyFileSchemaCompatibility.ts src/server/db/proxyFileSchemaCompatibility.test.ts
git commit -m "fix: trust proxy headers and align proxy file mysql indexes"
Step 3: Cherry-pick into PR1 branch
Run:
git cherry-pick <savepoint-commit>
Expected: first commit preserved inside PR1 branch before the larger consolidation commit.
Task 2: Responses Single Source
Files:
- Create:
src/server/transformers/openai/responses/normalization.ts - Modify:
src/server/transformers/openai/responses/conversion.ts - Modify:
src/server/transformers/openai/responses/compatibility.ts - Test:
src/server/transformers/openai/responses/conversion.test.ts
Step 1: Move shared normalization helpers into one source
Keep normalizeResponsesInputForCompatibility, normalizeResponsesMessageContent, and related block normalization in normalization.ts.
Step 2: Rewire both callers
Make conversion.ts and compatibility.ts import the shared helpers instead of maintaining their own independent copies.
Step 3: Verify parity
Run: npm test -- src/server/transformers/openai/responses/conversion.test.ts
Expected: PASS, including assertions that compatibility exports point at the shared implementation.
Task 3: Shared Surface Orchestration
Files:
- Create:
src/server/proxy-core/surfaces/sharedSurface.ts - Modify:
src/server/proxy-core/surfaces/chatSurface.ts - Modify:
src/server/proxy-core/surfaces/openAiResponsesSurface.ts - Modify:
src/server/proxy-core/surfaces/geminiSurface.ts - Test:
src/server/proxy-core/surfaces/sharedSurface.test.ts
Step 1: Extract common orchestration primitives
Centralize channel selection, dispatch, proxy logging, retry/failure handling, and common failure response shaping in sharedSurface.ts.
Step 2: Rewire surface callers
Make chat and responses surfaces consume the shared orchestration helpers instead of each keeping a parallel flow.
Step 3: Verify behavior
Run: npm test -- src/server/proxy-core/surfaces/sharedSurface.test.ts
Expected: PASS
Task 4: Provider Header Builders
Files:
- Create:
src/server/proxy-core/providers/headerUtils.ts - Modify:
src/server/proxy-core/providers/codexProviderProfile.ts - Modify:
src/server/proxy-core/providers/claudeProviderProfile.ts - Modify:
src/server/proxy-core/providers/geminiCliProviderProfile.ts - Modify:
src/server/routes/proxy/upstreamEndpoint.ts - Test:
src/server/proxy-core/providers/headerUtils.test.ts
Step 1: Extract header parsing and runtime header construction
Keep Codex, Claude, and Gemini CLI runtime header shaping in headerUtils.ts.
Step 2: Remove duplicate builders
Make both provider profiles and upstreamEndpoint.ts call the shared header builders.
Step 3: Verify behavior
Run: npm test -- src/server/proxy-core/providers/headerUtils.test.ts
Expected: PASS
Task 5: Cross-Layer Token Route Contract
Files:
- Create:
src/shared/tokenRouteContract.js - Create:
src/shared/tokenRouteContract.d.ts - Create:
src/shared/tokenRoutePatterns.js - Create:
src/shared/tokenRoutePatterns.d.ts - Modify:
src/server/services/tokenRouter.ts - Modify:
src/server/routes/api/tokens.ts - Modify:
src/web/pages/token-routes/utils.ts - Modify:
src/web/pages/token-routes/types.ts - Modify:
src/web/pages/helpers/routeListVisibility.ts - Modify:
src/web/pages/Settings.tsx - Test:
src/shared/tokenRouteContract.test.ts - Test:
src/shared/tokenRoutePatterns.test.ts
Step 1: Extract shared route mode and pattern matching
Make route mode normalization and model pattern matching authoritative in src/shared.
Step 2: Rewire server and web
Make token router, route APIs, token-routes helpers, and settings consume the shared contract instead of maintaining separate copies.
Step 3: Verify behavior
Run: npm test -- src/shared/tokenRouteContract.test.ts src/shared/tokenRoutePatterns.test.ts
Expected: PASS
Task 6: Account Mutation Workflow
Files:
- Create:
src/server/services/accountMutationWorkflow.ts - Modify:
src/server/routes/api/accounts.ts - Modify:
src/server/routes/api/accountTokens.ts - Test:
src/server/services/accountMutationWorkflow.test.ts
Step 1: Extract convergence workflow
Move token sync, default token ensure, balance refresh, model refresh, and route rebuild sequencing into accountMutationWorkflow.ts.
Step 2: Rewire controllers
Make account and account-token APIs call the workflow service instead of each owning private orchestration logic.
Step 3: Verify behavior
Run: npm test -- src/server/services/accountMutationWorkflow.test.ts
Expected: PASS
Task 7: Standard API Provider Base
Files:
- Create:
src/server/services/platforms/standardApiProvider.ts - Modify:
src/server/services/platforms/openai.ts - Modify:
src/server/services/platforms/claude.ts - Modify:
src/server/services/platforms/gemini.ts - Modify:
src/server/services/platforms/cliproxyapi.ts - Test:
src/server/services/platforms/standardApiProvider.test.ts - Test:
src/server/services/platforms/llmUpstream.test.ts
Step 1: Extract shared standard API adapter logic
Centralize base URL normalization, /v1/models resolution, unsupported login/checkin/balance defaults, and common model fetch behavior.
Step 2: Rewire adapters
Make OpenAI, Claude, Gemini, and CLIProxyAPI adapters extend the shared base instead of repeating the same template logic.
Step 3: Verify behavior
Run: npm test -- src/server/services/platforms/standardApiProvider.test.ts src/server/services/platforms/llmUpstream.test.ts
Expected: PASS
Task 8: Shared Input File Resolution And Web Helpers
Files:
- Modify:
src/server/services/proxyInputFileResolver.ts - Modify:
src/server/services/proxyInputFileResolver.test.ts - Modify:
src/server/proxy-core/surfaces/inputFilesSurface.ts - Create:
src/web/pages/helpers/accountConnection.ts - Create:
src/web/pages/helpers/accountConnection.test.ts - Modify:
src/web/pages/Accounts.tsx - Modify:
src/web/pages/Tokens.tsx - Modify:
src/web/api.ts - Modify:
src/web/api.test.ts
Step 1: Make route-level file inlining reuse the service implementation
Replace the duplicate inputFilesSurface.ts implementation with a re-export of the shared resolver service.
Step 2: Extract shared web account helpers
Move resolveAccountCredentialMode, parsePositiveInt, and isTruthyFlag into a single helper consumed by both Accounts and Tokens.
Step 3: De-duplicate proxy test aliases
Make testProxy / proxyTest and stream variants reuse the same implementation function.
Step 4: Verify behavior
Run: npm test -- src/server/services/proxyInputFileResolver.test.ts src/web/pages/helpers/accountConnection.test.ts src/web/api.test.ts
Expected: PASS
Task 9: PR1 Verification And Commit
Files:
- Verify:
scripts/dev/copy-runtime-db-generated.ts - Verify:
scripts/dev/copy-runtime-db-generated.test.ts - Verify: all files touched in Tasks 2-8
Step 1: Run focused regression suite
Run:
npm test -- scripts/dev/copy-runtime-db-generated.test.ts src/server/proxy-core/cliProfiles/codexProfile.test.ts src/server/proxy-core/providers/headerUtils.test.ts src/server/proxy-core/surfaces/sharedSurface.test.ts src/server/routes/api/oauth.test.ts src/server/services/accountMutationWorkflow.test.ts src/server/services/modelService.discovery.test.ts src/server/services/oauth/oauthAccount.test.ts src/server/services/platforms/standardApiProvider.test.ts src/server/services/platforms/llmUpstream.test.ts src/server/services/proxyInputFileResolver.test.ts src/server/transformers/openai/responses/conversion.test.ts src/shared/tokenRouteContract.test.ts src/shared/tokenRoutePatterns.test.ts src/web/api.test.ts src/web/pages/helpers/accountConnection.test.ts
Expected: PASS
Step 2: Run server build
Run: npm run build:server
Expected: PASS
Step 3: Commit PR1 consolidation work
Run:
git add docs/plans/2026-03-22-single-source-consolidation-pr1.md scripts/dev/copy-runtime-db-generated.test.ts scripts/dev/copy-runtime-db-generated.ts src/server/proxy-core/cliProfiles/codexProfile.ts src/server/proxy-core/cliProfiles/codexProfile.test.ts src/server/proxy-core/providers/headerUtils.ts src/server/proxy-core/providers/headerUtils.test.ts src/server/proxy-core/providers/claudeProviderProfile.ts src/server/proxy-core/providers/codexProviderProfile.ts src/server/proxy-core/providers/geminiCliProviderProfile.ts src/server/proxy-core/surfaces/chatSurface.ts src/server/proxy-core/surfaces/geminiSurface.ts src/server/proxy-core/surfaces/inputFilesSurface.ts src/server/proxy-core/surfaces/openAiResponsesSurface.ts src/server/proxy-core/surfaces/sharedSurface.ts src/server/proxy-core/surfaces/sharedSurface.test.ts src/server/routes/api/accountTokens.ts src/server/routes/api/accounts.ts src/server/routes/api/oauth.test.ts src/server/routes/api/tokens.ts src/server/routes/proxy/downstreamClientContext.ts src/server/routes/proxy/responsesWebsocket.ts src/server/routes/proxy/upstreamEndpoint.ts src/server/services/accountMutationWorkflow.ts src/server/services/accountMutationWorkflow.test.ts src/server/services/backupService.ts src/server/services/modelService.discovery.test.ts src/server/services/modelService.ts src/server/services/oauth/oauthAccount.ts src/server/services/oauth/oauthAccount.test.ts src/server/services/oauth/quota.ts src/server/services/oauth/service.ts src/server/services/platforms/claude.ts src/server/services/platforms/cliproxyapi.ts src/server/services/platforms/gemini.ts src/server/services/platforms/llmUpstream.test.ts src/server/services/platforms/openai.ts src/server/services/platforms/standardApiProvider.ts src/server/services/platforms/standardApiProvider.test.ts src/server/services/proxyInputFileResolver.ts src/server/services/proxyInputFileResolver.test.ts src/server/services/siteProxy.ts src/server/services/tokenRouter.ts src/server/transformers/anthropic/messages/inbound.ts src/server/transformers/openai/responses/compatibility.ts src/server/transformers/openai/responses/conversion.test.ts src/server/transformers/openai/responses/conversion.ts src/server/transformers/openai/responses/normalization.ts src/shared/tokenRouteContract.d.ts src/shared/tokenRouteContract.js src/shared/tokenRouteContract.test.ts src/shared/tokenRoutePatterns.d.ts src/shared/tokenRoutePatterns.js src/shared/tokenRoutePatterns.test.ts src/web/api.ts src/web/api.test.ts src/web/pages/Accounts.tsx src/web/pages/Settings.tsx src/web/pages/Tokens.tsx src/web/pages/helpers/accountConnection.ts src/web/pages/helpers/accountConnection.test.ts src/web/pages/helpers/routeListVisibility.ts src/web/pages/token-routes/types.ts src/web/pages/token-routes/utils.ts
git commit -m "refactor: consolidate single-source routing and protocol helpers"
Deferred After PR1
Keep out of this PR:
shared/chatFormatsCore.tsbreakup- Gemini
generate-contentmodule boundary cleanup - schema contract/introspection meta-rule unification
legacySchemaCompat.tsfeature compatibility dedupe- mobile page scaffold extraction
- large-file decomposition for
Settings.tsx,ModelTester.tsx,tokenRouter.ts,modelService.ts