| 1 | package agent |
| 2 | |
| 3 | import "reasonix/internal/tool" |
| 4 | |
| 5 | // contextUsage memoises the projected prompt size. The estimate walks every |
| 6 | // visible message, and status gauges redraw far more often than the view moves, |
| 7 | // so it is keyed on everything that can change the answer: the session, transcript, |
| 8 | // projection, calibration, and provider-visible tool schemas. |
| 9 | type contextUsage struct { |
| 10 | session *Session // transcript versions are local to this instance |
| 11 | transcriptVersion uint64 |
| 12 | projectionVersion uint64 |
| 13 | calibration *promptTokenCalibration |
| 14 | tools *tool.Registry |
| 15 | toolSchemaRevision uint64 |
| 16 | tokens int |
| 17 | } |
| 18 | |
| 19 | // ContextUsedTokens is the number ContextManager compares against its |
| 20 | // thresholds: the estimated prompt size of the view the next request sends. A |
| 21 | // gauge fed from the last turn's usage instead lags a turn, counts completion |
| 22 | // tokens the trigger ignores, and reads zero on a rebound session — which is |
| 23 | // how a session displays 8% while it is compacting. |
| 24 | func (a *Agent) ContextUsedTokens() int { |
| 25 | if a == nil { |
| 26 | return 0 |
| 27 | } |
| 28 | session := a.Session() |
| 29 | if session == nil { |
| 30 | return 0 |
| 31 | } |
| 32 | transcriptVersion := session.TranscriptVersion() |
| 33 | projectionVersion := a.currentProjectionVersion() |
| 34 | calibration := a.sess.output.promptCalibration.Load() |
| 35 | tools := a.svc.tools |
| 36 | toolSchemaRevision := tools.SchemaRevision() |
| 37 | if cached := a.sess.output.contextUsage.Load(); cached != nil && |
| 38 | cached.session == session && |
| 39 | cached.transcriptVersion == transcriptVersion && |
| 40 | cached.projectionVersion == projectionVersion && |
| 41 | cached.calibration == calibration && |
| 42 | cached.tools == tools && |
| 43 | cached.toolSchemaRevision == toolSchemaRevision { |
| 44 | return cached.tokens |
| 45 | } |
| 46 | tokens := a.estimatedVisibleRequestTokens(a.modelVisibleMessages()) |
| 47 | a.sess.output.contextUsage.Store(&contextUsage{ |
| 48 | session: session, |
| 49 | transcriptVersion: transcriptVersion, |
| 50 | projectionVersion: projectionVersion, |
| 51 | calibration: calibration, |
| 52 | tools: tools, |
| 53 | toolSchemaRevision: toolSchemaRevision, |
| 54 | tokens: tokens, |
| 55 | }) |
| 56 | return tokens |
| 57 | } |
| 58 |