Skip to content

refactor(sse): extract request guards, failure handling and post-translation finalize out of chatCore (slice 2) - #16901

Merged
diegosouzapw merged 21 commits into
release/v3.8.52from
refactor/rail3-chatcore-slice-2
Oct 17, 2026
Merged

diegosouzapw merged 21 commits into
release/v3.8.52from
refactor/rail3-chatcore-slice-2

Conversation

@diegosouzapw

@diegosouzapw diegosouzapw commented Oct 16, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Slice 2 of the chatCore.ts decomposition (#3501). Twenty request-path blocks move out of handleChatCoreInner into leaves under open-sse/handlers/chatCore/. Each one is lifted mechanically and called from the same point, so behaviour, side-effect order, logs and messages do not change. chatCore.ts goes from 3,948 to 3,286 lines (wc -l; the gate's split("\n").length reads 3,949 → 3,287), which meets the ≤ 3,300 target.

Design after #15709 (HouMinXi), which the author closed on 2026-10-15 after the branch drifted. Commits that reuse its module design or code carry Co-authored-by: Minxi Hou <houminxi@gmail.com>.

Root cause / design

  • One extraction per commit. Each leaf takes explicit, typed parameters and adds no any. Where a block mutated several handler bindings, the leaf gets a typed state object and updates it in place exactly where the inline code assigned it (postTranslationCompression). Late-bound handlers are read through getters at event time (chatStreamController). With this, even a part-way failure leaves the same state the inline block did.
  • No new open-sse → src import edges. The new boundary ratchet (ci(quality): ratchet the open-sse → src boundary (check:boundary:ratchet) #16874) counts unique file→file edges. Leaves therefore receive their src/ dependencies from the handler instead of importing them: getCachedSettings, applyReasoningRuleDirective, getModelNormalizeToolCallId/getModelPreserveOpenAIDeveloperRole, supportsMaxTokens() result, trackPendingRequest callback, typed event-bus emit, finalizePendingScope. The five edges that did move (lease DB, quota enforce/types, plugin hooks, CC request defaults) were removed from chatCore.ts at the same time. The measured count is 773 on both the base tip and this branch.
  • Source-guard tests were not edited. Several suites pin text inside chatCore.ts (refactor(sse): split chatCore request guards and failure handling #15709 had to edit one). This slice leaves those regions inline: the credential-refresh closures (token-refresh-race-comprehensive, hard-session-lease-bypass-inventory), applyProviderFailureClassification (upstream-status-restatement R10, api-key-429-cooldown, antigravity-429-quota-cooldown, the error-public-boundaries fixture's lastError: persistentMessage ≥ 9 count), the dedup hash (request-dedup-tenant-isolation), the Tier-2/Gemini TPM guards (pre-dispatch-error-route-meta), the compression gating expressions and the if (runPostTranslationCompression / translatedBody = translateRequest( anchors.

What changed

Module (new, open-sse/handlers/chatCore/) lines chatCore.ts Δ Covered by
managedLeaseFence.ts ¹ 62 +4/−40 hard-session-lease inventory, g13 golden, leaf-deps-contract
customSystemPrompt.ts ¹ 34 +5/−18 g13 golden, chatcore-* functional
pluginRequestGate.ts ¹ 51 +6/−21 8395-plugin-hooks-fire, chatcore-plugin-onrequest
deviceTracking.ts ¹ 22 +6/−8 g13 golden
clientToolNames.ts 32 +3/−20 namespace-tool-identity-integration, web-search fallback suites
requestTranslationError.ts 78 +12/−41 chatcore-translation-paths, translation-failure suites
claudeCodeBridgeBody.ts 157 +23/−80 cc-compatible-provider, claude-* passthrough suites
claudePassthroughBody.ts 138 +15/−102 claude-passthrough-, claude-mid-system-, claude-directive-*
postTranslationCompression.ts ¹ 119 +26/−63 omniglyph-chatcore-plumbing, chatcore-compression-*
translatedRequestFinalize.ts ¹ (incl. #16867 OpenRouter step) 179 +14/−117 openrouter-tool-schema-patterns, namespace-tool-identity, codex suites
upstreamRequestParams.ts 80 +14/−48 gpt6-max-tokens-rename-14869, repro-6912
quotaSharePreHook.ts 108 +17/−72 chatcore-quota-share-consumption, g13 golden
compressionComboConfig.ts 69 +9/−51 chatcore-compression-integration, default-combo-lossy-policy
compressionLiveEvents.ts 122 +14/−54 chatcore-compression-*
finalOutputBudget.ts 79 +15/−30 chatcore-model-output-cap-wiring, combo-context-limit suites
chatStreamController.ts 82 +11/−30 chatcore-streaming-*, streaming-tail
reasoningInputGate.ts 70 +20/−36 chatcore-reasoning-control, suffix-effort-propagation
providerRequestRegistration.ts 46 +12/−21 g13 golden, chatcore-*
liveZoneCompression.ts 71 +12/−38 chatcore-compression-*
connectionUpstreamOverrides.ts 33 +5/−15 chatcore-upstream-execute-headers

¹ design/code after #15709 (co-authored).

Also: config/quality/file-size-baseline.json lowers frozen["open-sse/handlers/chatCore.ts"] by hand from 4732 to 3945 (= ⌈3287 × 1.2⌉, keeping the #16831 headroom), with the note _rebaseline_2026_10_16_chatcore_slice_2. No other entry changes, and --update was not run. The changelog fragment is changelog.d/maintenance/0000-chatcore-slice-2.md.

Validation

Command Result
Golden/characterization set (166 files: every test importing chatCore.ts, every source guard reading it, chatcore-*, chatcore/*, g13 golden), DATA_DIR isolated 1426 pass / 6 fail / 4 skipped (1436 tests). The 6: 2 base-red compaction source guards (#16627, also red on the tip) and 4 already red in the pre-change baseline (call-log mapping ×2, #11825 plugin delivery, network-failure call log). No new failure. Pre-change baseline (older tip, 165 files): 1406 pass / 15 fail
Fast golden set (33 files) on the new tip before touching anything 311 pass / 4 fail. 2 are the flaky call-logs-id-collision; 2 are the base-red reactive-compaction source guards broken on the tip by #16627
Fast golden set at the mid-way rebase 325 pass / 2 fail (the same 2 base-red guards)
Quick golden (16 files, 143 tests) after each of the 20 commits 143/143 every time
npm run typecheck:core 0 errors
node scripts/check/check-open-sse-typecheck.mjs (covers chatCore + leaves) 0 errors, OK
npm run check:cycles:ratchet 14 cycles, within ceiling 14
node --import tsx scripts/check/check-known-symbols.ts OK
npm run check:file-size OK (176 frozen, new files under cap 1440)
node scripts/quality/measure-boundary.mjs --ratchet 773 edges on this branch, 773 on the base tip too (ceiling 771, already red on the base; this PR adds 0)
npx eslint / npx prettier --check on touched files clean

Not done

  • Credential refresh, provider-failure classification and request dedup stayed inline (the refactor(sse): split chatCore request guards and failure handling #15709 modules credentialRefreshRetry, providerFailureClassification, persistFailureUsage, requestDedup). Moving them requires editing source-guard tests that pin their text in chatCore.ts, and this slice edits no tests. A follow-up can re-point those guards first.
  • Coverage was not run. coverage.chatCore.lines in quality-baseline.json may move because lines left the file; the CI ratchet re-measures it.
  • The boundary ratchet is red on the base (773 > 771). Fixing that is out of scope.

⚠️ base-red inherited: #15306

diegosouzapw and others added 21 commits October 16, 2026 18:41
Move the managed exclusive-connection lease fence (assert + LEASE_*
error-code mapping + 409 lease-error result) from handleChatCore into
chatCore/managedLeaseFence.ts. Byte-identical behaviour; the handler
destructures the same three helpers it passed to the response legs.
chatCore slice 2, design after #15709 (HouMinXi).

Co-authored-by: Minxi Hou <houminxi@gmail.com>
Move the per-endpoint custom system prompt injection (#2063 port) into
chatCore/customSystemPrompt.ts. The handler still resolves the settings
snapshot (cachedSettings, else getCachedSettings()) at the same point
and passes it in, so the leaf adds no open-sse -> src import edge.
Byte-identical behaviour. chatCore slice 2, design after #15709
(HouMinXi).

Co-authored-by: Minxi Hou <houminxi@gmail.com>
Move the handler-side outcome of the plugin onRequest hook (labelled
403 plugin_block result on block, truthy body rewrite) into
chatCore/pluginRequestGate.ts. Byte-identical behaviour. chatCore slice
2, design after #15709 (HouMinXi).

Co-authored-by: Minxi Hou <houminxi@gmail.com>
Move the per-API-key device/connection tracking call (9router#931 port)
into chatCore/deviceTracking.ts. Byte-identical behaviour. chatCore
slice 2, design after #15709 (HouMinXi).

Co-authored-by: Minxi Hou <houminxi@gmail.com>
… chatCore

Move the capture of the client's own tool names (taken before the
web-search / web-fetch fallback preparers inject synthetic tools) into
chatCore/clientToolNames.ts. Byte-identical behaviour. chatCore slice 2.
…atCore

Move the translation catch body (plugin onError hook, defensive
status/message/type derivation from hostile thrown values,
translation-failure result + warn log) into
chatCore/requestTranslationError.ts. The handler keeps the
pending-request finalization and the early return. Byte-identical
behaviour. chatCore slice 2.
…Core

Move the isClaudeCodeCompatible translation branch into
chatCore/claudeCodeBridgeBody.ts; it returns the dispatch body and the
resolved bridge session id. The model flag lookups and the
reasoning-rule directive helper are injected by the handler, so the
leaf adds no open-sse -> src import edge. Byte-identical behaviour.
chatCore slice 2.
Move the pure Claude -> Claude passthrough translation branch (#1359:
deferred-tool hoist, Anthropic history sanitation, system-role
handling, output_format migration, output_config.format strip) into
chatCore/claudePassthroughBody.ts. The reasoning-rule directive helper
is injected. Byte-identical behaviour. chatCore slice 2.
…chatCore

Move the deferred post-translation OmniGlyph stage into
chatCore/postTranslationCompression.ts. The handler keeps the 'if
(runPostTranslationCompression ...)' gate and hands the four
request-scope bindings (translatedBody, tokensCompressed,
compressionResponseMeta, compressionAnalyticsWritePromise) in a state
object the stage updates in place, so even a partial failure leaves the
same state as the inline block. Fail-open as before. chatCore slice 2,
design after #15709 (HouMinXi).

Co-authored-by: Minxi Hou <houminxi@gmail.com>
…hatCore

Move the post-translation finalization (request tool metadata,
OpenRouter / Kiro / Claude tool-schema dispatch fixes, response
tool-name map, side-channel strip, upstream model id,
previous_response_id policy, Codex effort-suffix guard) into
chatCore/translatedRequestFinalize.ts. Byte-identical behaviour.
chatCore slice 2, design after #15709 (HouMinXi).

Co-authored-by: Minxi Hou <houminxi@gmail.com>
…atCore

Move the max_tokens / max_completion_tokens reconciliation (#1961,
#6912), store strip, Responses stream_options drop and provider output
caps (#711) into chatCore/upstreamRequestParams.ts. supportsMaxTokens()
is still evaluated by the handler at the same point and passed in.
Byte-identical behaviour. chatCore slice 2.
Move the Quota Share enforcement pre-hook (B/F7, fail-open) and its
combo soft-penalty propagation (G2) into chatCore/quotaSharePreHook.ts;
it returns the 429 response on block. The pending-request finalization
is injected by the handler. Byte-identical behaviour. chatCore slice 2.
Move the body of the applyCompressionComboConfig closure (fold a
runtime compression combo's pipeline, language packs and output mode
into the request CompressionConfig) into the pure
chatCore/compressionComboConfig.ts. The closure keeps the config
rebinding and the compressionComboApplied flag. Byte-identical
behaviour. chatCore slice 2.
Move the compression.step (F3.3) and compression.completed (U5) event
emission into chatCore/compressionLiveEvents.ts. The typed event-bus
emit is injected by the handler, so the leaf adds no open-sse -> src
import edge. Best-effort semantics unchanged. chatCore slice 2.
Move the enforceOutputTokenBudget call against the concrete target plus
its reject message and adjusted-fields log into
chatCore/finalOutputBudget.ts. The handler keeps the model output cap /
input cap resolution, the pending-request finalization and the 400
context_length_exceeded return. Byte-identical behaviour. chatCore
slice 2.
Move the createStreamController wiring (disconnect finalizer chain, 499
client_disconnected fallback, caller onDisconnect) into
chatCore/chatStreamController.ts. The two late-bound handlers are read
through getters at event time and finalizePendingScope is injected.
Byte-identical behaviour. chatCore slice 2.
Move the reasoning input policy application (OpenAI Chat / Responses
inbound bodies, #11178 combo-step fallback resolution) into
chatCore/reasoningInputGate.ts; it reports an incompatible target and
the handler returns the 400. Byte-identical behaviour. chatCore slice 2.
…hatCore

Move the pending-scope provider-request snapshot builder and the
cross-wire-shape message count into
chatCore/providerRequestRegistration.ts. Byte-identical behaviour.
chatCore slice 2.
Move the live-zone prompt-compression lane (session id resolution +
applyLiveZoneCompression dispatch, still lazily imported) into
chatCore/liveZoneCompression.ts. Byte-identical behaviour. chatCore
slice 2.
Move the connection-level custom User-Agent and #8369 custom upstream
headers resolution into chatCore/connectionUpstreamOverrides.ts.
Byte-identical behaviour. chatCore slice 2.
chatCore.ts measures 3287 (split("\n").length) after slice 2, down from
3949 on the tip. Lower its frozen ceiling by hand 4732 -> 3945 =
ceil(3287 x 1.2), keeping the #16831 20% headroom on the new size, and
record it as _rebaseline_2026_10_16_chatcore_slice_2. Only this entry is
touched; check:file-size --update was not run. Adds the maintenance
changelog fragment.

Co-authored-by: Minxi Hou <houminxi@gmail.com>
@diegosouzapw
diegosouzapw merged commit 07f7826 into release/v3.8.52 Oct 17, 2026
10 of 78 checks passed
@diegosouzapw
diegosouzapw deleted the refactor/rail3-chatcore-slice-2 branch October 17, 2026 03:49
@github-actions

Copy link
Copy Markdown
Contributor

CI Coverage Report

  • Coverage job: skipped
  • PR test policy: failure

Coverage artifact was not available for this run.

PR Test Policy

This PR changes production code in src/, open-sse/, electron/, or bin/ without accompanying automated tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant