Where does the bug appear (feature/product)?
Cursor SDK
Describe the Bug
Every send() restores conversation state by fetching each of the agent’s checkpoint blobs individually. JsonlLocalAgentStore.checkpoints.get reads and parses the whole checkpoints.ndjson on every call, so one point lookup costs O(file size). Restoring N blobs costs O(N x file size), and both grow each turn, so turn latency grows quadratically with conversation length. In my app a conversation reached 492 blobs / 9.3MB: send() took 11.65s to return a run, 8.44s of it inside 492 checkpoints.get calls. Another reached 3030 blobs / 34MB, projecting ~200s per message. checkpoints.create is affected too, roughly 64ms per append on a 1.4MB file.
Steps to Reproduce
No network or API key needed. For n in [50, 200, 800]: create a fresh JsonlLocalAgentStore in a temp dir, write n checkpoint blobs with an identical 20KB payload via checkpoints.create({agentId, blobId, data}), then time 20 checkpoints.get calls on distinct blobIds.
Measured per-get:
- 50 blobs, 1.3MB file: 2.53ms
- 200 blobs, 5.3MB file: 7.60ms
- 800 blobs, 21.4MB file: 37.16ms
Per-get cost tracks file size linearly while blob size stays constant, which confirms a full-file scan per lookup. Implied full-restore cost: 0.1s, 1.5s, 29.7s. An n=3200 case never finished building, because create rescans too. I see the same curve instrumenting real stores in my app.
Expected Behavior
checkpoints.get should be a point lookup: index the file on open, or cache parsed contents keyed by mtime, so restoring an agent stays linear in state size instead of quadratic. checkpoints.create should append without rescanning.
Version Information
@cursor/sdk 1.0.24, Node v20.11.0, Ubuntu 22.04.5 (Linux 6.12.67-linuxkit x86_64). Models composer-2.5 and claude-opus-5. Store wired as local: { cwd, settingSources: [‘user’,‘project’,‘plugins’], store: new JsonlLocalAgentStore(dir) }.