forked from boos/BoosAPI
fix: minimize codex upstream headers and clean quota wording
This commit is contained in:
@@ -994,7 +994,7 @@ describe('oauth routes', { timeout: 15_000 }, () => {
|
||||
success: true,
|
||||
quota: expect.objectContaining({
|
||||
status: 'unsupported',
|
||||
providerMessage: 'current local CLIProxyAPI evidence does not expose official quota windows for antigravity oauth',
|
||||
providerMessage: 'official quota windows are not exposed for antigravity oauth',
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
@@ -173,6 +173,9 @@ describe('responses proxy codex oauth refresh', () => {
|
||||
const response = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/v1/responses',
|
||||
headers: {
|
||||
'user-agent': 'CodexClient/1.0',
|
||||
},
|
||||
payload: {
|
||||
model: 'gpt-5.2-codex',
|
||||
input: 'hello codex',
|
||||
@@ -194,7 +197,7 @@ describe('responses proxy codex oauth refresh', () => {
|
||||
expect(secondOptions.headers.Version || secondOptions.headers.version).toBe('0.101.0');
|
||||
expect(String(secondOptions.headers.Session_id || secondOptions.headers.session_id || '')).toMatch(/^[0-9a-f-]{36}$/i);
|
||||
expect(secondOptions.headers.Conversation_id || secondOptions.headers.conversation_id).toBeUndefined();
|
||||
expect(secondOptions.headers['User-Agent'] || secondOptions.headers['user-agent']).toBe('codex_cli_rs/0.101.0 (Mac OS 26.0.1; arm64) Apple_Terminal/464');
|
||||
expect(secondOptions.headers['User-Agent'] || secondOptions.headers['user-agent']).toBe('CodexClient/1.0');
|
||||
expect(secondOptions.headers.Accept || secondOptions.headers.accept).toBe('text/event-stream');
|
||||
expect(secondOptions.headers.Connection || secondOptions.headers.connection).toBe('Keep-Alive');
|
||||
expect(response.json()?.output_text).toContain('ok after codex token refresh');
|
||||
@@ -272,6 +275,50 @@ describe('responses proxy codex oauth refresh', () => {
|
||||
expect(forwardedBody.prompt_cache_key).toBe('codex-cache-123');
|
||||
});
|
||||
|
||||
it('strips generic downstream headers before forwarding codex responses upstream', async () => {
|
||||
fetchMock.mockResolvedValue(new Response(JSON.stringify({
|
||||
id: 'resp_codex_header_filter',
|
||||
object: 'response',
|
||||
model: 'gpt-5.2-codex',
|
||||
status: 'completed',
|
||||
output_text: 'ok with filtered headers',
|
||||
usage: { input_tokens: 4, output_tokens: 2, total_tokens: 6 },
|
||||
}), {
|
||||
status: 200,
|
||||
headers: { 'content-type': 'application/json' },
|
||||
}));
|
||||
|
||||
const response = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/v1/responses',
|
||||
headers: {
|
||||
'openai-beta': 'responses-2025-03-11',
|
||||
'x-openai-client-user-agent': '{"client":"openclaw"}',
|
||||
origin: 'https://openclaw.example',
|
||||
referer: 'https://openclaw.example/app',
|
||||
'user-agent': 'OpenClaw/1.0',
|
||||
version: '0.202.0',
|
||||
session_id: 'session-from-client',
|
||||
},
|
||||
payload: {
|
||||
model: 'gpt-5.2-codex',
|
||||
input: 'hello codex',
|
||||
},
|
||||
});
|
||||
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(fetchMock).toHaveBeenCalledTimes(1);
|
||||
|
||||
const [, options] = fetchMock.mock.calls[0] as [string, any];
|
||||
expect(options.headers.Version || options.headers.version).toBe('0.202.0');
|
||||
expect(options.headers.Session_id || options.headers.session_id).toBe('session-from-client');
|
||||
expect(options.headers['User-Agent'] || options.headers['user-agent']).toBe('OpenClaw/1.0');
|
||||
expect(options.headers['openai-beta']).toBeUndefined();
|
||||
expect(options.headers['x-openai-client-user-agent']).toBeUndefined();
|
||||
expect(options.headers.origin).toBeUndefined();
|
||||
expect(options.headers.referer).toBeUndefined();
|
||||
});
|
||||
|
||||
it('records codex usage_limit_reached reset hints on upstream 429 failures', async () => {
|
||||
fetchMock.mockResolvedValue(new Response(JSON.stringify({
|
||||
error: {
|
||||
|
||||
@@ -286,8 +286,15 @@ function buildCodexRuntimeHeaders(input: {
|
||||
explicitSessionId?: string | null;
|
||||
continuityKey?: string | null;
|
||||
}): Record<string, string> {
|
||||
const authorization = (
|
||||
getInputHeader(input.baseHeaders, 'authorization')
|
||||
|| getInputHeader(input.baseHeaders, 'Authorization')
|
||||
|| ''
|
||||
);
|
||||
const originator = getInputHeader(input.providerHeaders, 'originator') || 'codex_cli_rs';
|
||||
const accountId = getInputHeader(input.providerHeaders, 'chatgpt-account-id');
|
||||
const version = getInputHeader(input.baseHeaders, 'version') || CODEX_CLIENT_VERSION;
|
||||
const userAgent = getInputHeader(input.baseHeaders, 'user-agent') || CODEX_DEFAULT_USER_AGENT;
|
||||
const explicitSessionId = asTrimmedString(input.explicitSessionId);
|
||||
const continuityKey = asTrimmedString(input.continuityKey);
|
||||
const sessionId = (
|
||||
@@ -305,13 +312,14 @@ function buildCodexRuntimeHeaders(input: {
|
||||
);
|
||||
|
||||
return {
|
||||
...input.baseHeaders,
|
||||
Authorization: authorization,
|
||||
'Content-Type': 'application/json',
|
||||
...(accountId ? { 'Chatgpt-Account-Id': accountId } : {}),
|
||||
Originator: originator,
|
||||
Version: CODEX_CLIENT_VERSION,
|
||||
Version: version,
|
||||
Session_id: sessionId,
|
||||
...(conversationId ? { Conversation_id: conversationId } : {}),
|
||||
'User-Agent': CODEX_DEFAULT_USER_AGENT,
|
||||
'User-Agent': userAgent,
|
||||
Accept: 'text/event-stream',
|
||||
Connection: 'Keep-Alive',
|
||||
};
|
||||
|
||||
@@ -76,7 +76,7 @@ describe('oauth quota snapshot helpers', () => {
|
||||
expect(snapshot).toEqual({
|
||||
status: 'unsupported',
|
||||
source: 'official',
|
||||
providerMessage: 'current local CLIProxyAPI evidence does not expose official quota windows for antigravity oauth',
|
||||
providerMessage: 'official quota windows are not exposed for antigravity oauth',
|
||||
windows: {
|
||||
fiveHour: {
|
||||
supported: false,
|
||||
|
||||
@@ -54,7 +54,7 @@ function buildProviderUnsupportedSnapshot(provider: string): OauthQuotaSnapshot
|
||||
return {
|
||||
status: 'unsupported',
|
||||
source: 'official',
|
||||
providerMessage: `current local CLIProxyAPI evidence does not expose official quota windows for ${provider} oauth`,
|
||||
providerMessage: `official quota windows are not exposed for ${provider} oauth`,
|
||||
windows: {
|
||||
fiveHour: buildUnsupportedWindow('official 5h quota window is unavailable for this provider'),
|
||||
sevenDay: buildUnsupportedWindow('official 7d quota window is unavailable for this provider'),
|
||||
|
||||
Reference in New Issue
Block a user