@@ -43,13 +43,14 @@ import { builtinSlashSCommands, CopilotCLICommand, copilotCLICommands, ICopilotC
4343import { ICopilotCLISessionItem , ICopilotCLISessionService } from '../copilotcli/node/copilotcliSessionService' ;
4444import { buildMcpServerMappings } from '../copilotcli/node/mcpHandler' ;
4545import { ICopilotCLISessionTracker } from '../copilotcli/vscode-node/copilotCLISessionTracker' ;
46- import { ICopilotCLIChatSessionInitializer } from './copilotCLIChatSessionInitializer' ;
46+ import { ICopilotCLIChatSessionInitializer , SessionInitOptions } from './copilotCLIChatSessionInitializer' ;
4747import { convertReferenceToVariable } from './copilotCLIPromptReferences' ;
4848import { ICopilotCLITerminalIntegration , TerminalOpenLocation } from './copilotCLITerminalIntegration' ;
4949import { CopilotCloudSessionsProvider } from './copilotCloudSessionsProvider' ;
5050import { IPullRequestDetectionService } from './pullRequestDetectionService' ;
51- import { ISessionOptionGroupBuilder , OPEN_REPOSITORY_COMMAND_ID , toRepositoryOptionItem , toWorkspaceFolderOptionItem } from './sessionOptionGroupBuilder' ;
51+ import { getSelectedSessionOptions , ISessionOptionGroupBuilder , OPEN_REPOSITORY_COMMAND_ID , toRepositoryOptionItem , toWorkspaceFolderOptionItem } from './sessionOptionGroupBuilder' ;
5252import { ISessionRequestLifecycle } from './sessionRequestLifecycle' ;
53+ import { UNTRUSTED_FOLDER_MESSAGE } from './folderRepositoryManagerImpl' ;
5354
5455/**
5556 * ODO:
@@ -267,19 +268,22 @@ export class CopilotCLIChatSessionContentProvider extends Disposable implements
267268
268269 const newInputStates : WeakRef < vscode . ChatSessionInputState > [ ] = [ ] ;
269270 controller . getChatSessionInputState = async ( sessionResource , context , token ) => {
270- const groups = sessionResource ? await this . _optionGroupBuilder . buildExistingSessionInputStateGroups ( sessionResource , token ) : await this . _optionGroupBuilder . provideChatSessionProviderOptionGroups ( context . previousInputState ) ;
271- const state = controller . createChatSessionInputState ( groups ) ;
272- if ( ! sessionResource ) {
271+ const isExistingSession = sessionResource && ! this . sessionService . isNewSessionId ( SessionIdForCLI . parse ( sessionResource ) ) ;
272+ if ( isExistingSession ) {
273+ const groups = await this . _optionGroupBuilder . buildExistingSessionInputStateGroups ( sessionResource , token ) ;
274+ return controller . createChatSessionInputState ( groups ) ;
275+ } else {
276+ const groups = await this . _optionGroupBuilder . provideChatSessionProviderOptionGroups ( context . previousInputState ) ;
277+ const state = controller . createChatSessionInputState ( groups ) ;
273278 // Only wire dynamic updates for new sessions (existing sessions are fully locked).
274279 // Note: don't use the getChatSessionInputState token here — it's a one-shot token
275280 // that may be disposed by the time the user interacts with the dropdowns.
276281 newInputStates . push ( new WeakRef ( state ) ) ;
277-
278282 state . onDidChange ( ( ) => {
279283 void this . _optionGroupBuilder . handleInputStateChange ( state ) ;
280284 } ) ;
285+ return state ;
281286 }
282- return state ;
283287 } ;
284288
285289 // Refresh new-session dropdown groups when git or workspace state changes
@@ -304,8 +308,9 @@ export class CopilotCLIChatSessionContentProvider extends Disposable implements
304308 this . _register ( this . _workspaceService . onDidChangeWorkspaceFolders ( refreshActiveInputState ) ) ;
305309 }
306310
307- provideHandleOptionsChange ( ) {
308- // This is required for Controller.createChatSessionInputState.onDidChange event to work.
311+ public async updateInputStateAfterFolderSelection ( inputState : vscode . ChatSessionInputState , folderUri : vscode . Uri ) : Promise < void > {
312+ this . _optionGroupBuilder . setNewFolderForInputState ( inputState , folderUri ) ;
313+ await this . _optionGroupBuilder . rebuildInputState ( inputState , folderUri ) ;
309314 }
310315
311316 public async refreshSession ( refreshOptions : { reason : 'update' ; sessionId : string } | { reason : 'update' ; sessionIds : string [ ] } | { reason : 'delete' ; sessionId : string } ) : Promise < void > {
@@ -485,7 +490,6 @@ export class CopilotCLIChatSessionContentProvider extends Disposable implements
485490 requestHandler : undefined ,
486491 title : session . label ,
487492 activeResponseCallback : undefined ,
488- options : { } ,
489493 } ;
490494 } else {
491495 this . newSessions . delete ( resource ) ;
@@ -503,15 +507,23 @@ export class CopilotCLIChatSessionContentProvider extends Disposable implements
503507 this . _prDetectionService . detectPullRequest ( copilotcliSessionId ) ;
504508
505509 const folderRepo = await this . folderRepositoryManager . getFolderRepository ( copilotcliSessionId , undefined , token ) ;
506- const [ history , title ] = await Promise . all ( [
510+ const [ history , title , optionGroups ] = await Promise . all ( [
507511 this . getSessionHistory ( copilotcliSessionId , folderRepo , token ) ,
508512 this . customSessionTitleService . getCustomSessionTitle ( copilotcliSessionId ) ,
513+ this . _optionGroupBuilder . buildExistingSessionInputStateGroups ( resource , token ) ,
509514 ] ) ;
510515
516+ const options : Record < string , string | vscode . ChatSessionProviderOptionItem > = { } ;
517+ for ( const group of optionGroups ) {
518+ if ( group . selected ) {
519+ options [ group . id ] = { ...group . selected , locked : true } ;
520+ }
521+ }
522+
511523 return {
512524 title,
513525 history,
514- activeResponseCallback : undefined ,
526+ options ,
515527 requestHandler : undefined ,
516528 } ;
517529 }
@@ -536,9 +548,6 @@ export class CopilotCLIChatSessionContentProvider extends Disposable implements
536548 }
537549 }
538550
539- public async updateInputStateAfterFolderSelection ( inputState : vscode . ChatSessionInputState , folderUri : vscode . Uri ) : Promise < void > {
540- return this . _optionGroupBuilder . updateInputStateAfterFolderSelection ( inputState , folderUri ) ;
541- }
542551}
543552
544553export class CopilotCLIChatSessionParticipant extends Disposable {
@@ -721,7 +730,8 @@ export class CopilotCLIChatSessionParticipant extends Disposable {
721730 } ;
722731 const branchNamePromise = ( isNewSession && request . prompt && this . branchNameGenerator ) ? this . branchNameGenerator . generateBranchName ( fakeContext , token ) : Promise . resolve ( undefined ) ;
723732
724- const sessionResult = await this . getOrCreateSession ( request , chatSessionContext , stream , { branchName : branchNamePromise } , disposables , token ) ;
733+ const selectedOptions = getSelectedSessionOptions ( chatSessionContext . inputState ) ;
734+ const sessionResult = await this . getOrCreateSession ( request , chatSessionContext . chatSessionItem . resource , { ...selectedOptions , newBranch : branchNamePromise , stream } , disposables , token ) ;
725735 ( { session } = sessionResult ) ;
726736 const { model } = sessionResult ;
727737 if ( ! session || token . isCancellationRequested ) {
@@ -759,8 +769,8 @@ export class CopilotCLIChatSessionParticipant extends Disposable {
759769 }
760770 }
761771
762- private async getOrCreateSession ( request : vscode . ChatRequest , chatSessionContext : vscode . ChatSessionContext , stream : vscode . ChatResponseStream , options : { branchName : Promise < string | undefined > } , disposables : DisposableStore , token : vscode . CancellationToken ) : Promise < { session : IReference < ICopilotCLISession > | undefined ; isNewSession : boolean ; model : { model : string ; reasoningEffort ?: string } | undefined ; trusted : boolean } > {
763- const result = await this . sessionInitializer . getOrCreateSession ( request , chatSessionContext , stream , options , disposables , token ) ;
772+ private async getOrCreateSession ( request : vscode . ChatRequest , chatResource : vscode . Uri , options : SessionInitOptions , disposables : DisposableStore , token : vscode . CancellationToken ) : Promise < { session : IReference < ICopilotCLISession > | undefined ; isNewSession : boolean ; model : { model : string ; reasoningEffort ?: string } | undefined ; trusted : boolean } > {
773+ const result = await this . sessionInitializer . getOrCreateSession ( request , chatResource , options , disposables , token ) ;
764774 const { session, isNewSession, model, trusted } = result ;
765775 if ( ! session || token . isCancellationRequested ) {
766776 return { session : undefined , isNewSession, model, trusted } ;
@@ -816,7 +826,7 @@ export class CopilotCLIChatSessionParticipant extends Disposable {
816826 return summary ? `${ userPrompt } \n${ summary } ` : userPrompt ;
817827 } ) ( ) ;
818828
819- const { workspaceInfo, cancelled } = await this . sessionInitializer . initializeWorkingDirectory ( undefined , undefined , undefined , stream , request . toolInvocationToken , token ) ;
829+ const { workspaceInfo, cancelled } = await this . sessionInitializer . initializeWorkingDirectory ( undefined , { stream } , request . toolInvocationToken , token ) ;
820830
821831 if ( cancelled || token . isCancellationRequested ) {
822832 stream . markdown ( l10n . t ( 'Copilot CLI delegation cancelled.' ) ) ;
@@ -1107,10 +1117,7 @@ export function registerCLIChatCommands(
11071117 }
11081118
11091119 // Command handler receives `{ inputState, sessionResource }` context args (new API)
1110- disposableStore . add ( vscode . commands . registerCommand ( OPEN_REPOSITORY_COMMAND_ID , async ( contextArg ?: { inputState : vscode . ChatSessionInputState ; sessionResource : vscode . Uri | undefined } | vscode . Uri ) => {
1111- // Support both new API shape and legacy Uri shape for backward compat
1112- const inputState = contextArg && ! isUri ( contextArg ) ? contextArg . inputState : undefined ;
1113-
1120+ disposableStore . add ( vscode . commands . registerCommand ( OPEN_REPOSITORY_COMMAND_ID , async ( { inputState } : { inputState : vscode . ChatSessionInputState ; sessionResource : vscode . Uri | undefined } ) => {
11141121 let selectedFolderUri : Uri | undefined = undefined ;
11151122 const mruItems = await copilotCLIFolderMruService . getRecentlyUsedFolders ( CancellationToken . None ) ;
11161123
@@ -1202,11 +1209,15 @@ export function registerCLIChatCommands(
12021209 return ;
12031210 }
12041211
1205- // // We need to check trust now, as we need to determine whether this is a Git repo or not.
1206- // // Using the relevant services to check if its a git repo result in checking trust as well, might as well check now instead of complicating code later to handle both trusted and untrusted cases.
1207- // if (!(await vscode.workspace.isResourceTrusted(selectedFolderUri))) {
1208- // return;
1209- // }
1212+ // First check if user trusts the folder.
1213+ const trusted = await vscode . workspace . requestResourceTrust ( {
1214+ uri : selectedFolderUri ,
1215+ message : UNTRUSTED_FOLDER_MESSAGE
1216+ } ) ;
1217+ if ( ! trusted ) {
1218+ return ;
1219+ }
1220+
12101221
12111222 // Update inputState groups with newly selected folder and reload branches
12121223 if ( inputState ) {
0 commit comments