fix(agentimport): stop summing cumulative subagent tokens across imported turns

main

Commit

suhaanthayyil2mo ago

The subagent-aware importers (Claude Code, Factory AI Droid) compute each turn's token usage via CalculateTotalTokenUsage over the full transcript prefix [0,end): main-agent fields are scoped to the turn's [start,end) slice (genuine per-turn deltas), but subagent IDs are discovered from the whole prefix (#329) and each agent-<id>.jsonl is re-read from line 0, so SubagentTokens is a cumulative-since-session-start snapshot that repeats every already-discovered subagent's full total on every later turn.

Both import consumers then summed that snapshot: writeSessionState folds turns with AddTokenUsage for the session total, and every imported checkpoint stores its turn's TokenUsage on entire/checkpoints/v1 (downstream sums those). The result multiplied a subagent's tokens by the number of turns after it was first discovered, inflating both the imported session total and per-checkpoint usage.

Rescope each turn's SubagentTokens from the cumulative snapshot to a per-turn delta (this turn's cumulative minus the previous turn's) in splitLineTurns via types.SubtractTokenUsage. Each imported checkpoint then carries only the subagent usage attributable to its turn, and summing the deltas reconstructs the final cumulative total exactly once. This mirrors the live path, which keeps the latest cumulative snapshot in state.TokenUsage and rescopes each checkpoint window to "cumulative minus a captured baseline" (accumulateTokenUsage / SessionState.SubagentTokensBaseline); here the baseline for turn k is turn k-1's cumulative. The cumulative is monotonic non-decreasing, so the deltas sum back to the final snapshot exactly. Turns with no discovered subagent keep a nil SubagentTokens, so this is a no-op for the non-subagent-aware importers.

Add regression tests for both importers: a subagent spawned in an early turn plus later prompt turns, asserting the subagent total is counted exactly once in both the summed per-turn/per-checkpoint usage and the imported session total, while main-agent totals still sum. Reverting the rescope makes both assertions fail with a 3x multiplication.

Refs #329

Co-authored-by: Cursor cursoragent@cursor.com