Clear remaining low-risk review debt on the release branch

The PR still had a few targeted review threads around contributor pagination,
route-layer passthroughs, dead header fallbacks, and synthetic response ids.
These are small enough to settle directly on the release branch without
broadening the merge scope, and they tighten the repo back toward the
service-owned boundaries this refactor is aiming for.

Constraint: Keep the changes narrow and regression-covered so the release PR stays green while review threads are closed out
Rejected: Leave the minor threads for follow-up after merge | they were isolated enough to fix now and would keep noise on the PR
Confidence: high
Scope-risk: narrow
Directive: When a route shim stops serving any route-local behavior, point callers at the owning service instead of keeping a passthrough around
Tested: Focused vitest for contributor updater, openai responses response bridge, upstream request builder, stats proxy logs, architecture boundaries; typecheck; repo drift check; git diff --check
Not-tested: Full npm test; unresolved review threads that still require larger product decisions
This commit is contained in:
cita-777
2026-04-18 13:19:29 +08:00
parent 4b5d045b00
commit 02520255db
11 changed files with 127 additions and 18 deletions
+1 -1
View File
@@ -31,7 +31,7 @@ import {
getProxyDebugTraceDetail,
listProxyDebugTraces,
} from "../../services/proxyDebugTraceStore.js";
import { parseProxyLogMessageMeta } from "../proxy/logPathMeta.js";
import { parseProxyLogMessageMeta } from "../../services/proxyLogMessage.js";
import { requiresManagedAccountTokens } from "../../services/accountExtraConfig.js";
import { ACCOUNT_TOKEN_VALUE_STATUS_READY } from "../../services/accountTokenService.js";
import {
+1 -1
View File
@@ -10,7 +10,7 @@ import { mergeProxyUsage, parseProxyUsage, pullSseDataEvents } from '../../servi
import { ensureModelAllowedForDownstreamKey, getDownstreamRoutingPolicy, recordDownstreamCostUsage } from './downstreamPolicy.js';
import { withSiteRecordProxyRequestInit } from '../../services/siteProxy.js';
import { getProxyUrlFromExtraConfig } from '../../services/accountExtraConfig.js';
import { composeProxyLogMessage } from './logPathMeta.js';
import { composeProxyLogMessage } from '../../services/proxyLogMessage.js';
import { formatUtcSqlDateTime } from '../../services/localTimeService.js';
import { detectProxyFailure } from '../../services/proxyFailureJudge.js';
import { resolveProxyLogBilling } from './proxyBilling.js';
+1 -1
View File
@@ -10,7 +10,7 @@ import { parseProxyUsage } from '../../services/proxyUsageParser.js';
import { ensureModelAllowedForDownstreamKey, getDownstreamRoutingPolicy, recordDownstreamCostUsage } from './downstreamPolicy.js';
import { withSiteRecordProxyRequestInit } from '../../services/siteProxy.js';
import { getProxyUrlFromExtraConfig } from '../../services/accountExtraConfig.js';
import { composeProxyLogMessage } from './logPathMeta.js';
import { composeProxyLogMessage } from '../../services/proxyLogMessage.js';
import { formatUtcSqlDateTime } from '../../services/localTimeService.js';
import { resolveProxyLogBilling } from './proxyBilling.js';
import { getProxyAuthContext } from '../../middleware/auth.js';
+1 -1
View File
@@ -9,7 +9,7 @@ import { shouldRetryProxyRequest } from '../../services/proxyRetryPolicy.js';
import { ensureModelAllowedForDownstreamKey, getDownstreamRoutingPolicy, recordDownstreamCostUsage } from './downstreamPolicy.js';
import { withSiteRecordProxyRequestInit } from '../../services/siteProxy.js';
import { getProxyUrlFromExtraConfig } from '../../services/accountExtraConfig.js';
import { composeProxyLogMessage } from './logPathMeta.js';
import { composeProxyLogMessage } from '../../services/proxyLogMessage.js';
import { formatUtcSqlDateTime } from '../../services/localTimeService.js';
import { cloneFormDataWithOverrides, ensureMultipartBufferParser, parseMultipartFormData } from './multipart.js';
import { getProxyAuthContext } from '../../middleware/auth.js';
-5
View File
@@ -1,5 +0,0 @@
export {
composeProxyLogMessage,
parseProxyLogMessageMeta,
type ParsedProxyLogMessageMeta,
} from '../../services/proxyLogMessage.js';
+1 -1
View File
@@ -8,7 +8,7 @@ import { shouldRetryProxyRequest } from '../../services/proxyRetryPolicy.js';
import { ensureModelAllowedForDownstreamKey, getDownstreamRoutingPolicy, recordDownstreamCostUsage } from './downstreamPolicy.js';
import { withSiteRecordProxyRequestInit } from '../../services/siteProxy.js';
import { getProxyUrlFromExtraConfig } from '../../services/accountExtraConfig.js';
import { composeProxyLogMessage } from './logPathMeta.js';
import { composeProxyLogMessage } from '../../services/proxyLogMessage.js';
import { formatUtcSqlDateTime } from '../../services/localTimeService.js';
import { getProxyAuthContext } from '../../middleware/auth.js';
import { buildUpstreamUrl } from './upstreamUrl.js';
@@ -580,7 +580,6 @@ export function buildUpstreamEndpointRequest(input: {
: {};
const anthropicVersion = (
claudeHeaders['anthropic-version']
|| passthroughHeaders['anthropic-version']
|| '2023-06-01'
);
const nativeClaudeBody = (
@@ -1,4 +1,4 @@
import { describe, expect, it } from 'vitest';
import { describe, expect, it, vi } from 'vitest';
import {
buildNormalizedFinalToOpenAiResponsesPayload,
@@ -211,6 +211,87 @@ describe('openai responses response bridge', () => {
});
});
it('generates unique synthetic ids within the same millisecond fallback window', () => {
const nowSpy = vi.spyOn(Date, 'now').mockReturnValue(1700000000);
try {
const first = buildNormalizedFinalToOpenAiResponsesPayload({
upstreamPayload: {
id: '',
model: 'gpt-5',
output: [
{
id: '',
type: 'function_call',
name: 'lookup_weather',
arguments: '{"city":"Paris"}',
},
{
id: '',
type: 'message',
role: 'assistant',
status: 'completed',
content: [{ type: 'output_text', text: 'first' }],
},
],
},
normalized: {
id: '',
model: 'gpt-5',
created: 1700000000,
content: 'first',
reasoningContent: '',
finishReason: 'stop',
toolCalls: [{
id: '',
name: 'lookup_weather',
arguments: '{"city":"Paris"}',
}],
},
usage: {
promptTokens: 1,
completionTokens: 1,
totalTokens: 2,
},
});
const second = buildNormalizedFinalToOpenAiResponsesPayload({
upstreamPayload: {
id: '',
model: 'gpt-5',
output: [
{
id: '',
type: 'message',
role: 'assistant',
status: 'completed',
content: [{ type: 'output_text', text: 'second' }],
},
],
},
normalized: {
id: '',
model: 'gpt-5',
created: 1700000000,
content: 'second',
reasoningContent: '',
finishReason: 'stop',
toolCalls: [],
},
usage: {
promptTokens: 1,
completionTokens: 1,
totalTokens: 2,
},
});
expect(first.id).not.toBe(second.id);
const firstOutput = first.output as Array<Record<string, unknown>>;
const secondOutput = second.output as Array<Record<string, unknown>>;
expect(firstOutput[1]?.id).not.toBe(secondOutput[0]?.id);
} finally {
nowSpy.mockRestore();
}
});
it('keeps the outbound facade pointed at the response bridge object', () => {
expect(openAiResponsesOutbound).toBe(openAiResponsesResponseBridge);
});
@@ -13,6 +13,13 @@ function asTrimmedString(value: unknown): string {
return typeof value === 'string' ? value.trim() : '';
}
let syntheticIdCounter = 0;
function createSyntheticId(prefix: 'resp' | 'msg' | 'call'): string {
syntheticIdCounter += 1;
return `${prefix}_${Date.now()}_${syntheticIdCounter}`;
}
function cloneJson<T>(value: T): T {
if (Array.isArray(value)) {
return value.map((item) => cloneJson(item)) as T;
@@ -26,18 +33,18 @@ function cloneJson<T>(value: T): T {
}
function ensureResponseId(rawId: string): string {
const trimmed = rawId.trim() || `resp_${Date.now()}`;
const trimmed = rawId.trim() || createSyntheticId('resp');
return trimmed.startsWith('resp_') ? trimmed : `resp_${trimmed}`;
}
function ensureMessageId(rawId: string): string {
const trimmed = rawId.trim() || `msg_${Date.now()}`;
const trimmed = rawId.trim() || createSyntheticId('msg');
return trimmed.startsWith('msg_') ? trimmed : `msg_${trimmed}`;
}
function ensureFunctionCallId(rawId: string): string {
const trimmed = rawId.trim();
if (!trimmed) return `call_${Date.now()}`;
if (!trimmed) return createSyntheticId('call');
return trimmed.startsWith('call_') ? trimmed : `call_${trimmed}`;
}
@@ -331,7 +338,7 @@ export function buildNormalizedFinalToOpenAiResponsesPayload(input: {
const normalizedId = typeof normalized.id === 'string' && normalized.id.trim()
? normalized.id.trim()
: `resp_${Date.now()}`;
: createSyntheticId('resp');
const responseId = ensureResponseId(normalizedId);
const messageId = ensureMessageId(normalizedId);
const syntheticOutput = extractSyntheticOutputItemsFromUpstream(upstreamPayload);