返回 DeepSeek-Reasonix
context_budget.go
根目录 / internal / provider / context_budget.go
1 package provider
2
3 // Context window accounting for local admission. Unknown never assumes a
4 // shared prompt+completion window; Independent disables shared-window clipping.
5 type ContextWindowMode uint8
6
7 const (
8 ContextWindowUnknown ContextWindowMode = iota
9 ContextWindowShared
10 ContextWindowIndependent
11 )
12
13 // How a provider places an output ceiling on the wire.
14 type OutputLimitMode uint8
15
16 const (
17 OutputLimitOmitWhenSafe OutputLimitMode = iota
18 OutputLimitAlways
19 OutputLimitRequired
20 OutputLimitUnsupported
21 )
22
23 // ContextBudgetPolicy is the provider-owned window and output-limit contract.
24 // Zero Auto/Max means the value is unknown. It never feeds compact_ratio.
25 type ContextBudgetPolicy struct {
26 WindowMode ContextWindowMode
27 AutoOutputTokens int
28 MaxOutputTokens int
29 LimitMode OutputLimitMode
30 }
31
32 // ContextBudgetPolicyProvider reports the unified budget contract. Existing
33 // OutputBudgetProvider and SharedWindowOutputProvider implementations remain
34 // valid fallbacks through ResolveContextBudgetPolicy.
35 type ContextBudgetPolicyProvider interface {
36 ContextBudgetPolicy() ContextBudgetPolicy
37 }
38
39 const (
40 ContextBudgetSourceUnknown = "unknown"
41 ContextBudgetSourceExplicit = "explicit"
42 ContextBudgetSourceOfficial = "official"
43 ContextBudgetSourceOpenCode = "opencode"
44 ContextBudgetSourceLearned = "learned"
45 )
46
47 func (m ContextWindowMode) String() string {
48 switch m {
49 case ContextWindowShared:
50 return "shared"
51 case ContextWindowIndependent:
52 return "independent"
53 default:
54 return "unknown"
55 }
56 }
57
58 func (m OutputLimitMode) String() string {
59 switch m {
60 case OutputLimitAlways:
61 return "always"
62 case OutputLimitRequired:
63 return "required"
64 case OutputLimitUnsupported:
65 return "unsupported"
66 default:
67 return "omit_when_safe"
68 }
69 }
70
71 // ResolveContextBudgetPolicy prefers the new capability and otherwise maps the
72 // older output-budget interfaces so tests, fork wrappers, and unmigrated
73 // adapters keep working.
74 func ResolveContextBudgetPolicy(p Provider) ContextBudgetPolicy {
75 if p == nil {
76 return ContextBudgetPolicy{}
77 }
78 if owned, ok := p.(ContextBudgetPolicyProvider); ok {
79 return owned.ContextBudgetPolicy()
80 }
81 policy := ContextBudgetPolicy{WindowMode: ContextWindowUnknown, LimitMode: OutputLimitOmitWhenSafe}
82 if shared, ok := p.(SharedWindowOutputProvider); ok && shared.SharesContextWindow() {
83 policy.WindowMode = ContextWindowShared
84 }
85 if budget, ok := p.(OutputBudgetProvider); ok {
86 n := budget.OutputBudget()
87 if n > 0 {
88 policy.AutoOutputTokens = n
89 policy.MaxOutputTokens = n
90 if policy.WindowMode == ContextWindowShared {
91 policy.LimitMode = OutputLimitAlways
92 }
93 }
94 }
95 return policy
96 }
97
97 lines GO