From bce0c0585668b65880adde150ba2e6095234ba76 Mon Sep 17 00:00:00 2001 From: Bohan Jiang <52446949+Bohan-J@users.noreply.github.com> Date: Fri, 24 Jul 2026 01:55:07 +0800 Subject: [PATCH] refactor(agent): drop dead Cursor cost fields (CLI reports no cost) (#5852) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MUL-5240 cursor-agent's stream-json never populates total_cost_usd or a per-step cost — the result event's usage object carries token counts only. Both fields were speculatively copied from Claude Code's schema in the original Cursor runtime PR (#1057) and were never read. Verified against the real CLI (2026.07.20, stream-json and json) plus Cursor's CLI docs. Remove the two dead fields and document that Cursor spend stays estimated from the static rate table (no authoritative per-turn cost to carry, unlike Grok). No behavior change. Co-authored-by: Bohan-J Co-authored-by: multica-agent --- server/pkg/agent/cursor.go | 15 ++++++++++++--- server/pkg/agent/cursor_test.go | 2 ++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/server/pkg/agent/cursor.go b/server/pkg/agent/cursor.go index 6a4aecedd..68846607a 100644 --- a/server/pkg/agent/cursor.go +++ b/server/pkg/agent/cursor.go @@ -665,7 +665,15 @@ type cursorStreamEvent struct { // tool_result fields Output string `json:"output,omitempty"` - // result fields + // result fields. + // + // The result event reports token counts only; cursor-agent's stream-json + // carries no per-turn cost (no `total_cost_usd`, no per-step `cost`). This + // was verified against the real CLI (2026.07.20, both stream-json and json + // output) and Cursor's CLI docs. So — unlike Grok, whose turn cost xAI + // reports authoritatively — Cursor spend is estimated downstream from the + // static rate table, never carried through here. Add a cost field only + // when a real payload proves the CLI emits one. ResultText string `json:"result,omitempty"` IsError bool `json:"is_error,omitempty"` InputTokens int64 `json:"inputTokens,omitempty"` @@ -673,7 +681,6 @@ type cursorStreamEvent struct { CacheReadTokens int64 `json:"cacheReadTokens,omitempty"` CacheWriteTokens int64 `json:"cacheWriteTokens,omitempty"` Usage *cursorUsage `json:"usage,omitempty"` - TotalCost float64 `json:"total_cost_usd,omitempty"` // error fields ErrorMsg string `json:"error,omitempty"` @@ -763,6 +770,9 @@ type cursorTextPart struct { Text string `json:"text"` } +// cursorStepFinishPart carries per-step token counts. cursor-agent does not +// report a per-step cost (see cursorStreamEvent's result-fields note), so only +// tokens are parsed here. type cursorStepFinishPart struct { Tokens struct { Input int `json:"input"` @@ -771,7 +781,6 @@ type cursorStepFinishPart struct { Read int `json:"read"` } `json:"cache"` } `json:"tokens"` - Cost float64 `json:"cost"` } // ── Helpers ── diff --git a/server/pkg/agent/cursor_test.go b/server/pkg/agent/cursor_test.go index 803a70958..a14494882 100644 --- a/server/pkg/agent/cursor_test.go +++ b/server/pkg/agent/cursor_test.go @@ -446,6 +446,8 @@ func TestCursorStepFinishParsing(t *testing.T) { t.Parallel() part := cursorStepFinishPart{} + // The trailing "cost" key is ignored: cursor-agent does not report per-step + // cost, and unknown keys must not break token parsing. data := `{"tokens":{"input":500,"output":200,"cache":{"read":100}},"cost":0.01}` if err := json.Unmarshal([]byte(data), &part); err != nil { t.Fatalf("unmarshal: %v", err)