返回 DeepSeek-Reasonix
reasoning_snapshot.go
根目录 / internal / config / reasoning_snapshot.go
1 package config
2
3 import (
4 "crypto/sha256"
5 "encoding/hex"
6 "encoding/json"
7 "maps"
8 "strings"
9 )
10
11 func reasoningSnapshotHash(ov ProviderModelOverride) string {
12 data, _ := json.Marshal(struct {
13 Protocol string
14 Efforts []string
15 Default string
16 }{ov.ReasoningProtocol, ov.SupportedEfforts, ov.DefaultEffort})
17 sum := sha256.Sum256(data)
18 return hex.EncodeToString(sum[:])
19 }
20
21 func reasoningCompatibilitySnapshots(entries []ProviderEntry) []ProviderEntry {
22 snapshots := make([]ProviderEntry, len(entries))
23 for i, entry := range entries {
24 snapshots[i] = reasoningCompatibilitySnapshot(entry)
25 }
26 return snapshots
27 }
28
29 // explicitModelReasoning peels only untouched generated fields. Legacy writers
30 // that change a declaration invalidate the digest, preserving the entire edit.
31 // A writer that drops the optional marker also leaves explicit declarations.
32 func explicitModelReasoning(ov ProviderModelOverride) ProviderModelOverride {
33 mask, digest, ok := strings.Cut(ov.ReasoningDefaults, ":")
34 ov.ReasoningDefaults = ""
35 if !ok || digest != reasoningSnapshotHash(ov) || strings.Trim(mask, "psd") != "" {
36 return ov
37 }
38 if strings.Contains(mask, "p") {
39 ov.ReasoningProtocol = ""
40 }
41 if strings.Contains(mask, "s") {
42 ov.SupportedEfforts = nil
43 }
44 if strings.Contains(mask, "d") {
45 ov.DefaultEffort = ""
46 }
47 return ov
48 }
49
50 // reasoningCompatibilitySnapshot keeps older readers functional without making
51 // generated defaults permanent user overrides in current readers. This copy is
52 // used only at serialization; runtime and settings retain explicit fields only.
53 func reasoningCompatibilitySnapshot(entry ProviderEntry) ProviderEntry {
54 e := entry
55 stripRuntimeReasoningDefaults(&e)
56 e.ModelOverrides = maps.Clone(entry.ModelOverrides)
57 for _, model := range e.ModelList() {
58 ov := explicitModelReasoning(e.ModelOverrides[model])
59 selected := e
60 selected.Model = model
61 resolved := ResolveReasoningEntry(&selected)
62 mask := ""
63 if ov.ReasoningProtocol == "" && explicitReasoningProtocol(&e) == "" && resolved.ReasoningProtocol != "" {
64 ov.ReasoningProtocol = resolved.ReasoningProtocol
65 mask += "p"
66 }
67 if len(ov.SupportedEfforts) == 0 && len(e.SupportedEfforts) == 0 && len(resolved.SupportedEfforts) > 0 {
68 ov.SupportedEfforts = append([]string(nil), resolved.SupportedEfforts...)
69 mask += "s"
70 }
71 if ov.DefaultEffort == "" && e.DefaultEffort == "" && resolved.DefaultEffort != "" {
72 ov.DefaultEffort = resolved.DefaultEffort
73 mask += "d"
74 }
75 if mask == "" {
76 continue
77 }
78 ov.ReasoningDefaults = mask + ":" + reasoningSnapshotHash(ov)
79 if e.ModelOverrides == nil {
80 e.ModelOverrides = map[string]ProviderModelOverride{}
81 }
82 e.ModelOverrides[model] = ov
83 }
84 return e
85 }
86
86 lines GO