mirror of
https://github.com/Twigpine/zero.git
synced 2026-11-08 09:49:34 -10:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c23a661df2 |
No files matched your search
@@ -89,8 +89,8 @@ func RuntimeUnsupportedReason(descriptor Descriptor) string {
|
||||
var descriptors = []Descriptor{
|
||||
// GitLawb OpenGateway — the recommended default. An OpenAI-compatible gateway
|
||||
// that smart-routes by model id across upstream providers (xiaomi-mimo,
|
||||
// minimax, qwen, google, nvidia, z-ai). Flat /v1/chat/completions with a
|
||||
// Bearer ogw_live_… key; listed first and badged in every picker.
|
||||
// minimax, qwen, google, nvidia, tencent, z-ai). Flat /v1/chat/completions
|
||||
// with a Bearer ogw_live_… key; listed first and badged in every picker.
|
||||
recommended(openAICompat("gitlawb-opengateway", "GitLawb OpenGateway", "https://opengateway.gitlawb.com/v1", "mimo-v2.5-pro", []string{"GITLAWB_OPENGATEWAY_API_KEY"}, "gitlawb opengateway", "opengateway")),
|
||||
openAI("openai", "OpenAI", "https://api.openai.com/v1", "gpt-4.1", []string{"OPENAI_API_KEY"}),
|
||||
anthropic("anthropic", "Anthropic", "https://api.anthropic.com", "claude-sonnet-4.5", []string{"ANTHROPIC_API_KEY"}),
|
||||
|
||||
@@ -140,12 +140,13 @@ var curatedModels = map[string][]Model{
|
||||
"zai": zaiCuratedModels,
|
||||
"zai-cn": zaiCuratedModels,
|
||||
// OpenGateway smart-routes by model id across its upstream providers
|
||||
// (see /health: xiaomi-mimo, minimax, qwen, google, nvidia, z-ai). These are
|
||||
// the curated coding defaults; the gateway accepts any model its upstreams
|
||||
// expose, so users can also type an id the picker doesn't list.
|
||||
// (see /health: xiaomi-mimo, minimax, qwen, google, nvidia, tencent, z-ai).
|
||||
// These are the curated coding defaults; the gateway accepts any model its
|
||||
// upstreams expose, so users can also type an id the picker doesn't list.
|
||||
"gitlawb-opengateway": {
|
||||
{ID: "mimo-v2.5-pro", Description: "catalog default (Xiaomi MiMo)"},
|
||||
{ID: "mimo-v2.5-pro-ultraspeed", Description: "fast model (Xiaomi MiMo)"},
|
||||
{ID: "tencent/hy3", Description: "free Tencent HY3 model"},
|
||||
{ID: "MiniMax-M3", Description: "MiniMax model"},
|
||||
{ID: "qwen-plus", Description: "Qwen model"},
|
||||
{ID: "gemini-2.5-pro", Description: "long-context model (Google)"},
|
||||
|
||||
@@ -47,6 +47,11 @@ func TestModelsAreProviderScoped(t *testing.T) {
|
||||
want: []string{"glm-4.5", "glm-4.6", "glm-4.5-air", "glm-z1-air"},
|
||||
notWant: []string{"gpt-4.1", "claude-sonnet-4.5"},
|
||||
},
|
||||
{
|
||||
provider: "gitlawb-opengateway",
|
||||
want: []string{"mimo-v2.5-pro", "tencent/hy3"},
|
||||
notWant: []string{"openai/gpt-4.1", "claude-sonnet-4.5"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
@@ -31,7 +31,7 @@ func LooksLikeCodingModelID(id string) bool {
|
||||
"mistral", "codestral", "devstral", "magistral", "ministral",
|
||||
"grok", "glm", "command", "nemotron", "mixtral", "coder",
|
||||
"code", "chat", "instruct", "reasoner", "reasoning", "mimo",
|
||||
"maverick", "scout", "bankr",
|
||||
"hy3", "tencent", "maverick", "scout", "bankr",
|
||||
} {
|
||||
if strings.Contains(normalized, term) {
|
||||
return true
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
func TestLooksLikeCodingModelID(t *testing.T) {
|
||||
coding := []string{"gpt-4o", "claude-sonnet-4.5", "o1", "o3-mini", "o4-mini", "qwen2.5-coder", "deepseek-chat", "kimi-k2", "codestral-latest", "grok-code"}
|
||||
coding := []string{"gpt-4o", "claude-sonnet-4.5", "o1", "o3-mini", "o4-mini", "qwen2.5-coder", "deepseek-chat", "kimi-k2", "codestral-latest", "grok-code", "tencent/hy3"}
|
||||
for _, id := range coding {
|
||||
if !LooksLikeCodingModelID(id) {
|
||||
t.Errorf("LooksLikeCodingModelID(%q) = false, want true", id)
|
||||
|
||||
@@ -80,6 +80,14 @@ func TestParseOpenGatewayCatalogSupportsRichModelJSON(t *testing.T) {
|
||||
"tags": ["coding", "free"],
|
||||
"cost": {"input": 0, "output": 0}
|
||||
},
|
||||
{
|
||||
"id": "tencent/hy3",
|
||||
"name": "Tencent HY3",
|
||||
"description": "free Tencent chat route",
|
||||
"context_window": 262144,
|
||||
"tools": true,
|
||||
"tags": ["free"]
|
||||
},
|
||||
{
|
||||
"id": "image-route",
|
||||
"name": "Image Route",
|
||||
@@ -92,8 +100,8 @@ func TestParseOpenGatewayCatalogSupportsRichModelJSON(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("ParseOpenGatewayCatalog returned error: %v", err)
|
||||
}
|
||||
if got := strings.Join(modelIDs(models), ","); got != "minimax-m3" {
|
||||
t.Fatalf("models = %#v, want one gateway coding model", got)
|
||||
if got := strings.Join(modelIDs(models), ","); got != "minimax-m3,tencent/hy3" {
|
||||
t.Fatalf("models = %#v, want gateway coding models", got)
|
||||
}
|
||||
model := models[0]
|
||||
if model.ID != "minimax-m3" || model.Description != "agentic coding route" {
|
||||
@@ -108,6 +116,9 @@ func TestParseOpenGatewayCatalogSupportsRichModelJSON(t *testing.T) {
|
||||
if model.Source != "opengateway" {
|
||||
t.Fatalf("gateway source = %q, want opengateway", model.Source)
|
||||
}
|
||||
if models[1].ID != "tencent/hy3" || models[1].ContextWindow != 262144 || !models[1].ToolCall {
|
||||
t.Fatalf("gateway HY3 model = %#v, want Tencent HY3 with context/tools", models[1])
|
||||
}
|
||||
}
|
||||
|
||||
func TestModelsDevProviderIDMapsZeroAliases(t *testing.T) {
|
||||
|
||||
@@ -56,6 +56,56 @@ func TestNewCreatesOpenAIProviderWithFactoryOptions(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewPassesOpenGatewayHY3ModelThrough(t *testing.T) {
|
||||
transport := &captureTransport{
|
||||
responseBody: "data: [DONE]\n\n",
|
||||
}
|
||||
client := &http.Client{Transport: transport}
|
||||
|
||||
provider, err := New(config.ProviderProfile{
|
||||
Name: "opengateway",
|
||||
CatalogID: "gitlawb-opengateway",
|
||||
ProviderKind: config.ProviderKindOpenAICompatible,
|
||||
APIKey: "ogw_live_test",
|
||||
Model: "tencent/hy3",
|
||||
}, Options{HTTPClient: client})
|
||||
if err != nil {
|
||||
t.Fatalf("New() error = %v", err)
|
||||
}
|
||||
stream, err := provider.StreamCompletion(context.Background(), zeroruntime.CompletionRequest{
|
||||
Messages: []zeroruntime.Message{{Role: zeroruntime.MessageRoleUser, Content: "hello"}},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("StreamCompletion() error = %v", err)
|
||||
}
|
||||
for range stream {
|
||||
}
|
||||
|
||||
if transport.request.URL.String() != "https://opengateway.gitlawb.com/v1/chat/completions" {
|
||||
t.Fatalf("request URL = %q, want OpenGateway chat completions", transport.request.URL.String())
|
||||
}
|
||||
var body map[string]any
|
||||
if err := json.NewDecoder(transport.body()).Decode(&body); err != nil {
|
||||
t.Fatalf("decode request body: %v", err)
|
||||
}
|
||||
if body["model"] != "tencent/hy3" {
|
||||
t.Fatalf("model = %q, want tencent/hy3 passthrough", body["model"])
|
||||
}
|
||||
|
||||
metadata, err := ResolveRuntimeMetadata(config.ProviderProfile{
|
||||
Name: "opengateway",
|
||||
CatalogID: "gitlawb-opengateway",
|
||||
ProviderKind: config.ProviderKindOpenAICompatible,
|
||||
Model: "tencent/hy3",
|
||||
}, Options{})
|
||||
if err != nil {
|
||||
t.Fatalf("ResolveRuntimeMetadata() error = %v", err)
|
||||
}
|
||||
if metadata.ProviderKind != config.ProviderKindOpenAICompatible || metadata.APIModel != "tencent/hy3" {
|
||||
t.Fatalf("runtime metadata = %#v, want OpenAI-compatible tencent/hy3", metadata)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewThreadsCustomProviderHeaders(t *testing.T) {
|
||||
transport := &captureTransport{
|
||||
responseBody: "data: [DONE]\n\n",
|
||||
|
||||
Reference in new issue
Block a user