@@ -1082,35 +1082,60 @@ export class CopilotRemoteAgentManager extends Disposable {
1082
1082
} ;
1083
1083
}
1084
1084
1085
- private async streamNewLogContent ( stream : vscode . ChatResponseStream , newLogContent : string ) : Promise < boolean > {
1085
+ private async streamNewLogContent ( stream : vscode . ChatResponseStream , newLogContent : string ) : Promise < { hasStreamedContent : boolean ; hasSetupStepProgress : boolean } > {
1086
1086
try {
1087
1087
if ( ! newLogContent . trim ( ) ) {
1088
- return false ;
1088
+ return { hasStreamedContent : false , hasSetupStepProgress : false } ;
1089
1089
}
1090
1090
1091
1091
// Parse the new log content
1092
1092
const logChunks = parseSessionLogs ( newLogContent ) ;
1093
1093
let hasStreamedContent = false ;
1094
+ let hasSetupStepProgress = false ;
1094
1095
1095
1096
for ( const chunk of logChunks ) {
1096
1097
for ( const choice of chunk . choices ) {
1097
1098
const delta = choice . delta ;
1098
1099
1099
1100
if ( delta . role === 'assistant' ) {
1100
- if ( delta . content ) {
1101
- if ( ! delta . content . startsWith ( '<pr_title>' ) ) {
1102
- stream . markdown ( delta . content ) ;
1103
- hasStreamedContent = true ;
1101
+ // Handle special case for run_custom_setup_step
1102
+ if ( choice . finish_reason === 'tool_calls' && delta . tool_calls ?. length && delta . tool_calls [ 0 ] . function . name === 'run_custom_setup_step' ) {
1103
+ const toolCall = delta . tool_calls [ 0 ] ;
1104
+ let args : any = { } ;
1105
+ try {
1106
+ args = JSON . parse ( toolCall . function . arguments ) ;
1107
+ } catch {
1108
+ // fallback to empty args
1104
1109
}
1105
- }
1106
1110
1107
- if ( delta . tool_calls ) {
1108
- for ( const toolCall of delta . tool_calls ) {
1109
- const toolPart = this . createToolInvocationPart ( toolCall , delta . content || '' ) ;
1111
+ if ( delta . content && delta . content . trim ( ) ) {
1112
+ // Finished setup step - create/update tool part
1113
+ const toolPart = this . createToolInvocationPart ( toolCall , args . name || delta . content ) ;
1110
1114
if ( toolPart ) {
1111
1115
stream . push ( toolPart ) ;
1112
1116
hasStreamedContent = true ;
1113
1117
}
1118
+ } else {
1119
+ // Running setup step - just track progress
1120
+ hasSetupStepProgress = true ;
1121
+ Logger . appendLine ( `Setup step in progress: ${ args . name || 'Unknown step' } ` , CopilotRemoteAgentManager . ID ) ;
1122
+ }
1123
+ } else {
1124
+ if ( delta . content ) {
1125
+ if ( ! delta . content . startsWith ( '<pr_title>' ) ) {
1126
+ stream . markdown ( delta . content ) ;
1127
+ hasStreamedContent = true ;
1128
+ }
1129
+ }
1130
+
1131
+ if ( delta . tool_calls ) {
1132
+ for ( const toolCall of delta . tool_calls ) {
1133
+ const toolPart = this . createToolInvocationPart ( toolCall , delta . content || '' ) ;
1134
+ if ( toolPart ) {
1135
+ stream . push ( toolPart ) ;
1136
+ hasStreamedContent = true ;
1137
+ }
1138
+ }
1114
1139
}
1115
1140
}
1116
1141
}
@@ -1124,13 +1149,15 @@ export class CopilotRemoteAgentManager extends Disposable {
1124
1149
1125
1150
if ( hasStreamedContent ) {
1126
1151
Logger . appendLine ( `Streamed content (markdown or tool parts), progress should be cleared` , CopilotRemoteAgentManager . ID ) ;
1152
+ } else if ( hasSetupStepProgress ) {
1153
+ Logger . appendLine ( `Setup step progress detected, keeping progress indicator` , CopilotRemoteAgentManager . ID ) ;
1127
1154
} else {
1128
1155
Logger . appendLine ( `No actual content streamed, progress may still be showing` , CopilotRemoteAgentManager . ID ) ;
1129
1156
}
1130
- return hasStreamedContent ;
1157
+ return { hasStreamedContent, hasSetupStepProgress } ;
1131
1158
} catch ( error ) {
1132
1159
Logger . error ( `Error streaming new log content: ${ error } ` , CopilotRemoteAgentManager . ID ) ;
1133
- return false ;
1160
+ return { hasStreamedContent : false , hasSetupStepProgress : false } ;
1134
1161
}
1135
1162
}
1136
1163
@@ -1181,8 +1208,8 @@ export class CopilotRemoteAgentManager extends Disposable {
1181
1208
if ( sessionInfo . state !== 'in_progress' ) {
1182
1209
if ( logs . length > lastProcessedLength ) {
1183
1210
const newLogContent = logs . slice ( lastProcessedLength ) ;
1184
- const didStreamContent = await this . streamNewLogContent ( stream , newLogContent ) ;
1185
- if ( didStreamContent ) {
1211
+ const streamResult = await this . streamNewLogContent ( stream , newLogContent ) ;
1212
+ if ( streamResult . hasStreamedContent ) {
1186
1213
hasActiveProgress = false ;
1187
1214
}
1188
1215
}
@@ -1194,12 +1221,15 @@ export class CopilotRemoteAgentManager extends Disposable {
1194
1221
if ( logs . length > lastLogLength ) {
1195
1222
Logger . appendLine ( `New logs detected, attempting to stream content` , CopilotRemoteAgentManager . ID ) ;
1196
1223
const newLogContent = logs . slice ( lastProcessedLength ) ;
1197
- const didStreamContent = await this . streamNewLogContent ( stream , newLogContent ) ;
1224
+ const streamResult = await this . streamNewLogContent ( stream , newLogContent ) ;
1198
1225
lastProcessedLength = logs . length ;
1199
1226
1200
- if ( didStreamContent ) {
1227
+ if ( streamResult . hasStreamedContent ) {
1201
1228
Logger . appendLine ( `Content was streamed, resetting hasActiveProgress to false` , CopilotRemoteAgentManager . ID ) ;
1202
1229
hasActiveProgress = false ;
1230
+ } else if ( streamResult . hasSetupStepProgress ) {
1231
+ Logger . appendLine ( `Setup step progress detected, keeping progress active` , CopilotRemoteAgentManager . ID ) ;
1232
+ // Keep hasActiveProgress as is, don't reset it
1203
1233
} else {
1204
1234
Logger . appendLine ( `No content was streamed, keeping hasActiveProgress as ${ hasActiveProgress } ` , CopilotRemoteAgentManager . ID ) ;
1205
1235
}
@@ -1343,25 +1373,51 @@ export class CopilotRemoteAgentManager extends Disposable {
1343
1373
const delta = choice . delta ;
1344
1374
1345
1375
if ( delta . role === 'assistant' ) {
1346
- if ( delta . content ) {
1347
- if ( ! delta . content . startsWith ( '<pr_title>' ) ) {
1348
- currentResponseContent += delta . content ;
1376
+ // Handle special case for run_custom_setup_step
1377
+ if ( choice . finish_reason === 'tool_calls' && delta . tool_calls ?. length && delta . tool_calls [ 0 ] . function . name === 'run_custom_setup_step' ) {
1378
+ const toolCall = delta . tool_calls [ 0 ] ;
1379
+ let args : any = { } ;
1380
+ try {
1381
+ args = JSON . parse ( toolCall . function . arguments ) ;
1382
+ } catch {
1383
+ // fallback to empty args
1349
1384
}
1350
- }
1351
1385
1352
- if ( delta . tool_calls ) {
1353
- // Add any accumulated content as markdown first
1354
- if ( currentResponseContent . trim ( ) ) {
1355
- responseParts . push ( new vscode . ChatResponseMarkdownPart ( currentResponseContent . trim ( ) ) ) ;
1356
- currentResponseContent = '' ;
1357
- }
1386
+ // Ignore if delta.content is empty/undefined (running state)
1387
+ if ( delta . content && delta . content . trim ( ) ) {
1388
+ // Add any accumulated content as markdown first
1389
+ if ( currentResponseContent . trim ( ) ) {
1390
+ responseParts . push ( new vscode . ChatResponseMarkdownPart ( currentResponseContent . trim ( ) ) ) ;
1391
+ currentResponseContent = '' ;
1392
+ }
1358
1393
1359
- for ( const toolCall of delta . tool_calls ) {
1360
- const toolPart = this . createToolInvocationPart ( toolCall , delta . content || '' ) ;
1394
+ const toolPart = this . createToolInvocationPart ( toolCall , args . name || delta . content ) ;
1361
1395
if ( toolPart ) {
1362
1396
responseParts . push ( toolPart ) ;
1363
1397
}
1364
1398
}
1399
+ // Skip if content is empty (running state)
1400
+ } else {
1401
+ if ( delta . content ) {
1402
+ if ( ! delta . content . startsWith ( '<pr_title>' ) ) {
1403
+ currentResponseContent += delta . content ;
1404
+ }
1405
+ }
1406
+
1407
+ if ( delta . tool_calls ) {
1408
+ // Add any accumulated content as markdown first
1409
+ if ( currentResponseContent . trim ( ) ) {
1410
+ responseParts . push ( new vscode . ChatResponseMarkdownPart ( currentResponseContent . trim ( ) ) ) ;
1411
+ currentResponseContent = '' ;
1412
+ }
1413
+
1414
+ for ( const toolCall of delta . tool_calls ) {
1415
+ const toolPart = this . createToolInvocationPart ( toolCall , delta . content || '' ) ;
1416
+ if ( toolPart ) {
1417
+ responseParts . push ( toolPart ) ;
1418
+ }
1419
+ }
1420
+ }
1365
1421
}
1366
1422
}
1367
1423
}
0 commit comments