mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
fix: stop context/cache stats from jumping (subagent usage + stripped context_window) (#1256)
* fix(web): exclude subagent usage from the parent context indicator The status bar's `ctx N/M` and `cache N` come from latestUsage, which scans the normalized messages backwards for the most recent usage. That scan includes sidechain messages, so while a Task subagent runs its usage — describing the subagent's own, much smaller context — becomes the parent's numerator, then snaps back when the parent resumes. The existing `scope_role !== 'child'` guard never fired on any path. Claude never stamps scope_role (sdkToLogConverter.ts says so outright), and Codex drops child token_count events in the CLI before they can reach the web layer, so no producer ever emits 'child'. isSidechain is the signal that actually survives. sdkToLogConverter.ts:308-313 already documents this exact reducer behaviour, but works around only the denominator by forcing the main session's context_window onto sidechain messages. The numerator was left unguarded. * fix(cli): stop stripping context_window from local-session usage UsageSchema is a plain z.object, so Zod's default strip mode drops every undeclared key. sessionScanner forwards parsed.data rather than the raw line, so on the local-JSONL path usage is truncated to the five declared fields and context_window — injected on the SDK path by sdkToLogConverter — never survives. The web status bar then falls back to getContextBudgetTokens, which subtracts a 10k headroom, so the same model reports a 1.0M denominator on a remote session and 990k on a local one. RawMessageSchema right below already carries .passthrough() with a comment about losing message.model and messageId the same way; the nested usage object just never got the same treatment.
This commit is contained in:
@@ -6,13 +6,18 @@
|
||||
import { z } from "zod";
|
||||
|
||||
// Usage statistics for assistant messages - used in apiSession.ts
|
||||
// `passthrough` for the same reason as RawMessageSchema below: the SDK path
|
||||
// injects `context_window` onto this object (sdkToLogConverter.ts) and Anthropic
|
||||
// keeps adding usage breakdowns. Under Zod's default `strip`, the local-JSONL
|
||||
// path silently dropped `context_window`, which made the web status bar fall
|
||||
// back to a heuristic denominator for local sessions only.
|
||||
export const UsageSchema = z.object({
|
||||
input_tokens: z.number().int().nonnegative(),
|
||||
cache_creation_input_tokens: z.number().int().nonnegative().optional(),
|
||||
cache_read_input_tokens: z.number().int().nonnegative().optional(),
|
||||
output_tokens: z.number().int().nonnegative(),
|
||||
service_tier: z.string().optional(),
|
||||
});
|
||||
}).passthrough();
|
||||
|
||||
// `passthrough` keeps fields the SDK adds going forward (e.g. `model`, future
|
||||
// usage breakdowns) so the hub forwards them verbatim. Without it, Zod's
|
||||
|
||||
Reference in New Issue
Block a user