Add Cursor agent support with filter UI - #64
Conversation
Add parser for Cursor's SQLite-based chat history (workspace storage), thread agent type filter through analytics dashboard, and update UI to support filtering by agent. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- extractAssistantContent now uses isBlockBodyEnd to stop consuming lines when non-indented prose follows a marker block, preserving visible assistant text after thinking/tool sections. - isContainedIn rejects rel=="." so a path equal to root is not treated as contained. - GetAgents excludes empty agent names to avoid a blank UI option. - Add tests for all three fixes plus isBlockBodyEnd and DecodeCursorProjectDir. Addresses review #7566 findings 1, 2, 3, and 4. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- GetAgents returns [] instead of null when no agents match - isContainedIn no longer false-negatives on ..prefixed names - Add black accent color for cursor agent Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Reject rel == ".." (parent directory) in isContainedIn - Add "parent of root" test case for isContainedIn - Add TestGetAgentsEmptyResultSerializesAsArray verifying [] JSON Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
roborev: Combined Review (
|
validateCursorContainment and FindCursorSourceFile used strings.HasPrefix(rel, "..") which rejects valid paths like "..config/". Use separator-aware check matching isContainedIn. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
roborev: Combined Review (
|
Cursor changed its transcript format from .txt (plain text with role markers) to .jsonl (Anthropic API message format). Add format detection (first non-empty line is valid JSON) and a JSONL parser that reuses ExtractTextContent for assistant messages. Update all 5 extension-check sites in discovery and engine to accept both .txt and .jsonl files. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The content parser's regex matched `[Thinking]` and `[Tool call]` markers even when they appeared inside backtick code spans in markdown. This caused false-positive thinking/tool block detection when message text discussed these markers (e.g. code reviews). Pre-compute inline code span positions and skip any marker match whose start falls inside a span. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace isCursorJSONL SplitN(20) with byte-capped scan (4 KB) so leading blank lines beyond 20 don't cause misdetection - FindCursorSourceFile now picks the newest file by mtime when both .jsonl and .txt exist for the same session ID - Replace INLINE_CODE_RE regex with a CommonMark-compliant scanner that handles arbitrary backtick delimiter lengths - Add tests for all three fixes: many-blank-line detection, discovery/find coexistence, and long-delimiter inline code Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DecodeCursorProjectDir now only matches marker words (dev, work, code, etc.) at the expected home-directory position rather than scanning the entire hyphenated name. This prevents project names like "my-dev-tool" from being truncated to "tool". DiscoverCursorSessions now dedupes by basename stem when both .txt and .jsonl exist for the same session, preferring .jsonl. This prevents both files from mapping to the same session ID and the last-processed one silently overwriting the other. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
scanInlineCodeSpans now only skips triple-backtick runs at line start as fenced blocks when there is no closing run of the same length on the same line. This correctly treats ``` [Bash] ``` at line start as an inline code span. isCursorJSONL now uses the scan window (4 KB) only to locate the first non-empty line start, then validates the full line from the original data. Lines exceeding 4 KB are no longer truncated before validation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
roborev: Combined Review (
|
…acktick Unify .jsonl/.txt precedence: both DiscoverCursorSessions and FindCursorSourceFile now prefer .jsonl over .txt (previously FindCursorSourceFile used mtime which could diverge from discovery). DecodeCursorProjectDir now scans forward from the minimum marker position instead of checking a single fixed index, handling multi-token usernames like "john-doe" correctly. scanInlineCodeSpans no longer breaks the outer loop when an opening backtick run has no matching closer. This allows later valid spans of different lengths to be found. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Split directory markers into high-confidence (Documents, Code, projects, repos) and low-confidence (code, src, work, dev) tiers. Scan for high-confidence markers first, so a username containing a low-confidence marker word (e.g. "john-code-doe") doesn't shadow a later high-confidence marker (e.g. "Documents"). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add test for the inherent ambiguity in Cursor's lossy path encoding where a low-confidence marker word could be either a directory name or part of a username. The two-pass scan favors high-confidence markers, which is correct for the common case. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
roborev: Combined Review (
|
roborev: Combined Review (
|
When the file watcher triggers processCursor for a .txt file, check if a sibling .jsonl exists for the same stem. If so, skip the .txt to prevent it from overwriting a richer .jsonl parse. This closes the gap where discovery and source lookup prefer .jsonl but watcher-driven sync could still process a .txt. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@jfan-nux — thanks for working on this! please feel free to send follow up PRs if you run into issues |
roborev: Combined Review (
|
## Summary Supersedes #22 (squashed, rebased on main, with review fixes). - Add Cursor as a supported agent type, syncing transcripts from `~/.cursor/projects/<project>/agent-transcripts/` with a dedicated parser, file discovery, and sync engine wiring - Support both `.txt` (legacy plain-text) and `.jsonl` (Anthropic API message format) transcript files with automatic format detection - Add `/api/v1/agents` endpoint and agent filter dropdown in the dashboard header to filter sessions by source - Thread agent filter through analytics so all dashboard panels respect the selection - Map Cursor tool names (Shell, StrReplace, LS) to normalized categories ### Parser and sync details - Format detection: first non-empty line is checked for valid JSON to dispatch between JSONL and text parsers - JSONL parser reuses `ExtractTextContent` for assistant messages (handles `text`, `thinking`, `tool_use`, `tool_result` blocks) and `extractUserQuery` for user messages (strips `<user_query>` tags) - Discovery dedupes by basename when both `.txt` and `.jsonl` exist, preferring `.jsonl` - `FindCursorSourceFile` picks the newest file by mtime when both extensions exist - `DecodeCursorProjectDir` anchors marker matching to the home-directory position to avoid truncating project names containing marker words (e.g. `my-dev-tool`) - `CursorSessionID` derives extension-agnostic session IDs ### Content parser fix - Frontend content parser no longer false-matches `[Thinking]` / `[Bash]` markers inside inline code spans (backtick-quoted text in markdown) - Replaced regex-based inline code detection with a CommonMark-compliant scanner supporting arbitrary backtick delimiter lengths - Fenced code blocks at line start are correctly distinguished from inline triple-backtick spans ### Earlier review fixes - Fix `extractAssistantContent` dropping visible prose after marker blocks (added `isBlockBodyEnd` heuristic) - Fix `isContainedIn` rejecting `..`-prefixed child names and accepting `rel == "."` - Exclude empty agent names from `GetAgents` query - Return `[]` instead of `null` JSON when no agents match - Use black accent color for Cursor agent Co-authored-by: jfan-nux <jfan3@wellesley.edu> Closes #22 --------- Co-authored-by: jfan-nux <jfan3@wellesley.edu> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Summary
Supersedes #22 (squashed, rebased on main, with review fixes).
~/.cursor/projects/<project>/agent-transcripts/with a dedicated parser, file discovery, and sync engine wiring.txt(legacy plain-text) and.jsonl(Anthropic API message format) transcript files with automatic format detection/api/v1/agentsendpoint and agent filter dropdown in the dashboard header to filter sessions by sourceParser and sync details
ExtractTextContentfor assistant messages (handlestext,thinking,tool_use,tool_resultblocks) andextractUserQueryfor user messages (strips<user_query>tags).txtand.jsonlexist, preferring.jsonlFindCursorSourceFilepicks the newest file by mtime when both extensions existDecodeCursorProjectDiranchors marker matching to the home-directory position to avoid truncating project names containing marker words (e.g.my-dev-tool)CursorSessionIDderives extension-agnostic session IDsContent parser fix
[Thinking]/[Bash]markers inside inline code spans (backtick-quoted text in markdown)Earlier review fixes
extractAssistantContentdropping visible prose after marker blocks (addedisBlockBodyEndheuristic)isContainedInrejecting..-prefixed child names and acceptingrel == "."GetAgentsquery[]instead ofnullJSON when no agents matchCo-authored-by: jfan-nux jfan3@wellesley.edu
Closes #22