返回 DeepSeek-Reasonix
web_search.go
根目录 / internal / config / web_search.go
1 package config
2
3 import (
4 "net/url"
5 "strings"
6 )
7
8 // SupportsServerWebSearch reports whether the provider kind has a wire format
9 // for a provider-executed web search tool. OpenAI Chat Completions is excluded:
10 // DeepSeek's documented chat-completions tool contract only supports functions.
11 func SupportsServerWebSearch(e *ProviderEntry) bool {
12 if e == nil {
13 return false
14 }
15 switch strings.ToLower(strings.TrimSpace(e.Kind)) {
16 case "anthropic", "responses":
17 return true
18 default:
19 return false
20 }
21 }
22
23 // IsOfficialDeepSeekWebSearchEndpoint matches the exact protocol base URLs
24 // documented by DeepSeek. Host-only matching is intentionally insufficient:
25 // Anthropic requires the /anthropic prefix, while Responses uses the origin.
26 func IsOfficialDeepSeekWebSearchEndpoint(e *ProviderEntry) bool {
27 if !SupportsServerWebSearch(e) {
28 return false
29 }
30 u, err := url.Parse(strings.TrimSpace(e.BaseURL))
31 if err != nil || !strings.EqualFold(u.Scheme, "https") || !strings.EqualFold(u.Hostname(), "api.deepseek.com") ||
32 u.Port() != "" || u.User != nil || u.RawQuery != "" || u.Fragment != "" {
33 return false
34 }
35 path := strings.TrimRight(u.EscapedPath(), "/")
36 switch strings.ToLower(strings.TrimSpace(e.Kind)) {
37 case "responses":
38 return path == ""
39 case "anthropic":
40 return path == "/anthropic"
41 default:
42 return false
43 }
44 }
45
46 // EffectiveWebSearch resolves the persisted tri-state. Official DeepSeek
47 // Anthropic and Responses endpoints default on when old configuration omitted
48 // web_search, while compatible third-party endpoints remain opt-in. An explicit
49 // false always wins so users can turn the capability off permanently.
50 func EffectiveWebSearch(e *ProviderEntry) bool {
51 if !SupportsServerWebSearch(e) {
52 return false
53 }
54 if e.WebSearch != nil {
55 return *e.WebSearch
56 }
57 return IsOfficialDeepSeekWebSearchEndpoint(e)
58 }
59
59 lines GO