description: "Replay-aware token and context-pressure measurement for users and maintainers sizing prompts or building compaction and occupancy displays."
English | 中文
Use ctx.tokenMeter to estimate a session's current request and context pressure or price one message. Measurements replay the durable session log, remain deterministic, and make no model calls, so compaction, occupancy displays, and telemetry can share one result. When session projections are available, consumers can read tokenUsage, contextPressure, and contextBreakdown; text and routes without image pricing use an approximate fixed heuristic, declared visual-token pricing applies when available, and files are priced as model-visible handle text. Provider-reported usage is reused only for an identical request envelope; the package adds no model-visible content and makes no loop decisions.
Mount this plugin when a consumer needs token or context pressure for compaction decisions, occupancy displays, or telemetry. The estimator has no settings and adds no model-visible surface; model capacity belongs to the adapter that owns the exact provider/model route and is available through ctx.llm.resolveModelInfo().context.
Choose it when several plugins should agree on one replay-based measurement — compaction planning, occupancy UIs, and pressure checks all read the same fold. The measurements replay the durable session log, so they are deterministic, cost no model calls, and reflect exactly what is logged. Text and undeclared image routes use a fixed heuristic; reach for a provider tokenizer when a deployment needs exact billing-grade counts.
ctx.tokenMeter exposes two operations. measure(session, requestHeader?) returns a detached, deeply immutable snapshot at one consumed-log revision: totalTokens is request-and-response pressure, and surfaceTokens is the surface-only route-priced total equal to the sum of nodes[].tokens. An optional requestHeader override selects the priced route and pressure fields; the node set still describes the current session. estimateMessage(message) prices one message with the fixed heuristic. Every call clones the positional surface nodes, so measurement is O(surface).
const { totalTokens, surfaceTokens, nodes } = ctx.tokenMeter.measure(session)
const price = ctx.tokenMeter.estimateMessage(message)
Each measurement resolves the effective envelope's provider/model through the optional llm service. Image occurrences use the routed request's visual-token price plus model-visible text when the adapter declares pricing, and occurrences selected by an image/offload event are priced as the route's placeholder text exactly as the surface sends them; other routes keep the fixed heuristic. File occurrences use the exact route-independent handle text that the same llm service resolves for adapter dispatch, including its current execution-world path or explicit no-path message. Each node also carries route-independent heuristicTokens for replacement shadow prices. Provider usage is reused only when the latest successful call's canonical request envelope matches the measured envelope and its total is no lower than that call's full route-priced anchor; otherwise the complete current envelope and surface are estimated. Surface changes stay signed relative to a matching anchor repriced under the same route, including negative deltas after shrinking replacements.
The measurement anchor includes the priced surface immediately before the successful assistant/message, including system and user messages admitted after step/start and replacements made before a retry. With unchanged durable output, the completed call has zero surface delta: its prompt is already included in provider usage. Later surface changes remain signed deltas against that anchor.
When the composition provides ctx.sessionProjections, token-meter registers three projection units. tokenUsage carries the complete durable log's uncachedInputTokens, outputTokens, cacheReadTokens, and cacheWriteTokens. A final assistant-message sample replaces streaming usage from the same attempt; llm/retry-started ends that replacement scope, so a retry in the same step contributes another billed attempt. contextPressure carries optional pressureTokens (the newest provider-reported prompt size), optional projectedTokens (what the next request's prompt would cost), and optional contextWindow from the newest request/context record. contextBreakdown carries heuristic systemTokens, toolsTokens, and messageTokens — the context's composition, not its provider-billed size. Unloading the plugin removes all three keys.
Image offload reprices existing node identities while preserving prior usage anchors. The fixed reference heuristic excludes offloaded metadata, so an offload decision does not change contextBreakdown or the scalar heuristic total; route-aware measurement replaces the selected visual prices with placeholder text.
contextBreakdown classifies the last nonempty surviving system/message in surface order as systemTokens; empty dormant nodes contribute nothing, and no nonempty system means zero. messageTokens includes every other visible node, including superseded prompts. Their sum always equals measure().nodes[].heuristicTokens, including after unmetered replacements, compaction, and per-node prompt clearing. toolsTokens follows the latest request/header. All three use the fixed heuristic, not route image pricing or file-handle projection; they are approximate composition, not billing or projectedTokens.
deriveTurnTokenUsage(events) folds one complete turn into exact per-attempt and whole-turn usage for browser consumers. It returns no result when lifecycle evidence is missing, counts are unsafe, or exact totals conflict; each corresponding aggregate appears only when every participating attempt reports its optional cache, reasoning, or route value.
- name: '@deepseek-ai/dsh-token-meter'
- name: '@deepseek-ai/dsh-compaction-basic'
Both plugins have usable defaults. The meter consumes only the optional llm service, and only to resolve route-declared request-image pricing; compaction remains optional. A deployment configures capacity and image pricing on its LLM adapter and compaction policy on dsh-compaction-basic.
Occupancy is a reference figure, not a billing record: nothing in the harness makes decisions from it, and compaction reads measure() instead. A UI computes occupancy by dividing measured pressure by the separately resolved capacity for the selected model. The contextBreakdown figures are estimates that will not sum to projectedTokens, whose provider anchor carries exactly the heuristic error — CJK text and JSON schemas underprice badly at four characters per token.
Read these pages when the package-level contract is not enough. They move from the measurement service to the compaction consumer and the shared types.
ctx.tokenMeter.resolveModelInfo() serves.measure().projectedTokens and the rejected atomic-pair comparison.Indirectly, through consumers such as dsh-compaction-basic; the service itself adds no prompt, message, schema, tool, or model call.
No direct invalidation; the named consumer owns any request-prefix changes.
These limits define where the measurement stops and future work begins. They are current package constraints, not a general token-accounting comparison or a task backlog.
contextPressure.projectedTokens folds that replacement at zero delta until the next usage sample; contextBreakdown.systemTokens and measure() reprice the new prompt immediately.Runtime invariant: No companion is published. Usage folds replace samples within each attempt; totals need not be monotone. Composition and measurement share the positional replacement planner and fixed estimator, so their heuristic surface totals agree by construction rather than through independent mutable observations. Route-priced totals deliberately differ.