Add Cursor agent support on new agent interface#392
Add Cursor agent support on new agent interface#392squishykid wants to merge 13 commits intomainfrom
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
Comment @cursor review or bugbot run to trigger another review on this PR
There was a problem hiding this comment.
Pull request overview
Adds Cursor as a first-class agent implementation in the refactored agent/hook architecture, enabling lifecycle event dispatch, hook installation into .cursor/hooks.json, and reuse of the existing JSONL transcript + incremental checkpoint flow.
Changes:
- Introduces
cmd/entire/cli/agent/cursor/implementing Cursor agent identity, transcript handling, lifecycle event mapping, and hook management. - Wires Cursor into hook command registration/dispatch (including PostTodo incremental checkpoints) and agent registry constants.
- Updates summarization to treat Cursor transcripts as JSONL (shared path with Claude Code).
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| cmd/entire/cli/summarize/summarize.go | Routes Cursor to the JSONL condensed-transcript path. |
| cmd/entire/cli/setup.go | Adds Cursor to “Preview” messaging and to global hook removal. |
| cmd/entire/cli/hooks_cursor_posttodo.go | Adds Cursor PostTodo handler delegating to Claude’s incremental checkpoint logic. |
| cmd/entire/cli/hooks_cmd.go | Ensures Cursor agent package is registered via blank import. |
| cmd/entire/cli/hook_registry.go | Adds Cursor PostTodo dispatch path alongside Claude’s. |
| cmd/entire/cli/agent/registry.go | Adds AgentNameCursor / AgentTypeCursor constants. |
| cmd/entire/cli/agent/cursor/types.go | Defines Cursor hooks.json structures + hook input raw types with conversation_id fallback. |
| cmd/entire/cli/agent/cursor/lifecycle.go | Implements ParseHookEvent mapping Cursor hooks to normalized lifecycle events + transcript analyzer methods. |
| cmd/entire/cli/agent/cursor/lifecycle_test.go | Adds unit tests for lifecycle mapping and conversation_id fallback behavior. |
| cmd/entire/cli/agent/cursor/hooks.go | Implements install/uninstall/detection for .cursor/hooks.json with matcher-based tool hooks. |
| cmd/entire/cli/agent/cursor/hooks_test.go | Adds unit tests for hook install/uninstall/idempotency/preservation behavior. |
| cmd/entire/cli/agent/cursor/cursor.go | Implements Cursor agent identity, legacy hook parsing, session I/O, transcript chunking, and modified-file extraction. |
905aeb4 to
2abcac1
Compare
dd067cd to
c072c01
Compare
950ba73 to
4ae0a70
Compare
- Remove dead code: ParseHookInput, GetHookConfigPath, SupportsHooks (zero callers) - Remove incorrect extractModifiedFiles/FileModificationTools (Cursor transcript lacks tool_use blocks) - Fix FormatResumeCommand: return human-readable instruction instead of invalid CLI command - Document transcript.Line.Role field (Cursor uses "role", Claude Code uses "type") - Add shared transcript.ExtractModifiedFiles utility to transcript package - ReadSession no longer populates ModifiedFiles (relies on git status instead) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Entire-Checkpoint: cd204de06bd2
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Entire-Checkpoint: d5891c95e5a4
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Entire-Checkpoint: 86d61e18931c
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Cursor JSONL uses "role" instead of "type" to distinguish user/assistant messages. Normalize role→type during transcript parsing so all downstream consumers (summarize, explain) work uniformly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Entire-Checkpoint: fac4ff295b71
| func TestBuildCondensedTranscriptFromBytes_CursorRoleBasedJSONL(t *testing.T) { | ||
| // Cursor transcripts use "role" instead of "type" and wrap user text in <user_query> tags. | ||
| // The transcript parser normalizes role→type, so condensation should work. | ||
| cursorJSONL := `{"role":"user","message":{"content":[{"type":"text","text":"<user_query>\nhello\n</user_query>"}]}} | ||
| {"role":"assistant","message":{"content":[{"type":"text","text":"Hi there!"}]}} | ||
| {"role":"user","message":{"content":[{"type":"text","text":"<user_query>\nadd one to a file and commit\n</user_query>"}]}} | ||
| {"role":"assistant","message":{"content":[{"type":"text","text":"Created one.txt with one and committed."}]}} | ||
| ` |
There was a problem hiding this comment.
Cursor user prompts are wrapped in <user_query>...</user_query> (as noted in this test), but the current extraction path (transcript.ExtractUserContent → textutil.StripIDEContextTags) does not strip those tags. This means summarized/condensed user prompts will likely include the wrapper markup, which will leak into intent extraction and summaries. Consider stripping Cursor’s <user_query> wrapper during user-content extraction (either by extending StripIDEContextTags or adding a Cursor-specific cleanup step) and tightening this test to assert the tags are removed (not just that it contains "hello").
Entire-Checkpoint: f15cd73bd481
| if raw.ToolResponse.AgentID != "" { | ||
| event.SubagentID = raw.ToolResponse.AgentID | ||
| } | ||
| // TODO "tool_output": "{\"status\":\"success\",\"agentId\":\"3211cc34-8d8f-42de-9dcf-c19625b17566\",\"durationMs\":7901,\"messageCount\":1,\"toolCallCount\":1}", |
There was a problem hiding this comment.
need to fix sub-agent extraction
Summary
Adds Cursor as a supported agent with full hook lifecycle, transcript storage, and checkpoint integration.
New: Cursor agent package (
agent/cursor/)types.go— Cursor-specific types withconversation_idfallback for session IDscursor.go— Agent implementation with JSONL transcript storage (ReadSession, WriteSession, ChunkTranscript, ReassembleTranscript)lifecycle.go—ParseHookEventmapping 7 Cursor hooks to normalized lifecycle events, plusReadTranscripthooks.go— Hook install/uninstall for.cursor/hooks.jsonwith unknown field preservationhooks_test.go— 11 hook tests (install, idempotent, force, preserve existing/unknown fields, uninstall)lifecycle_test.go— 15 lifecycle tests covering all hook types, edge cases, and ReadTranscriptcursor_test.go— 30 tests covering identity, session storage (ReadSession/WriteSession round-trips), chunking, DetectPresence, and sanitizePathForCursorModified
setup.go— UsesIsPreview()for preview labels, addsremoveAgentHooksfor Cursor uninstallhooks_cmd.go— Blank import for cursor packageinit()registrationtranscript/types.go— DocumentedRolefield (Cursor usesrole, Claude Code usestype)transcript/parse.go— Added sharedExtractModifiedFilesutility for agents with tool_use blocksDesign decisions
tool_useblocks, so modified file detection relies on git status instead of transcript parsingTest plan
mise run test)mise run test:integration)mise run lint)go build ./cmd/entire/)entire enable --agent cursorcreates.cursor/hooks.jsonentire disableremoves hooks from.cursor/hooks.jsonentire hooks cursor --helpshows all hook verbs🤖 Generated with Claude Code