@@ -15,14 +15,15 @@ import { revive } from 'vs/base/common/marshalling';
15
15
import { StopWatch } from 'vs/base/common/stopwatch' ;
16
16
import { URI , UriComponents } from 'vs/base/common/uri' ;
17
17
import { localize } from 'vs/nls' ;
18
+ import { IConfigurationService } from 'vs/platform/configuration/common/configuration' ;
18
19
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey' ;
19
20
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation' ;
20
21
import { ILogService } from 'vs/platform/log/common/log' ;
21
22
import { Progress } from 'vs/platform/progress/common/progress' ;
22
23
import { IStorageService , StorageScope , StorageTarget } from 'vs/platform/storage/common/storage' ;
23
24
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry' ;
24
25
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace' ;
25
- import { ChatAgentLocation , IChatAgent , IChatAgentRequest , IChatAgentResult , IChatAgentService } from 'vs/workbench/contrib/chat/common/chatAgents' ;
26
+ import { ChatAgentLocation , IChatAgent , IChatAgentCommand , IChatAgentData , IChatAgentRequest , IChatAgentResult , IChatAgentService } from 'vs/workbench/contrib/chat/common/chatAgents' ;
26
27
import { CONTEXT_VOTE_UP_ENABLED } from 'vs/workbench/contrib/chat/common/chatContextKeys' ;
27
28
import { ChatModel , ChatRequestModel , ChatRequestRemovalReason , ChatWelcomeMessageModel , IChatModel , IChatRequestModel , IChatRequestVariableData , IChatResponseModel , IExportableChatData , ISerializableChatData , ISerializableChatsData , getHistoryEntriesFromModel , updateRanges } from 'vs/workbench/contrib/chat/common/chatModel' ;
28
29
import { ChatRequestAgentPart , ChatRequestAgentSubcommandPart , ChatRequestSlashCommandPart , IParsedChatRequest , chatAgentLeader , chatSubcommandLeader , getPromptText } from 'vs/workbench/contrib/chat/common/chatParserTypes' ;
@@ -111,7 +112,8 @@ export class ChatService extends Disposable implements IChatService {
111
112
@IChatVariablesService private readonly chatVariablesService : IChatVariablesService ,
112
113
@IChatAgentService private readonly chatAgentService : IChatAgentService ,
113
114
@IWorkbenchAssignmentService workbenchAssignmentService : IWorkbenchAssignmentService ,
114
- @IContextKeyService contextKeyService : IContextKeyService
115
+ @IContextKeyService contextKeyService : IContextKeyService ,
116
+ @IConfigurationService private readonly configurationService : IConfigurationService
115
117
) {
116
118
super ( ) ;
117
119
@@ -549,35 +551,60 @@ export class ChatService extends Disposable implements IChatService {
549
551
let rawResult : IChatAgentResult | null | undefined ;
550
552
let agentOrCommandFollowups : Promise < IChatFollowup [ ] | undefined > | undefined = undefined ;
551
553
554
+
552
555
if ( agentPart || ( defaultAgent && ! commandPart ) ) {
553
- const agent = ( agentPart ?. agent ?? defaultAgent ) ! ;
556
+ const prepareChatAgentRequest = async ( agent : IChatAgentData , command ?: IChatAgentCommand , chatRequest ?: ChatRequestModel ) => {
557
+ const initVariableData : IChatRequestVariableData = { variables : [ ] } ;
558
+ request = chatRequest ?? model . addRequest ( parsedRequest , initVariableData , attempt , agent , command , options ?. confirmation ) ;
559
+
560
+ // Variables may have changed if the agent and slash command changed, so resolve them again even if we already had a chatRequest
561
+ const variableData = await this . chatVariablesService . resolveVariables ( parsedRequest , options ?. attachedContext , model , progressCallback , token ) ;
562
+ model . updateRequest ( request , variableData ) ;
563
+ const promptTextResult = getPromptText ( request . message ) ;
564
+ const updatedVariableData = updateRanges ( variableData , promptTextResult . diff ) ; // TODO bit of a hack
565
+
566
+ return {
567
+ sessionId,
568
+ requestId : request . id ,
569
+ agentId : agent . id ,
570
+ message : promptTextResult . message ,
571
+ command : command ?. name ,
572
+ variables : updatedVariableData ,
573
+ enableCommandDetection,
574
+ attempt,
575
+ location,
576
+ locationData : options ?. locationData ,
577
+ acceptedConfirmationData : options ?. acceptedConfirmationData ,
578
+ rejectedConfirmationData : options ?. rejectedConfirmationData ,
579
+ } satisfies IChatAgentRequest ;
580
+ } ;
581
+
582
+ let detectedAgent : IChatAgentData | undefined ;
583
+ let detectedCommand : IChatAgentCommand | undefined ;
584
+ if ( this . configurationService . getValue ( 'chat.experimental.detectParticipant.enabled' ) && ! agentPart && ! commandPart ) {
585
+ // We have no agent or command to scope history with, pass the full history to the participant detection provider
586
+ const defaultAgentHistory = getHistoryEntriesFromModel ( model , defaultAgent . id ) ;
587
+
588
+ // Prepare the request object that we will send to the participant detection provider
589
+ const chatAgentRequest = await prepareChatAgentRequest ( defaultAgent , agentSlashCommandPart ?. command ) ;
590
+
591
+ const result = await this . chatAgentService . detectAgentOrCommand ( chatAgentRequest , defaultAgentHistory , { location } , token ) ;
592
+ if ( result ) {
593
+ // Update the response in the ChatModel to reflect the detected agent and command
594
+ request . response ?. setAgent ( result . agent , result . command ) ;
595
+ detectedAgent = result . agent ;
596
+ detectedCommand = result . command ;
597
+ }
598
+ }
599
+
600
+ const agent = ( detectedAgent ?? agentPart ?. agent ?? defaultAgent ) ! ;
601
+ const command = detectedCommand ?? agentSlashCommandPart ?. command ;
554
602
await this . extensionService . activateByEvent ( `onChatParticipant:${ agent . id } ` ) ;
555
- const history = getHistoryEntriesFromModel ( model , agentPart ?. agent . id ) ;
556
603
557
- const initVariableData : IChatRequestVariableData = { variables : [ ] } ;
558
- request = model . addRequest ( parsedRequest , initVariableData , attempt , agent , agentSlashCommandPart ?. command , options ?. confirmation ) ;
604
+ // Recompute history in case the agent or command changed
605
+ const history = getHistoryEntriesFromModel ( model , agent . id ) ;
606
+ const requestProps = await prepareChatAgentRequest ( agent , command , request /* Reuse the request object if we already created it for participant detection */ ) ;
559
607
completeResponseCreated ( ) ;
560
- const variableData = await this . chatVariablesService . resolveVariables ( parsedRequest , options ?. attachedContext , model , progressCallback , token ) ;
561
- model . updateRequest ( request , variableData ) ;
562
-
563
- const promptTextResult = getPromptText ( request . message ) ;
564
- const updatedVariableData = updateRanges ( variableData , promptTextResult . diff ) ; // TODO bit of a hack
565
-
566
- const requestProps : IChatAgentRequest = {
567
- sessionId,
568
- requestId : request . id ,
569
- agentId : agent . id ,
570
- message : promptTextResult . message ,
571
- command : agentSlashCommandPart ?. command . name ,
572
- variables : updatedVariableData ,
573
- enableCommandDetection,
574
- attempt,
575
- location,
576
- locationData : options ?. locationData ,
577
- acceptedConfirmationData : options ?. acceptedConfirmationData ,
578
- rejectedConfirmationData : options ?. rejectedConfirmationData ,
579
- } ;
580
-
581
608
const agentResult = await this . chatAgentService . invokeAgent ( agent . id , requestProps , progressCallback , history , token ) ;
582
609
rawResult = agentResult ;
583
610
agentOrCommandFollowups = this . chatAgentService . getFollowups ( agent . id , requestProps , agentResult , history , followupsCancelToken ) ;
0 commit comments