support deepseek 1M

This commit is contained in:
Rene 2026-05-23 23:06:07 +08:00
parent ce6eef602e
commit 23ebb2b09f
2 changed files with 57 additions and 6 deletions

View file

@ -184,7 +184,22 @@ func listCmd() *cobra.Command {
} }
func knownModelIDs() []string { func knownModelIDs() []string {
return []string{"glm-5.1", "glm-5", "kimi-k2.6", "kimi-k2.5", "mimo-v2.5-pro", "mimo-v2.5", "mimo-v2-pro", "mimo-v2-omni", "minimax-m2.7", "minimax-m2.5", "deepseek-v4-pro", "deepseek-v4-flash", "qwen3.6-plus", "qwen3.5-plus"} return []string{"glm-5.1", "glm-5", "kimi-k2.6", "kimi-k2.5", "mimo-v2.5-pro", "mimo-v2.5", "mimo-v2-pro", "mimo-v2-omni", "minimax-m2.7", "minimax-m2.5", "deepseek-v4-pro[1M]", "deepseek-v4-flash[1M]", "qwen3.6-plus", "qwen3.5-plus"}
}
func cleanModelName(model string) string {
model = strings.TrimSuffix(model, "[1M]")
model = strings.TrimSuffix(model, "[128K]")
return model
}
func modelContextWindow(model string) int {
switch cleanModelName(model) {
case "deepseek-v4-pro", "deepseek-v4-flash":
return 1000000
default:
return 128000
}
} }
func modelSupportsImages(model string) bool { func modelSupportsImages(model string) bool {
@ -489,6 +504,11 @@ func prepareChatBody(body []byte) ([]byte, error) {
} }
changed := requestStreamingUsage(req) changed := requestStreamingUsage(req)
model, _ := req["model"].(string) model, _ := req["model"].(string)
if clean := cleanModelName(model); clean != model {
req["model"] = clean
changed = true
model = clean
}
if rawChatBodyHasImages(req) { if rawChatBodyHasImages(req) {
if !modelSupportsImages(model) { if !modelSupportsImages(model) {
return nil, unsupportedImageModelError(model) return nil, unsupportedImageModelError(model)
@ -582,7 +602,7 @@ func stripRawChatImageDetails(req map[string]any) bool {
} }
func convertRequest(ar AnthropicRequest) OAIRequest { func convertRequest(ar AnthropicRequest) OAIRequest {
model := ar.Model model := cleanModelName(ar.Model)
if model == "" || strings.HasPrefix(model, "claude-") { if model == "" || strings.HasPrefix(model, "claude-") {
model = "kimi-k2.6" model = "kimi-k2.6"
} }
@ -600,7 +620,7 @@ func convertRequest(ar AnthropicRequest) OAIRequest {
} }
func responsesToChat(rr ResponsesRequest) OAIRequest { func responsesToChat(rr ResponsesRequest) OAIRequest {
model := rr.Model model := cleanModelName(rr.Model)
if model == "" { if model == "" {
model = "kimi-k2.6" model = "kimi-k2.6"
} }
@ -1522,6 +1542,7 @@ func writeCodexProfile(path, baseURL string) error {
func writeCodexModelCatalog(path string) error { func writeCodexModelCatalog(path string) error {
models := make([]map[string]any, 0, len(knownModelIDs())) models := make([]map[string]any, 0, len(knownModelIDs()))
for i, id := range knownModelIDs() { for i, id := range knownModelIDs() {
cw := modelContextWindow(id)
models = append(models, map[string]any{ models = append(models, map[string]any{
"slug": id, "slug": id,
"display_name": id, "display_name": id,
@ -1544,8 +1565,8 @@ func writeCodexModelCatalog(path string) error {
"truncation_policy": map[string]any{"mode": "tokens", "limit": 10000}, "truncation_policy": map[string]any{"mode": "tokens", "limit": 10000},
"supports_parallel_tool_calls": false, "supports_parallel_tool_calls": false,
"supports_image_detail_original": false, "supports_image_detail_original": false,
"context_window": 128000, "context_window": cw,
"max_context_window": 128000, "max_context_window": cw,
"auto_compact_token_limit": nil, "auto_compact_token_limit": nil,
"effective_context_window_percent": 95, "effective_context_window_percent": 95,
"experimental_supported_tools": []any{}, "experimental_supported_tools": []any{},

View file

@ -60,6 +60,36 @@ func TestWriteCodexProfileReplacesExistingSections(t *testing.T) {
} }
} }
func TestModelContextWindow(t *testing.T) {
if got := modelContextWindow("deepseek-v4-flash[1M]"); got != 1000000 {
t.Fatalf("deepseek-v4-flash[1M]: got %d, want 1000000", got)
}
if got := modelContextWindow("deepseek-v4-pro[1M]"); got != 1000000 {
t.Fatalf("deepseek-v4-pro[1M]: got %d, want 1000000", got)
}
if got := modelContextWindow("kimi-k2.6"); got != 128000 {
t.Fatalf("kimi-k2.6: got %d, want 128000", got)
}
if got := modelContextWindow("unknown-model"); got != 128000 {
t.Fatalf("unknown-model: got %d, want 128000", got)
}
}
func TestCleanModelName(t *testing.T) {
tests := []struct{ in, want string }{
{"deepseek-v4-flash[1M]", "deepseek-v4-flash"},
{"deepseek-v4-pro[1M]", "deepseek-v4-pro"},
{"deepseek-v4-flash", "deepseek-v4-flash"},
{"kimi-k2.6", "kimi-k2.6"},
{"kimi-k2.6[128K]", "kimi-k2.6"},
}
for _, tt := range tests {
if got := cleanModelName(tt.in); got != tt.want {
t.Errorf("cleanModelName(%q) = %q, want %q", tt.in, got, tt.want)
}
}
}
func TestWriteCodexModelCatalog(t *testing.T) { func TestWriteCodexModelCatalog(t *testing.T) {
path := filepath.Join(t.TempDir(), "ocgo-models.json") path := filepath.Join(t.TempDir(), "ocgo-models.json")
if err := writeCodexModelCatalog(path); err != nil { if err := writeCodexModelCatalog(path); err != nil {
@ -70,7 +100,7 @@ func TestWriteCodexModelCatalog(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
content := string(b) content := string(b)
for _, want := range []string{`"models"`, `"slug": "deepseek-v4-pro"`, `"context_window": 128000`, `"truncation_policy"`, `"supports_image_detail_original": false`, `"image"`} { for _, want := range []string{`"models"`, `"slug": "deepseek-v4-pro[1M]"`, `"context_window": 1000000`, `"truncation_policy"`, `"supports_image_detail_original": false`, `"image"`} {
if !strings.Contains(content, want) { if !strings.Contains(content, want) {
t.Fatalf("missing %q in:\n%s", want, content) t.Fatalf("missing %q in:\n%s", want, content)
} }