Skip to content

fix(translator/antigravity): support max_completion_tokens in openai chat completions - #192

Open
warelik wants to merge 2 commits into
kaitranntt:mainfrom
warelik:fix/antigravity-max-completion-tokens
Open

fix(translator/antigravity): support max_completion_tokens in openai chat completions#192
warelik wants to merge 2 commits into
kaitranntt:mainfrom
warelik:fix/antigravity-max-completion-tokens

Conversation

@warelik

@warelik warelik commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Problem

OpenAI deprecated max_tokens in favor of max_completion_tokens for reasoning models (o1, o3-mini, newer gpt-4o versions), and modern OpenAI client libraries send max_completion_tokens by default.

When translating OpenAI Chat Completions requests to Antigravity (ConvertOpenAIRequestToAntigravity), only max_tokens was inspected. When a client supplied max_completion_tokens without max_tokens, request.generationConfig.maxOutputTokens was omitted from the upstream Antigravity payload, causing upstream models to ignore client token limits.

Fix

  • internal/translator/antigravity/openai/chat-completions/antigravity_openai_request.go:72: Updated ConvertOpenAIRequestToAntigravity to read max_tokens first, and if absent/non-numeric, fall back to max_completion_tokens (matching the mapping pattern used in gemini_openai_request.go).

Tests

  • TestConvertOpenAIRequestToAntigravityMapsMaxTokens:
    • only max_tokens: Verifies max_tokens sets maxOutputTokens.
    • only max_completion_tokens: Verifies max_completion_tokens sets maxOutputTokens.
    • max_tokens preferred over max_completion_tokens: Verifies max_tokens precedence when both are provided.
    • neither present: Verifies maxOutputTokens is omitted.
    • non-numeric max_tokens ignored: Verifies string max_tokens is ignored.
    • non-numeric max_completion_tokens ignored: Verifies string max_completion_tokens is ignored.

Reverse bite-check

Reverting internal/translator/antigravity/openai/chat-completions/antigravity_openai_request.go to the pre-fix state reproduces the failure where max_completion_tokens is ignored:

=== RUN   TestConvertOpenAIRequestToAntigravityMapsMaxTokens
=== RUN   TestConvertOpenAIRequestToAntigravityMapsMaxTokens/only_max_tokens
=== RUN   TestConvertOpenAIRequestToAntigravityMapsMaxTokens/only_max_completion_tokens
    antigravity_openai_request_test.go:513: expected maxOutputTokens to be set, but it was missing. Output: {"project":"","request":{"contents":[{"role":"user","parts":[{"text":"hi"}]}],"safetySettings":[{"category":"HARM_CATEGORY_HARASSMENT","threshold":"OFF"},{"category":"HARM_CATEGORY_HATE_SPEECH","threshold":"OFF"},{"category":"HARM_CATEGORY_SEXUALLY_EXPLICIT","threshold":"OFF"},{"category":"HARM_CATEGORY_DANGEROUS_CONTENT","threshold":"OFF"},{"category":"HARM_CATEGORY_CIVIC_INTEGRITY","threshold":"BLOCK_NONE"}]},"model":"gemini-2.5-pro"}
=== RUN   TestConvertOpenAIRequestToAntigravityMapsMaxTokens/max_tokens_preferred_over_max_completion_tokens
=== RUN   TestConvertOpenAIRequestToAntigravityMapsMaxTokens/neither_present
=== RUN   TestConvertOpenAIRequestToAntigravityMapsMaxTokens/non-numeric_max_tokens_ignored
=== RUN   TestConvertOpenAIRequestToAntigravityMapsMaxTokens/non-numeric_max_completion_tokens_ignored
--- FAIL: TestConvertOpenAIRequestToAntigravityMapsMaxTokens (0.00s)
    --- PASS: TestConvertOpenAIRequestToAntigravityMapsMaxTokens/only_max_tokens (0.00s)
    --- FAIL: TestConvertOpenAIRequestToAntigravityMapsMaxTokens/only_max_completion_tokens (0.00s)
    --- PASS: TestConvertOpenAIRequestToAntigravityMapsMaxTokens/max_tokens_preferred_over_max_completion_tokens (0.00s)
    --- PASS: TestConvertOpenAIRequestToAntigravityMapsMaxTokens/neither_present (0.00s)
    --- PASS: TestConvertOpenAIRequestToAntigravityMapsMaxTokens/non-numeric_max_tokens_ignored (0.00s)
    --- PASS: TestConvertOpenAIRequestToAntigravityMapsMaxTokens/non-numeric_max_completion_tokens_ignored (0.00s)
FAIL
FAIL	github.com/router-for-me/CLIProxyAPI/v7/internal/translator/antigravity/openai/chat-completions	0.407s
FAIL

Verification

TMPDIR=/Users/warelik/.cache/gotmp GOCACHE=/Users/warelik/.cache/gocache go build ./...
TMPDIR=/Users/warelik/.cache/gotmp GOCACHE=/Users/warelik/.cache/gocache go vet ./internal/translator/antigravity/openai/chat-completions/...
gofmt -l internal/translator/antigravity/openai/chat-completions/antigravity_openai_request.go internal/translator/antigravity/openai/chat-completions/antigravity_openai_request_test.go
TMPDIR=/Users/warelik/.cache/gotmp GOCACHE=/Users/warelik/.cache/gocache go test -v -run "TestConvertOpenAIRequestToAntigravityMapsMaxTokens" ./internal/translator/antigravity/openai/chat-completions/...

Output:

=== RUN   TestConvertOpenAIRequestToAntigravityMapsMaxTokens
=== RUN   TestConvertOpenAIRequestToAntigravityMapsMaxTokens/only_max_tokens
=== RUN   TestConvertOpenAIRequestToAntigravityMapsMaxTokens/only_max_completion_tokens
=== RUN   TestConvertOpenAIRequestToAntigravityMapsMaxTokens/max_tokens_preferred_over_max_completion_tokens
=== RUN   TestConvertOpenAIRequestToAntigravityMapsMaxTokens/neither_present
=== RUN   TestConvertOpenAIRequestToAntigravityMapsMaxTokens/non-numeric_max_tokens_ignored
=== RUN   TestConvertOpenAIRequestToAntigravityMapsMaxTokens/non-numeric_max_completion_tokens_ignored
--- PASS: TestConvertOpenAIRequestToAntigravityMapsMaxTokens (0.00s)
    --- PASS: TestConvertOpenAIRequestToAntigravityMapsMaxTokens/only_max_tokens (0.00s)
    --- PASS: TestConvertOpenAIRequestToAntigravityMapsMaxTokens/only_max_completion_tokens (0.00s)
    --- PASS: TestConvertOpenAIRequestToAntigravityMapsMaxTokens/max_tokens_preferred_over_max_completion_tokens (0.00s)
    --- PASS: TestConvertOpenAIRequestToAntigravityMapsMaxTokens/neither_present (0.00s)
    --- PASS: TestConvertOpenAIRequestToAntigravityMapsMaxTokens/non-numeric_max_tokens_ignored (0.00s)
    --- PASS: TestConvertOpenAIRequestToAntigravityMapsMaxTokens/non-numeric_max_completion_tokens_ignored (0.00s)
PASS
ok  	github.com/router-for-me/CLIProxyAPI/v7/internal/translator/antigravity/openai/chat-completions	0.384s

Tooling note

The jbcontext semantic-search CLI is installed but non-functional in this environment
(jbcontext search fails with the OS keychain is not accessible). The equivalent
review passes were performed with the repository's own tooling and manual inspection
instead; this is disclosed for transparency about how the change was reviewed.

…chat completions

OpenAI reasoning models send max_completion_tokens instead of max_tokens.

Map max_completion_tokens to request.generationConfig.maxOutputTokens when max_tokens is absent, preserving priority.

Refs: router-for-me/CLIProxyAPI#5108
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