返回 DeepSeek-Reasonix
context_status.go
根目录 / internal / agent / context_status.go
1 package agent
2
3 import (
4 "slices"
5 "strings"
6
7 "reasonix/internal/provider"
8 )
9
10 // ContextMaintenanceSnapshot is a read-only view of the current provider-bound
11 // context. It separates present composition from cumulative summary-call cost.
12 type ContextMaintenanceSnapshot struct {
13 CanonicalTokens int
14 ProjectedTokens int
15 SummaryTokens int
16 LastSavedTokens int
17 SnipTrigger int
18 FoldTrigger int
19 ForceTrigger int
20 TriggerTokens int
21 CheckpointState string
22 HardInputCeiling int
23 Headroom int
24 ProjectionVersion uint64
25 Blocked bool
26 LastReceipt *ContextMaintenanceReceipt
27 ContextBudget *ContextBudgetSnapshot
28 }
29
30 // ContextBudgetSnapshot is the optional send-time admission view for the
31 // desktop Context Panel. All fields are optional for older frontends.
32 type ContextBudgetSnapshot struct {
33 WindowMode string
34 LimitMode string
35 Source string
36 WindowTokens int
37 PromptTokens int
38 AutoOutputTokens int
39 MaxOutputTokens int
40 RequestedOutputTokens int
41 EffectiveOutputTokens int
42 ReserveTokens int
43 PhysicalRemaining int
44 Clipped bool
45 LastRecovery string
46 ObservedWindow int
47 ObservedPrompt int
48 ObservedCompletion int
49 }
50
51 func (a *Agent) ContextMaintenanceSnapshot() ContextMaintenanceSnapshot {
52 if a == nil || a.sess.conversation == nil {
53 return ContextMaintenanceSnapshot{}
54 }
55 canonical, _ := a.sess.conversation.snapshotMessagesVersion()
56 a.sess.compactionMu.Lock()
57 state := a.sess.compactionState
58 checkpointState := a.sess.checkpointState
59 a.sess.compactionMu.Unlock()
60 visible := canonical
61 valid := projectionValid(state, canonical, a.currentPromptCacheKey())
62 if valid {
63 if projected := modelVisibleFromProjection(state.Projection, canonical); len(projected) > 0 {
64 visible = projected
65 }
66 }
67 trigger := a.compactTrigger()
68 // UI checkpoint label requires a still-valid covered prefix, not merely
69 // that the sidecar loaded.
70 uiCheckpoint := "none"
71 if valid && len(state.Projection.Messages) > 0 {
72 uiCheckpoint = stateCheckpointState(checkpointState, state)
73 }
74 snapshot := ContextMaintenanceSnapshot{
75 CanonicalTokens: a.estimatedVisibleRequestTokens(canonical),
76 ProjectedTokens: a.estimatedVisibleRequestTokens(visible),
77 FoldTrigger: trigger,
78 TriggerTokens: trigger,
79 CheckpointState: uiCheckpoint,
80 HardInputCeiling: a.hardInputCeiling(),
81 ProjectionVersion: state.Projection.ProjectionVersion,
82 }
83 for _, msg := range visible {
84 if isCompactionSummary(msg) {
85 snapshot.SummaryTokens += a.estimatedPromptTokens([]provider.Message{msg})
86 }
87 }
88 snapshot.Headroom = max(0, snapshot.HardInputCeiling-snapshot.ProjectedTokens)
89 currentHash := a.contextMaintenanceInputHash(visible)
90 if state.LastReceipt != nil {
91 receipt := *state.LastReceipt
92 snapshot.LastReceipt = &receipt
93 if receipt.Status == "applied" && (receipt.Action == "prune" || receipt.Action == "summary") {
94 snapshot.LastSavedTokens = receipt.SavedTokens
95 }
96 // Generation-scoped blocked/failed receipts match contextMaintenanceBlocked.
97 if receipt.Status == "blocked" || receipt.Status == "failed" {
98 snapshot.Blocked = true
99 }
100 }
101 // Legacy sidecars may only have top-level BlockedInputHash.
102 if !snapshot.Blocked && state.BlockedInputHash != "" && state.BlockedInputHash == currentHash {
103 snapshot.Blocked = true
104 }
105 if budget := a.lastAdmission(); budget.WindowTokens > 0 || budget.PromptTokens > 0 || budget.LastRecovery != "" && budget.LastRecovery != contextRecoveryNone {
106 snapshot.ContextBudget = &ContextBudgetSnapshot{
107 WindowMode: budget.WindowMode, LimitMode: budget.LimitMode, Source: budget.Source,
108 WindowTokens: budget.WindowTokens, PromptTokens: budget.PromptTokens,
109 AutoOutputTokens: budget.AutoOutputTokens, MaxOutputTokens: budget.MaxOutputTokens,
110 RequestedOutputTokens: budget.RequestedOutputTokens, EffectiveOutputTokens: budget.EffectiveOutputTokens,
111 ReserveTokens: budget.ReserveTokens, PhysicalRemaining: budget.PhysicalRemaining,
112 Clipped: budget.Clipped, LastRecovery: budget.LastRecovery,
113 ObservedWindow: budget.ObservedWindow, ObservedPrompt: budget.ObservedPrompt,
114 ObservedCompletion: budget.ObservedCompletion,
115 }
116 }
117 return snapshot
118 }
119
120 // LastCompactionSummary returns display metadata from the latest installed
121 // projection. Provider request construction never reads this helper.
122 func (a *Agent) LastCompactionSummary() string {
123 if a == nil || a.sess.conversation == nil {
124 return ""
125 }
126 a.sess.compactionMu.Lock()
127 state := a.sess.compactionState
128 a.sess.compactionMu.Unlock()
129 for _, message := range slices.Backward(state.Projection.Messages) {
130 if isCompactionSummary(message) {
131 return strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(message.Content, summaryTagOpen), summaryTagClose))
132 }
133 }
134 return ""
135 }
136
137 func stateCheckpointState(runtimeState string, state CompactionState) string {
138 if len(state.Projection.Messages) == 0 {
139 return "none"
140 }
141 if runtimeState == "applied" {
142 return "applied"
143 }
144 return "restored"
145 }
146
146 lines GO