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