feat: Add Gemini adapter, improve API key fallback for Gemini AI Studio compatibility, and enhance OpenAI tool call streaming.

This commit is contained in:
CJACK
2026-02-22 01:26:08 +08:00
parent 7a4e994f3a
commit 920767f486
16 changed files with 1041 additions and 21 deletions

View File

@@ -187,7 +187,12 @@ func extractCallerToken(req *http.Request) string {
return token
}
}
return strings.TrimSpace(req.Header.Get("x-api-key"))
if key := strings.TrimSpace(req.Header.Get("x-api-key")); key != "" {
return key
}
// Gemini AI Studio compatibility: allow query key fallback only when no
// header-based credential is present.
return strings.TrimSpace(req.URL.Query().Get("key"))
}
func callerTokenID(token string) string {

View File

@@ -114,6 +114,40 @@ func TestDetermineMissingToken(t *testing.T) {
}
}
func TestDetermineWithQueryKeyUsesDirectToken(t *testing.T) {
r := newTestResolver(t)
req, _ := http.NewRequest(http.MethodPost, "/v1beta/models/gemini-2.5-pro:generateContent?key=direct-query-key", nil)
a, err := r.Determine(req)
if err != nil {
t.Fatalf("determine failed: %v", err)
}
if a.UseConfigToken {
t.Fatalf("expected direct token mode")
}
if a.DeepSeekToken != "direct-query-key" {
t.Fatalf("unexpected token: %q", a.DeepSeekToken)
}
}
func TestDetermineHeaderTokenPrecedenceOverQueryKey(t *testing.T) {
r := newTestResolver(t)
req, _ := http.NewRequest(http.MethodPost, "/v1beta/models/gemini-2.5-pro:generateContent?key=query-key", nil)
req.Header.Set("x-api-key", "managed-key")
a, err := r.Determine(req)
if err != nil {
t.Fatalf("determine failed: %v", err)
}
defer r.Release(a)
if !a.UseConfigToken {
t.Fatalf("expected managed key mode from header token")
}
if a.AccountID == "" {
t.Fatalf("expected managed account to be acquired")
}
}
func TestDetermineCallerMissingToken(t *testing.T) {
r := newTestResolver(t)
req, _ := http.NewRequest(http.MethodGet, "/v1/responses/resp_1", nil)