Files
magpie/internal/provider/test_protocol_headers_test.go
yetone e20e1e9eea provider, gui: Detect asks a Gemini API too, at the URL's …/v1beta, with the key in x-goog-api-key and a gemini model from the list, and the editor shows Detect on a Gemini pick (#1346, NagaseMinato: 「检测」不会探测 Gemini 端点,为什么呢?)
Detect asked OpenAI chat, Responses and Anthropic only, and the editor hid
Detect when Gemini was picked. Now detectProtocols adds Gemini:
- a typed …/v1 or a bare host is asked at …/v1beta; a …/v1beta base is
  kept; a pasted …/models/x:generateContent URL is cut back to its base
  (for every API, so the others aren't asked under ":generateContent");
- the provider's own Gemini URL is asked as it is;
- the probe is the same tinyBody a Gemini test sends, x-goog-api-key, no
  Authorization; a model id with "gemini" in it is preferred.
Nothing is saved; "Use these" keeps the Gemini pick and its URL.

Run: go test -tags nogui ./... (all ok), go vet and GOOS=linux/windows
go vet on ./internal/provider ./internal/gui. GUI, Chromium and WebKit:
provider-gemini 8/8 (900px and 440px, en/zh/ja/de labels), provider-detect,
provider-detect-models, provider-base-api, provider-url-each-api,
provider-add-models, gui-ja, gui-de, gui-zh-tw, click-scroll.
Without the fix TestDetectGemini fails ("no model to try") and
provider-gemini fails 4 of 4 in Chromium.
Real: aihubmix (owner's key, sandbox HOME) at https://aihubmix.com/gemini/v1beta
with gemini-2.5-flash: Gemini ok 200; at https://aihubmix.com/v1 chat,
responses and anthropic ok and Gemini 400 (aihubmix serves Gemini under
/gemini). Not tried with a real Google AI Studio key.
2026-10-09 02:20:30 +08:00

79 lines
2.4 KiB
Go

package provider
import (
"context"
"net/http"
"net/http/httptest"
"testing"
)
// Agent Space refuses Responses probes with anthropic-version, while
// Anthropic endpoints require it. Every probe entry point follows that rule.
func TestProviderProbesUseProtocolHeaders(t *testing.T) {
for _, entry := range []string{"endpoints", "models", "detect", "detect-models"} {
t.Run(entry, func(t *testing.T) {
detectHome(t)
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodGet {
_, _ = w.Write([]byte(`{"data":[{"id":"gpt-6-sol"},{"id":"claude-opus-5"}]}`))
return
}
_, version := r.Header["Anthropic-Version"]
if r.URL.Path == "/v1/messages" {
if r.Header.Get("anthropic-version") != "2023-06-01" {
http.Error(w, `{"error":{"message":"anthropic-version is required"}}`, http.StatusBadRequest)
return
}
} else if version {
http.Error(w, `{"error":{"message":"The request headers are invalid.","type":"invalid_request_error","param":null,"code":"invalid_headers"}}`, http.StatusBadRequest)
return
}
_, _ = w.Write([]byte(`{}`))
}))
defer srv.Close()
p := Provider{ID: "relay", Key: "sk-test", Chat: srv.URL + "/v1",
Responses: srv.URL + "/v1", Anthropic: srv.URL,
Models: []string{"gpt-6-sol", "claude-opus-5"}}
ctx := context.Background()
var results []Result
want := 3
switch entry {
case "endpoints":
results = p.Test(ctx)
case "models":
p.Chat, p.Anthropic = "", ""
results = p.TestModels(ctx, []string{"gpt-6-sol"})
want = 1
case "detect":
want = len(detectProtocols) // Gemini's too, without anthropic-version
detected, err := p.Detect(ctx, srv.URL, "gpt-6-sol")
if err != nil {
t.Fatal(err)
}
for _, d := range detected {
results = append(results, d.Result)
}
case "detect-models":
want = len(detectProtocols)
models, _, err := p.DetectModels(ctx, srv.URL, []string{"gpt-6-sol"})
if err != nil {
t.Fatal(err)
}
for _, m := range models {
for _, d := range m.Results {
results = append(results, d.Result)
}
}
}
if len(results) != want {
t.Fatalf("got %d probe results, want %d: %+v", len(results), want, results)
}
for _, r := range results {
if !r.OK || r.Status != http.StatusOK {
t.Errorf("%s probe failed: %+v", r.Protocol, r)
}
}
})
}
}