Address high-priority review gaps before merging the dev snapshot

The release branch still had unresolved review comments around payload-rule
atomicity, brand blocking, compact fallback controls, and response
compatibility edge-cases. This patch pulls those behaviors back in line with
the intended contracts and adds focused regression coverage for the fragile
bridges.

Constraint: The fixes must stay narrow to the PR branch so review/merge can continue without reopening the larger dev snapshot conflict set
Rejected: Leave outdated-looking threads unresolved until after merge | reviewers still see concrete unfixed regressions in the current release branch
Rejected: Re-run another broad merge from dev/main | too risky while the PR branch is already green and mergeable
Confidence: medium
Scope-risk: moderate
Directive: If these release-branch fixes need to persist for future release cuts, backport them onto dev instead of re-fighting the same review threads next time
Tested: Focused vitest for settings events, brand matcher, compact responses, codex compatibility, anthropic stream bridge, openai chat response bridge; typecheck; repo drift check; git diff --check
Not-tested: Full npm test; live PR thread resolution state after push
This commit is contained in:
cita-777
2026-04-18 13:05:52 +08:00
parent 57db7fd107
commit 4b5d045b00
13 changed files with 338 additions and 72 deletions
@@ -86,14 +86,17 @@ describe('ensureCompactResponsesJsonAcceptHeader', () => {
});
});
it('preserves existing accept values and unrelated platforms', () => {
it('forces compact requests back to application/json even when callers asked for SSE', () => {
expect(ensureCompactResponsesJsonAcceptHeader({
Accept: 'application/json',
Accept: 'text/event-stream',
}, {
sitePlatform: 'codex',
})).toEqual({
Accept: 'application/json',
accept: 'application/json',
});
});
it('preserves unrelated platforms', () => {
expect(ensureCompactResponsesJsonAcceptHeader({}, {
sitePlatform: 'openai',
})).toEqual({});
@@ -42,10 +42,11 @@ export function ensureCompactResponsesJsonAcceptHeader(
},
): Record<string, string> {
if (!shouldForceCompactResponsesJsonAccept(options?.sitePlatform)) return headers;
const existingAccept = asTrimmedString(headers.accept) || asTrimmedString(headers.Accept);
if (existingAccept) return headers;
const nextHeaders = { ...headers };
delete (nextHeaders as Record<string, unknown>).Accept;
delete (nextHeaders as Record<string, unknown>).accept;
return {
...headers,
...nextHeaders,
accept: 'application/json',
};
}
@@ -105,15 +105,16 @@ function isRecord(value: unknown): value is Record<string, unknown> {
}
function getCodexSessionHeaderValue(headers: Record<string, string>): string {
for (const [rawKey, rawValue] of Object.entries(headers)) {
const normalizedKey = rawKey.trim().toLowerCase();
if (
normalizedKey === 'session_id'
|| normalizedKey === 'session-id'
|| normalizedKey === 'conversation_id'
|| normalizedKey === 'conversation-id'
) {
return String(rawValue || '').trim();
const normalizedEntries = Object.entries(headers).map(([rawKey, rawValue]) => [
rawKey.trim().toLowerCase(),
String(rawValue || '').trim(),
] as const);
for (const preferredKey of ['session_id', 'session-id', 'conversation_id', 'conversation-id']) {
const match = normalizedEntries.find(([normalizedKey, normalizedValue]) => (
normalizedKey === preferredKey && normalizedValue
));
if (match) {
return match[1];
}
}
return '';
@@ -626,7 +627,7 @@ export async function handleOpenAiResponsesSurfaceRequest(
ctx.rawErrText = await readRuntimeResponseText(recoveredResponse).catch(() => 'unknown error');
}
}
const compactFallbackEnabled = config.responsesCompactFallbackToResponsesEnabled || !isCodexSite;
const compactFallbackEnabled = config.responsesCompactFallbackToResponsesEnabled;
if (
isCompactRequest
&& compactFallbackEnabled