返回 DeepSeek-Reasonix
context_maintenance.go
根目录 / desktop / context_maintenance.go
1 package main
2
3 import (
4 "time"
5
6 "reasonix/internal/agent"
7 "reasonix/internal/billing"
8 )
9
10 // ContextInfo is the prompt-vs-window gauge payload plus session totals. Used
11 // and Window both zero means no context-window data yet.
12 type ContextInfo struct {
13 Used int `json:"used"`
14 Window int `json:"window"`
15 SessionTokens int `json:"sessionTokens"`
16 CompactRatio float64 `json:"compactRatio,omitempty"`
17 SessionCost float64 `json:"sessionCost,omitempty"`
18 SessionCurrency string `json:"sessionCurrency,omitempty"`
19 CacheHitTokens int `json:"cacheHitTokens,omitempty"`
20 CacheMissTokens int `json:"cacheMissTokens,omitempty"`
21 Estimated bool `json:"estimated,omitempty"`
22 SessionCostComplete bool `json:"sessionCostComplete,omitempty"`
23 SessionCostQuote *billing.CostQuote `json:"sessionCostQuote,omitempty"`
24 Sources map[string]usageSourceStats `json:"sources,omitempty"`
25 Maintenance *ContextMaintenanceInfo `json:"maintenance,omitempty"`
26 ContextBudget *ContextBudgetInfo `json:"contextBudget,omitempty"`
27 }
28
29 // ContextMaintenanceInfo is the bridge-safe current-view snapshot. Optional
30 // fields preserve compatibility with older desktop/front-end combinations.
31 type ContextMaintenanceInfo struct {
32 CanonicalTokens int `json:"canonicalTokens,omitempty"`
33 ProjectedTokens int `json:"projectedTokens,omitempty"`
34 SummaryTokens int `json:"summaryTokens,omitempty"`
35 LastSavedTokens int `json:"lastSavedTokens,omitempty"`
36 SnipTrigger int `json:"snipTrigger,omitempty"` // always 0; legacy compatibility
37 FoldTrigger int `json:"foldTrigger,omitempty"` // alias of TriggerTokens
38 ForceTrigger int `json:"forceTrigger,omitempty"` // always 0; legacy compatibility
39 TriggerTokens int `json:"triggerTokens,omitempty"`
40 CheckpointState string `json:"checkpointState,omitempty"` // none|restored|applied
41 HardInputCeiling int `json:"hardInputCeiling,omitempty"`
42 Headroom int `json:"headroom,omitempty"`
43 ProjectionVersion uint64 `json:"projectionVersion,omitempty"`
44 Blocked bool `json:"blocked,omitempty"`
45 LastReceipt *ContextMaintenanceReceiptInfo `json:"lastReceipt,omitempty"`
46 ContextBudget *ContextBudgetInfo `json:"contextBudget,omitempty"`
47 }
48
49 // ContextBudgetInfo is the optional send-time admission view. Older desktop
50 // builds ignore unknown fields; omission is the compatibility default.
51 type ContextBudgetInfo struct {
52 WindowMode string `json:"windowMode,omitempty"`
53 LimitMode string `json:"limitMode,omitempty"`
54 Source string `json:"source,omitempty"`
55 WindowTokens int `json:"windowTokens,omitempty"`
56 PromptTokens int `json:"promptTokens,omitempty"`
57 AutoOutputTokens int `json:"autoOutputTokens,omitempty"`
58 MaxOutputTokens int `json:"maxOutputTokens,omitempty"`
59 RequestedOutputTokens int `json:"requestedOutputTokens,omitempty"`
60 EffectiveOutputTokens int `json:"effectiveOutputTokens,omitempty"`
61 ReserveTokens int `json:"reserveTokens,omitempty"`
62 PhysicalRemaining int `json:"physicalRemaining,omitempty"`
63 Clipped bool `json:"clipped,omitempty"`
64 LastRecovery string `json:"lastRecovery,omitempty"`
65 ObservedWindow int `json:"observedWindow,omitempty"`
66 ObservedPrompt int `json:"observedPrompt,omitempty"`
67 ObservedCompletion int `json:"observedCompletion,omitempty"`
68 }
69
70 type ContextMaintenanceReceiptInfo struct {
71 OperationID string `json:"operationId,omitempty"`
72 Status string `json:"status,omitempty"`
73 Action string `json:"action,omitempty"`
74 Trigger string `json:"trigger,omitempty"`
75 SourceProjection uint64 `json:"sourceProjection,omitempty"`
76 ProjectionVersion uint64 `json:"projectionVersion,omitempty"`
77 CoveredCount int `json:"coveredCount,omitempty"`
78 CoveredPrefixHash string `json:"coveredPrefixHash,omitempty"`
79 InputHash string `json:"inputHash,omitempty"`
80 OutputHash string `json:"outputHash,omitempty"`
81 InputTokens int `json:"inputTokens,omitempty"`
82 ResultTokens int `json:"resultTokens,omitempty"`
83 SavedTokens int `json:"savedTokens,omitempty"`
84 AffectedToolResults int `json:"affectedToolResults,omitempty"`
85 SummaryHash string `json:"summaryHash,omitempty"`
86 Archive string `json:"archive,omitempty"`
87 CacheBreak bool `json:"cacheBreak,omitempty"`
88 Reason string `json:"reason,omitempty"`
89 BlockedInputHash string `json:"blockedInputHash,omitempty"`
90 CreatedAt string `json:"createdAt,omitempty"`
91 }
92
93 func contextMaintenanceInfo(snapshot agent.ContextMaintenanceSnapshot) *ContextMaintenanceInfo {
94 if snapshot.CanonicalTokens == 0 && snapshot.ProjectedTokens == 0 && snapshot.LastReceipt == nil {
95 return nil
96 }
97 info := &ContextMaintenanceInfo{
98 CanonicalTokens: snapshot.CanonicalTokens, ProjectedTokens: snapshot.ProjectedTokens,
99 SummaryTokens: snapshot.SummaryTokens, LastSavedTokens: snapshot.LastSavedTokens,
100 // Snip/Force remain zero for one-version compatibility with older frontends.
101 FoldTrigger: snapshot.TriggerTokens, TriggerTokens: snapshot.TriggerTokens,
102 CheckpointState: snapshot.CheckpointState, HardInputCeiling: snapshot.HardInputCeiling,
103 Headroom: snapshot.Headroom, ProjectionVersion: snapshot.ProjectionVersion,
104 Blocked: snapshot.Blocked,
105 }
106 if snapshot.ContextBudget != nil {
107 info.ContextBudget = contextBudgetInfo(snapshot.ContextBudget)
108 }
109 if source := snapshot.LastReceipt; source != nil {
110 info.LastReceipt = contextMaintenanceReceiptInfo(source)
111 }
112 return info
113 }
114
115 func contextBudgetInfo(source *agent.ContextBudgetSnapshot) *ContextBudgetInfo {
116 if source == nil {
117 return nil
118 }
119 return &ContextBudgetInfo{
120 WindowMode: source.WindowMode, LimitMode: source.LimitMode, Source: source.Source,
121 WindowTokens: source.WindowTokens, PromptTokens: source.PromptTokens,
122 AutoOutputTokens: source.AutoOutputTokens, MaxOutputTokens: source.MaxOutputTokens,
123 RequestedOutputTokens: source.RequestedOutputTokens, EffectiveOutputTokens: source.EffectiveOutputTokens,
124 ReserveTokens: source.ReserveTokens, PhysicalRemaining: source.PhysicalRemaining,
125 Clipped: source.Clipped, LastRecovery: source.LastRecovery,
126 ObservedWindow: source.ObservedWindow, ObservedPrompt: source.ObservedPrompt,
127 ObservedCompletion: source.ObservedCompletion,
128 }
129 }
130
131 func contextMaintenanceReceiptInfo(source *agent.ContextMaintenanceReceipt) *ContextMaintenanceReceiptInfo {
132 receipt := &ContextMaintenanceReceiptInfo{
133 OperationID: source.OperationID, Status: source.Status, Action: source.Action, Trigger: source.Trigger,
134 SourceProjection: source.SourceProjection, ProjectionVersion: source.ProjectionVersion,
135 CoveredCount: source.CoveredCount, CoveredPrefixHash: source.CoveredPrefixHash,
136 InputHash: source.InputHash, OutputHash: source.OutputHash,
137 InputTokens: source.InputTokens, ResultTokens: source.ResultTokens, SavedTokens: source.SavedTokens,
138 AffectedToolResults: source.AffectedToolResults, SummaryHash: source.SummaryHash, Archive: source.Archive,
139 CacheBreak: source.CacheBreak, Reason: source.Reason, BlockedInputHash: source.BlockedInputHash,
140 }
141 if !source.CreatedAt.IsZero() {
142 receipt.CreatedAt = source.CreatedAt.Format(time.RFC3339Nano)
143 }
144 return receipt
145 }
146
146 lines GO