Transcript Incremental Projection
Nucleic-Session: 0FFD007B-0696-4517-9429-129C7B0FD5AC Co-authored-by: Nucleic <[email protected]>
This commit is contained in:
@@ -123,17 +123,37 @@ struct SessionDetailView: View {
|
|||||||
set: { store.setSessionEffort(sessionID, $0) })
|
set: { store.setSessionEffort(sessionID, $0) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Memo for the context-occupancy scan below. The backward scan usually stops at the last
|
||||||
|
/// turn's usage event, but a stream with sparse (or no) usage reporting walks the whole
|
||||||
|
/// transcript — and `body` re-evaluates on every store change and keystroke, so an O(N) scan
|
||||||
|
/// per evaluation quietly compounds on long sessions. `(count, lastSeq)` pins the stream, as
|
||||||
|
/// in the projection cache; a class held in `@State` so updating it from `body` doesn't
|
||||||
|
/// itself invalidate the view.
|
||||||
|
private final class ContextScanCache {
|
||||||
|
var count = -1
|
||||||
|
var lastSeq: UInt64 = 0
|
||||||
|
var used: Int?
|
||||||
|
}
|
||||||
|
@State private var contextScanCache = ContextScanCache()
|
||||||
|
|
||||||
/// Live context-window occupancy (newest turn's input tokens ÷ the model's window), read
|
/// Live context-window occupancy (newest turn's input tokens ÷ the model's window), read
|
||||||
/// from the transcript exactly as the Mac header does.
|
/// from the transcript exactly as the Mac header does. Only the token scan is memoized —
|
||||||
|
/// the window division stays live, so a model switch reflects immediately.
|
||||||
private var contextPercent: Int? {
|
private var contextPercent: Int? {
|
||||||
let used = store.openEvents.reversed().lazy.compactMap { event -> Int? in
|
let events = store.openEvents
|
||||||
|
let cache = contextScanCache
|
||||||
|
if cache.count != events.count || cache.lastSeq != events.last?.seq ?? 0 {
|
||||||
|
cache.count = events.count
|
||||||
|
cache.lastSeq = events.last?.seq ?? 0
|
||||||
|
cache.used = events.reversed().lazy.compactMap { event -> Int? in
|
||||||
switch event.kind {
|
switch event.kind {
|
||||||
case .turnCompleted(let turn): return turn.usage?.contextInputTokens
|
case .turnCompleted(let turn): return turn.usage?.contextInputTokens
|
||||||
case .usage(let usage): return usage.contextInputTokens
|
case .usage(let usage): return usage.contextInputTokens
|
||||||
default: return nil
|
default: return nil
|
||||||
}
|
}
|
||||||
}.first { $0 > 0 }
|
}.first { $0 > 0 }
|
||||||
guard let used else { return nil }
|
}
|
||||||
|
guard let used = cache.used else { return nil }
|
||||||
let window = store.modelCatalog.contextWindow(summary?.model)
|
let window = store.modelCatalog.contextWindow(summary?.model)
|
||||||
guard window > 0 else { return nil }
|
guard window > 0 else { return nil }
|
||||||
return min(100, Int((Double(used) / Double(window)) * 100))
|
return min(100, Int((Double(used) / Double(window)) * 100))
|
||||||
|
|||||||
Reference in New Issue
Block a user