refactor(agent): drop dead Cursor cost fields (CLI reports no cost) (#5852)

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 <bohan@devv.ai>
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
Bohan Jiang
2026-07-24 01:55:07 +08:00
committed by GitHub
parent a92bd5387e
commit bce0c05856
2 changed files with 14 additions and 3 deletions

View File

@@ -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 ──

View File

@@ -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)