Update DeepSeek Patrol defaults

This commit is contained in:
rcourtman 2026-05-08 01:24:50 +01:00
parent f0105e586e
commit f8047177ef
10 changed files with 43 additions and 10 deletions

View file

@ -470,7 +470,12 @@ provider catalog, or a provider returns no usable models, the effective BYOK
selection may fall back only to the provider-owned default declared in
`internal/config/ai.go`. Runtime startup, connection-test, and load-config
paths may not return an empty effective model or borrow another provider's
selection just because live model discovery was unavailable.
selection just because live model discovery was unavailable. DeepSeek's
provider-owned fallback must track the current V4 API contract and use
`deepseek-v4-flash` rather than retired compatibility aliases such as
`deepseek-chat` or `deepseek-reasoner`; AI runtime context-window and cost
budgeting must likewise know the V4 Flash/Pro 1M context and distinct pricing
classes before Patrol treats those models as ready.
Retired quickstart ownership is now an inert compatibility boundary, not a
self-hosted GA runtime path. The old quickstart provider, bootstrap manager,
and local token-cache persistence API are removed from the Pulse runtime;

View file

@ -29,7 +29,7 @@ type modelPrice struct {
OutputUSDPerMTok float64
}
const pricingAsOf = "2025-12"
const pricingAsOf = "2026-04"
// PricingAsOf indicates the effective date of the pricing table used for estimation.
func PricingAsOf() string {
@ -49,8 +49,10 @@ var providerPrices = map[string][]modelPrice{
{Pattern: "claude-haiku*", InputUSDPerMTok: 0.25, OutputUSDPerMTok: 1.25},
},
"deepseek": {
// DeepSeek docs include an "input cache hit" discount; this uses cache-miss rates for conservative estimates.
{Pattern: "deepseek-*", InputUSDPerMTok: 0.28, OutputUSDPerMTok: 0.42},
// DeepSeek docs include an input cache-hit discount; this uses cache-miss rates for conservative estimates.
{Pattern: "deepseek-v4-flash*", InputUSDPerMTok: 0.14, OutputUSDPerMTok: 0.28},
{Pattern: "deepseek-v4-pro*", InputUSDPerMTok: 0.435, OutputUSDPerMTok: 0.87},
{Pattern: "deepseek-*", InputUSDPerMTok: 0.14, OutputUSDPerMTok: 0.28},
},
"gemini": {
// Gemini pricing (as of December 2025)

View file

@ -183,6 +183,8 @@ func TestEstimateUSD_DeepSeekModels(t *testing.T) {
{"deepseek-chat", true},
{"deepseek-coder", true},
{"deepseek-reasoner", true},
{"deepseek-v4-flash", true},
{"deepseek-v4-pro", true},
{"unknown-deepseek", false},
}

View file

@ -193,7 +193,16 @@ func TestEstimateUSDKnownAndUnknownModels(t *testing.T) {
if !ok {
t.Fatalf("expected deepseek pricing to be known for deepseek-reasoner")
}
expected = 0.70 // 1M input * $0.28 + 1M output * $0.42
expected = 0.42 // 1M input * $0.14 + 1M output * $0.28
if math.Abs(usd-expected) > 0.0001 {
t.Fatalf("expected usd %.4f, got %.4f", expected, usd)
}
usd, ok, _ = EstimateUSD("deepseek", "deepseek-v4-pro", 1_000_000, 1_000_000)
if !ok {
t.Fatalf("expected deepseek pricing to be known for deepseek-v4-pro")
}
expected = 1.305 // 1M input * $0.435 + 1M output * $0.87
if math.Abs(usd-expected) > 0.0001 {
t.Fatalf("expected usd %.4f, got %.4f", expected, usd)
}

View file

@ -81,6 +81,16 @@ func TestEvaluatePatrolConfigReadiness_AssignsStableCause(t *testing.T) {
cfg.PatrolModel = "deepseek:deepseek-v4-flash"
},
},
{
name: "deepseek v4 pro ready",
wantCause: PatrolFailureCauseNone,
wantReady: true,
configure: func(cfg *config.AIConfig) {
cfg.Enabled = true
cfg.DeepSeekAPIKey = "sk-test"
cfg.PatrolModel = "deepseek:deepseek-v4-pro"
},
},
{
name: "ready",
wantCause: PatrolFailureCauseNone,

View file

@ -35,8 +35,10 @@ var modelContextWindows = map[string]int{
"gemini-1.5-flash": 1_048_576,
// DeepSeek
"deepseek-chat": 128_000,
"deepseek-reasoner": 128_000,
"deepseek-v4-flash": 1_000_000,
"deepseek-v4-pro": 1_000_000,
"deepseek-chat": 1_000_000,
"deepseek-reasoner": 1_000_000,
// MiniMax
"MiniMax-Text-01": 1_000_000,

View file

@ -10,6 +10,9 @@ func TestContextWindowTokens_ExactMatch(t *testing.T) {
{model: "claude-opus-4", want: 200_000},
{model: "gpt-4", want: 8_192},
{model: "gemini-1.5-pro", want: 2_097_152},
{model: "deepseek-v4-flash", want: 1_000_000},
{model: "deepseek-v4-pro", want: 1_000_000},
{model: "deepseek-chat", want: 1_000_000},
}
for _, tc := range testCases {

View file

@ -353,7 +353,7 @@ func DefaultModelForProvider(provider string) string {
case AIProviderOpenRouter:
return FormatModelString(AIProviderOpenRouter, "openai/gpt-4o-mini")
case AIProviderDeepSeek:
return FormatModelString(AIProviderDeepSeek, "deepseek-chat")
return FormatModelString(AIProviderDeepSeek, "deepseek-v4-flash")
case AIProviderGemini:
return FormatModelString(AIProviderGemini, "gemini-1.5-pro")
case AIProviderOllama:

View file

@ -162,7 +162,7 @@ func TestDefaultModelForProvider(t *testing.T) {
{
name: "deepseek",
provider: AIProviderDeepSeek,
want: FormatModelString(AIProviderDeepSeek, "deepseek-chat"),
want: FormatModelString(AIProviderDeepSeek, "deepseek-v4-flash"),
},
{
name: "gemini",

View file

@ -234,7 +234,7 @@ func TestDefaultModelForProvider_UsesCanonicalProviderFallbacks(t *testing.T) {
{provider: AIProviderAnthropic, expected: "anthropic:claude-3-5-sonnet-latest"},
{provider: AIProviderOpenAI, expected: "openai:gpt-4o"},
{provider: AIProviderOpenRouter, expected: "openrouter:openai/gpt-4o-mini"},
{provider: AIProviderDeepSeek, expected: "deepseek:deepseek-chat"},
{provider: AIProviderDeepSeek, expected: "deepseek:deepseek-v4-flash"},
{provider: AIProviderGemini, expected: "gemini:gemini-1.5-pro"},
{provider: AIProviderOllama, expected: "ollama:llama3.2"},
{provider: AIProviderQuickstart, expected: ""},