diff --git a/internal/api/modules/amp/proxy.go b/internal/api/modules/amp/proxy.go index 211f0f5d..c593c1b3 100644 --- a/internal/api/modules/amp/proxy.go +++ b/internal/api/modules/amp/proxy.go @@ -215,7 +215,7 @@ func createReverseProxy(upstreamURL string, secretSource SecretSource) (*httputi // Don't log as error for context canceled - it's usually client closing connection if errors.Is(err, context.Canceled) { - log.Debugf("amp upstream proxy [%s]: client canceled request for %s %s", errType, req.Method, req.URL.Path) + return } else { log.Errorf("amp upstream proxy error [%s] for %s %s: %v", errType, req.Method, req.URL.Path, err) } diff --git a/internal/api/modules/amp/proxy_test.go b/internal/api/modules/amp/proxy_test.go index ff23e398..32f5d860 100644 --- a/internal/api/modules/amp/proxy_test.go +++ b/internal/api/modules/amp/proxy_test.go @@ -493,6 +493,30 @@ func TestReverseProxy_ErrorHandler(t *testing.T) { } } +func TestReverseProxy_ErrorHandler_ContextCanceled(t *testing.T) { + // Test that context.Canceled errors return 499 without generic error response + proxy, err := createReverseProxy("http://example.com", NewStaticSecretSource("")) + if err != nil { + t.Fatal(err) + } + + // Create a canceled context to trigger the cancellation path + ctx, cancel := context.WithCancel(context.Background()) + cancel() // Cancel immediately + + req := httptest.NewRequest(http.MethodGet, "/test", nil).WithContext(ctx) + rr := httptest.NewRecorder() + + // Directly invoke the ErrorHandler with context.Canceled + proxy.ErrorHandler(rr, req, context.Canceled) + + // Body should be empty for canceled requests (no JSON error response) + body := rr.Body.Bytes() + if len(body) > 0 { + t.Fatalf("expected empty body for canceled context, got: %s", body) + } +} + func TestReverseProxy_FullRoundTrip_Gzip(t *testing.T) { // Upstream returns gzipped JSON without Content-Encoding header upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/internal/registry/model_definitions_static_data.go b/internal/registry/model_definitions_static_data.go index 99b83781..18a1a3a1 100644 --- a/internal/registry/model_definitions_static_data.go +++ b/internal/registry/model_definitions_static_data.go @@ -975,6 +975,7 @@ func GetAntigravityModelConfig() map[string]*AntigravityModelConfig { "gemini-2.5-flash-lite": {Thinking: &ThinkingSupport{Min: 0, Max: 24576, ZeroAllowed: true, DynamicAllowed: true}}, "gemini-3-pro-high": {Thinking: &ThinkingSupport{Min: 128, Max: 32768, ZeroAllowed: false, DynamicAllowed: true, Levels: []string{"low", "high"}}}, "gemini-3-pro-image": {Thinking: &ThinkingSupport{Min: 128, Max: 32768, ZeroAllowed: false, DynamicAllowed: true, Levels: []string{"low", "high"}}}, + "gemini-3.1-pro-high": {Thinking: &ThinkingSupport{Min: 128, Max: 32768, ZeroAllowed: false, DynamicAllowed: true, Levels: []string{"low", "high"}}}, "gemini-3-flash": {Thinking: &ThinkingSupport{Min: 128, Max: 32768, ZeroAllowed: false, DynamicAllowed: true, Levels: []string{"minimal", "low", "medium", "high"}}}, "claude-opus-4-5-thinking": {Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: true}, MaxCompletionTokens: 64000}, "claude-opus-4-6-thinking": {Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: true}, MaxCompletionTokens: 64000},