mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 17:17:38 +00:00
* Keep clear in the same chat and reset its provider context * Derive clear pauses only from journal membership and cover older rewind clients * Point queued command rewind test at the structured hook * Group queue consume errors and rewind replay assertions
56 lines
2.1 KiB
TypeScript
56 lines
2.1 KiB
TypeScript
// Context usage a chat surface can derive from the transcript alone: the prompt
|
|
// the model read on the last request that reported usage, against the window of
|
|
// the model that served it.
|
|
|
|
import { contextTokensFromUsage } from './agent-session-context-usage'
|
|
import type { NativeChatMessage } from './native-chat-types'
|
|
import { isNativeChatContextClear } from './agent-session-context-clear'
|
|
|
|
export type NativeChatContextUsage = {
|
|
usedTokens: number
|
|
/** Null when the serving model's window is not known. */
|
|
windowTokens: number | null
|
|
/** Rounded and never clamped: an over-limit turn reads above 100. Null with the window. */
|
|
percentage: number | null
|
|
}
|
|
|
|
/** Resolves a model's context window, or null when the host does not know it. */
|
|
export type NativeChatContextWindowLookup = (message: NativeChatMessage) => number | null
|
|
|
|
/** True for the transcript row an agent writes when it compacts the conversation. */
|
|
export function isNativeChatCompactionBoundary(message: NativeChatMessage): boolean {
|
|
return (
|
|
message.role === 'system' &&
|
|
message.blocks.some((block) => block.type === 'text' && block.presentation === 'compaction')
|
|
)
|
|
}
|
|
|
|
/** The newest usage-bearing response decides; a compaction after it means the
|
|
* context it measured is gone, so nothing is known until the next response. */
|
|
export function deriveNativeChatContextUsage(
|
|
messages: readonly NativeChatMessage[],
|
|
windowFor: NativeChatContextWindowLookup
|
|
): NativeChatContextUsage | null {
|
|
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
const message = messages[index]!
|
|
if (isNativeChatCompactionBoundary(message) || isNativeChatContextClear(message)) {
|
|
return null
|
|
}
|
|
if (message.role !== 'assistant' || !message.usage) {
|
|
continue
|
|
}
|
|
const usedTokens = contextTokensFromUsage(message.usage)
|
|
if (usedTokens <= 0) {
|
|
return null
|
|
}
|
|
const window = windowFor(message)
|
|
const windowTokens = window !== null && window > 0 ? window : null
|
|
return {
|
|
usedTokens,
|
|
windowTokens,
|
|
percentage: windowTokens === null ? null : Math.round((usedTokens / windowTokens) * 100)
|
|
}
|
|
}
|
|
return null
|
|
}
|