@@ -70,6 +70,9 @@ function summarizeSpan(event: CapturedLogEvent | undefined): Json {
7070 if ( typeof event . row . error === "string" ) {
7171 summary . error = event . row . error ;
7272 }
73+ if ( typeof summary . name === "string" && summary . name . startsWith ( "Agent:" ) ) {
74+ summary . name = "Agent: <subagent>" ;
75+ }
7376 return summary ;
7477}
7578
@@ -82,6 +85,42 @@ function findCursorTask(events: CapturedLogEvent[], operationName: string) {
8285 return findChildSpans ( events , "Cursor Agent" , operation ?. span . id ) . at ( - 1 ) ;
8386}
8487
88+ function findSubagentTool (
89+ events : CapturedLogEvent [ ] ,
90+ parentId : string | undefined ,
91+ ) {
92+ if ( ! parentId ) {
93+ return undefined ;
94+ }
95+ return [ ...events ]
96+ . reverse ( )
97+ . find (
98+ ( event ) =>
99+ event . span . type === "tool" &&
100+ event . span . parentIds . includes ( parentId ) &&
101+ [ "tool: Agent" , "tool: Task" , "tool: task" ] . includes (
102+ event . span . name ?? "" ,
103+ ) ,
104+ ) ;
105+ }
106+
107+ function findSubagentTask (
108+ events : CapturedLogEvent [ ] ,
109+ parentId : string | undefined ,
110+ ) {
111+ if ( ! parentId ) {
112+ return undefined ;
113+ }
114+ return [ ...events ]
115+ . reverse ( )
116+ . find (
117+ ( event ) =>
118+ event . span . type === "task" &&
119+ event . span . parentIds . includes ( parentId ) &&
120+ event . span . name ?. startsWith ( "Agent:" ) ,
121+ ) ;
122+ }
123+
85124function outputText ( event : CapturedLogEvent | undefined ) : string {
86125 return typeof event ?. output === "string" ? event . output : "" ;
87126}
@@ -95,10 +134,8 @@ function summarize(events: CapturedLogEvent[]): Json {
95134 "cursor-sdk-resume-conversation-operation" ,
96135 ) ;
97136 const tool = findAllSpans ( events , "tool: shell" ) . at ( - 1 ) ;
98- const subagentTask = events . find (
99- ( event ) =>
100- event . span . type === "task" && event . span . name ?. startsWith ( "Agent:" ) ,
101- ) ;
137+ const subagentTool = findSubagentTool ( events , streamTask ?. span . id ) ;
138+ const subagentTask = findSubagentTask ( events , subagentTool ?. span . id ) ;
102139
103140 return normalizeForSnapshot ( {
104141 conversation : {
@@ -119,6 +156,7 @@ function summarize(events: CapturedLogEvent[]): Json {
119156 findOperation ( events , "cursor-sdk-stream-operation" ) ,
120157 ) ,
121158 subagent_task : summarizeSpan ( subagentTask ) ,
159+ subagent_tool : summarizeSpan ( subagentTool ) ,
122160 task : summarizeSpan ( streamTask ) ,
123161 tool : summarizeSpan ( tool ) ,
124162 } ,
@@ -213,6 +251,23 @@ export function defineCursorSDKInstrumentationAssertions(options: {
213251 } ,
214252 ) ;
215253
254+ test ( "captures subagent spans when Cursor uses agents" , testConfig , ( ) => {
255+ const streamTask = findCursorTask ( events , "cursor-sdk-stream-operation" ) ;
256+ const subagentTool = findSubagentTool ( events , streamTask ?. span . id ) ;
257+ const subagentTask = findSubagentTask ( events , subagentTool ?. span . id ) ;
258+
259+ expect ( subagentTool ) . toBeDefined ( ) ;
260+ expect ( subagentTool ?. metadata ) . toMatchObject ( {
261+ "cursor_sdk.tool.status" : "completed" ,
262+ } ) ;
263+ expect ( subagentTask ) . toBeDefined ( ) ;
264+ expect ( subagentTask ?. span . rootId ) . toBe ( streamTask ?. span . rootId ) ;
265+ expect ( subagentTask ?. metadata ) . toMatchObject ( {
266+ "cursor_sdk.tool.status" : "completed" ,
267+ } ) ;
268+ expect ( subagentTask ?. output ) . toBeDefined ( ) ;
269+ } ) ;
270+
216271 test ( "preserves user onDelta/onStep callbacks" , testConfig , ( ) => {
217272 expect ( findLatestSpan ( events , "cursor-sdk-user-on-delta" ) ) . toBeDefined ( ) ;
218273 expect ( findLatestSpan ( events , "cursor-sdk-user-on-step" ) ) . toBeDefined ( ) ;
0 commit comments