Skip to content

Commit 50542fb

Browse files
fix: give DeepSeek V4 models a 1M last-resort context window (#226)
Flash and v4.1 ids were falling through to the V3 128K default, so trim and the ctx gauge used 131k against a 1M-class model. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent ac68101 commit 50542fb

5 files changed

Lines changed: 29 additions & 7 deletions

File tree

‎cmd/odek/serve_api_test.go‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,25 @@ func TestHandleModelList_ReturnsOnlyConfiguredModel(t *testing.T) {
457457
if models[0]["description"] == "" {
458458
t.Error("description should be non-empty for a known model")
459459
}
460+
if ctx, ok := models[0]["max_context"].(float64); !ok || ctx != 1_000_000 {
461+
t.Errorf("max_context = %v, want 1000000 (deepseek-v4 1M window)", models[0]["max_context"])
462+
}
463+
}
464+
465+
func TestHandleModelList_DeepSeekV41UsesV4Window(t *testing.T) {
466+
handler := handleModelList("deepseek-v4.1-flash-expires-on-0910", nil)
467+
w := httptest.NewRecorder()
468+
handler(w, httptest.NewRequest(http.MethodGet, "/api/models", nil))
469+
var models []modelEntry
470+
if err := json.NewDecoder(w.Body).Decode(&models); err != nil {
471+
t.Fatal(err)
472+
}
473+
if len(models) != 1 {
474+
t.Fatalf("len = %d, want 1", len(models))
475+
}
476+
if models[0].MaxContext != 1_000_000 {
477+
t.Errorf("v4.1 last-resort ctx = %d, want 1000000", models[0].MaxContext)
478+
}
460479
}
461480

462481
func TestHandleModelList_EmptyConfigModel_ReturnsEmptyList(t *testing.T) {

‎docs/MIGRATION.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ DeepSeek-only leftover: when `provider` is `deepseek`, `ODEK_API_KEY` → `DEEPS
6767

6868
- Thinking: set `--thinking medium` (or `low`/`high`/`disabled`; `enabled` still works as an alias for `medium`).
6969
- Timeout: default **300s** for every model. Raise with `llm.request_timeout_seconds`.
70-
- Context window: `llm.context_window` → `ListModels` → last-resort table for shipped ids (`deepseek-v4-flash` 128K, `deepseek-v4-pro` 1M, GLM/Kimi/OpenAI prefixes) → else 0 (no trim).
70+
- Context window: `llm.context_window` → last-resort table for shipped ids (`deepseek-v4*` 1M, `deepseek-` 128K, GLM/Kimi/OpenAI prefixes) → `ListModels` → else 0 (no trim).
7171

7272
`ProfileLabel` now returns the model id.
7373

‎docs/PROVIDERS.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ window. **No auto-thinking and no auto-timeout.**
7171

7272
| Prefix | Tokens |
7373
|---|---|
74-
| `deepseek-v4-pro` | 1M |
75-
| `deepseek-v4-flash` / `deepseek-` | 128K |
74+
| `deepseek-v4` (pro, flash, v4.1-*) | 1M |
75+
| `deepseek-` (v3 chat / reasoner) | 128K |
7676
| `glm-5.3` / `glm-5.2` | 1M |
7777
| `glm-5-turbo` | 200K |
7878
| `glm-` | 128K |

‎internal/llmclient/client.go‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -647,9 +647,8 @@ func LastResortContext(model string) int {
647647
{"kimi-", 262_144},
648648
{"k3-256k", 262_144},
649649
{"k3", 1_000_000},
650-
{"deepseek-v4-pro", 1_000_000},
651-
{"deepseek-v4-flash", 131_072},
652-
{"deepseek-", 131_072},
650+
{"deepseek-v4", 1_000_000}, // pro, flash, v4.1-* (official 1M window)
651+
{"deepseek-", 131_072}, // v3 chat / reasoner
653652
// OpenAI — api.openai.com ListModels omits context_length.
654653
{"gpt-6", 1_050_000},
655654
{"gpt-5.6", 1_050_000},

‎internal/llmclient/client_test.go‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,12 @@ func TestLastResortContext(t *testing.T) {
7878
model string
7979
want int
8080
}{
81-
{"deepseek-v4-flash", 131_072},
81+
{"deepseek-v4-flash", 1_000_000},
8282
{"deepseek-v4-pro", 1_000_000},
83+
{"deepseek-v4.1", 1_000_000},
84+
{"deepseek-v4.1-flash-expires-on-0910", 1_000_000},
85+
{"deepseek-chat", 131_072},
86+
{"deepseek-reasoner", 131_072},
8387
{"gpt-6-astra", 1_050_000},
8488
{"gpt-6", 1_050_000},
8589
{"gpt-5.6-luna", 1_050_000},

0 commit comments

Comments
 (0)