@@ -12,7 +12,7 @@ import { ConfigKey, IConfigurationService } from '../../../platform/configuratio
1212import { INativeEnvService } from '../../../platform/env/common/envService' ;
1313import { IFileSystemService } from '../../../platform/filesystem/common/fileSystemService' ;
1414import { IGitExtensionService } from '../../../platform/git/common/gitExtensionService' ;
15- import { getGitHubRepoInfoFromContext , IGitService , RepoContext } from '../../../platform/git/common/gitService' ;
15+ import { IGitService , RepoContext } from '../../../platform/git/common/gitService' ;
1616import { toGitUri } from '../../../platform/git/common/utils' ;
1717import { ILogService } from '../../../platform/log/common/logService' ;
1818import { IPromptsService , ParsedPromptFile } from '../../../platform/promptFiles/common/promptsService' ;
@@ -37,7 +37,7 @@ import { emptyWorkspaceInfo, getWorkingDirectory, isIsolationEnabled, IWorkspace
3737import { IChatDelegationSummaryService } from '../copilotcli/common/delegationSummaryService' ;
3838import { ICopilotCLIAgents , ICopilotCLIModels , ICopilotCLISDK } from '../copilotcli/node/copilotCli' ;
3939import { CopilotCLIPromptResolver } from '../copilotcli/node/copilotcliPromptResolver' ;
40- import { CopilotCLICommand , copilotCLICommands , ICopilotCLISession } from '../copilotcli/node/copilotcliSession' ;
40+ import { builtinSlashSCommands , CopilotCLICommand , copilotCLICommands , ICopilotCLISession } from '../copilotcli/node/copilotcliSession' ;
4141import { ICopilotCLISessionItem , ICopilotCLISessionService } from '../copilotcli/node/copilotcliSessionService' ;
4242import { ICopilotCLISessionTracker } from '../copilotcli/vscode-node/copilotCLISessionTracker' ;
4343import { isCopilotCLIPlanAgent } from './copilotCLIPlanAgentProvider' ;
@@ -1081,6 +1081,9 @@ export class CopilotCLIChatSessionParticipant extends Disposable {
10811081 : { prompt : `/${ request . command } ` } ;
10821082 await session . object . handleRequest ( request , input , [ ] , modelId , authInfo , token ) ;
10831083 await this . commitWorktreeChangesIfNeeded ( session . object , token ) ;
1084+ } else if ( request . prompt && Object . values ( builtinSlashSCommands ) . includes ( request . prompt ) ) {
1085+ await session . object . handleRequest ( request , { prompt : request . prompt } , [ ] , modelId , authInfo , token ) ;
1086+ await this . commitWorktreeChangesIfNeeded ( session . object , token ) ;
10841087 } else {
10851088 // Construct the full prompt with references to be sent to CLI.
10861089 const plan = request . modeInstructions2 ? isCopilotCLIPlanAgent ( request . modeInstructions2 ) : false ;
@@ -1204,6 +1207,38 @@ export class CopilotCLIChatSessionParticipant extends Disposable {
12041207 await this . workspaceFolderService . handleRequestCompleted ( workingDirectory ) ;
12051208 }
12061209 }
1210+
1211+ await this . handlePullRequestCreated ( session ) ;
1212+ }
1213+
1214+ private async handlePullRequestCreated ( session : ICopilotCLISession ) : Promise < void > {
1215+ const prUrl = session . createdPullRequestUrl ;
1216+ if ( ! prUrl ) {
1217+ return ;
1218+ }
1219+
1220+ try {
1221+ const worktreeProperties = await this . copilotCLIWorktreeManagerService . getWorktreeProperties ( session . sessionId ) ;
1222+ if ( worktreeProperties && worktreeProperties . version === 2 ) {
1223+ await this . copilotCLIWorktreeManagerService . setWorktreeProperties ( session . sessionId , {
1224+ ...worktreeProperties ,
1225+ pullRequestUrl : prUrl ,
1226+ changes : undefined ,
1227+ } ) ;
1228+ this . sessionItemProvider . notifySessionsChange ( ) ;
1229+ }
1230+ } catch ( error ) {
1231+ this . logService . error ( `Failed to persist pull request metadata: ${ error instanceof Error ? error . message : String ( error ) } ` ) ;
1232+ }
1233+
1234+ const openAction = l10n . t ( 'Open Pull Request' ) ;
1235+ const selection = await vscode . window . showInformationMessage (
1236+ l10n . t ( 'Pull request created successfully.' ) ,
1237+ openAction
1238+ ) ;
1239+ if ( selection === openAction ) {
1240+ await vscode . env . openExternal ( vscode . Uri . parse ( prUrl ) ) ;
1241+ }
12071242 }
12081243
12091244 /**
@@ -1845,9 +1880,6 @@ export function registerCLIChatCommands(
18451880 const resource = sessionItemOrResource instanceof vscode . Uri
18461881 ? sessionItemOrResource
18471882 : sessionItemOrResource ?. resource ;
1848- const sessionLabel = sessionItemOrResource instanceof vscode . Uri
1849- ? undefined
1850- : sessionItemOrResource ?. label ;
18511883
18521884 if ( ! resource ) {
18531885 return ;
@@ -1857,111 +1889,18 @@ export function registerCLIChatCommands(
18571889 const sessionId = SessionIdForCLI . parse ( resource ) ;
18581890 const worktreeProperties = await copilotCLIWorktreeManagerService . getWorktreeProperties ( sessionId ) ;
18591891 if ( ! worktreeProperties || worktreeProperties . version !== 2 ) {
1860- throw new Error ( 'Create pull request is only supported for v2 worktree sessions' ) ;
1861- }
1862-
1863- // Get GitHub repo info from the repository
1864- const repoContext = await gitService . getRepository ( vscode . Uri . file ( worktreeProperties . repositoryPath ) , true ) ;
1865- if ( ! repoContext ) {
1866- throw new Error ( 'Unable to find repository' ) ;
1867- }
1868- const repoInfo = getGitHubRepoInfoFromContext ( repoContext ) ;
1869- if ( ! repoInfo ) {
1870- throw new Error ( 'Unable to determine GitHub repository owner and name' ) ;
1871- }
1872-
1873- const title = sessionLabel || `Merging ${ worktreeProperties . branchName } to ${ worktreeProperties . baseBranchName } ` ;
1874- // Push the worktree branch to the remote before creating the PR
1875- const worktreeUri = vscode . Uri . file ( worktreeProperties . worktreePath ) ;
1876- const gitApi = gitExtensionService . getExtensionApi ( ) ;
1877- const worktreeRepo = gitApi ?. getRepository ( worktreeUri ) ;
1878- if ( ! worktreeRepo ) {
1879- throw new Error ( 'Unable to find git repository for worktree' ) ;
1880- }
1881-
1882- // Determine the remote name from repoContext instead of hard-coding 'origin'
1883- let remoteName = repoContext . upstreamRemote ;
1884- if ( ! remoteName && repoInfo . remoteUrl && repoContext . remoteFetchUrls ) {
1885- for ( let i = 0 ; i < repoContext . remotes . length ; i ++ ) {
1886- if ( repoContext . remoteFetchUrls [ i ] === repoInfo . remoteUrl ) {
1887- remoteName = repoContext . remotes [ i ] ;
1888- break ;
1889- }
1890- }
1891- }
1892- if ( ! remoteName ) {
1893- remoteName = 'origin' ;
1894- }
1895- await worktreeRepo . push ( remoteName , worktreeProperties . branchName , true ) ;
1896-
1897- // Find the MCP tool by matching against registered tool names
1898- const createPrTool = toolsService . tools . find ( t => t . name . endsWith ( 'create_pull_request' ) && t . name . includes ( 'github' ) ) ;
1899- if ( ! createPrTool ) {
1900- throw new Error ( 'GitHub MCP server create_pull_request tool not found. Please ensure the GitHub MCP server is configured and running.' ) ;
1901- }
1902-
1903- const result = await toolsService . invokeTool ( createPrTool . name , {
1904- toolInvocationToken : undefined ,
1905- input : {
1906- owner : repoInfo . id . org ,
1907- repo : repoInfo . id . repo ,
1908- title,
1909- head : worktreeProperties . branchName ,
1910- base : worktreeProperties . baseBranchName ,
1911- body : '' ,
1912- } ,
1913- } , CancellationToken . None ) ;
1914-
1915- // Extract the PR URL from the tool result
1916- let prUrl : string | undefined ;
1917- for ( const part of result . content ) {
1918- if ( part instanceof vscode . LanguageModelTextPart ) {
1919- try {
1920- const parsed = JSON . parse ( part . value ) ;
1921- if ( parsed . url ) {
1922- prUrl = parsed . url ;
1923- break ;
1924- }
1925- } catch {
1926- // Not JSON, ignore
1927- }
1928- } else if ( part instanceof vscode . LanguageModelDataPart && part . mimeType === 'application/json' ) {
1929- try {
1930- const decoded = new TextDecoder ( ) . decode ( part . data ) ;
1931- const parsed = JSON . parse ( decoded ) ;
1932- if ( parsed . url ) {
1933- prUrl = parsed . url ;
1934- break ;
1935- }
1936- } catch {
1937- // Not valid JSON data, ignore
1938- }
1939- }
1940- }
1941-
1942- if ( prUrl ) {
1943- await copilotCLIWorktreeManagerService . setWorktreeProperties ( sessionId , {
1944- ...worktreeProperties ,
1945- pullRequestUrl : prUrl ,
1946- changes : undefined ,
1947- } ) ;
1948- copilotcliSessionItemProvider . notifySessionsChange ( ) ;
1949-
1950- const openAction = l10n . t ( 'Open Pull Request' ) ;
1951- const selection = await vscode . window . showInformationMessage (
1952- l10n . t ( 'Pull request created successfully.' ) ,
1953- openAction
1954- ) ;
1955- if ( selection === openAction ) {
1956- await vscode . env . openExternal ( vscode . Uri . parse ( prUrl ) ) ;
1957- }
1958- } else {
1959- throw new Error ( 'Unable to extract pull request URL from create_pull_request tool result' ) ;
1892+ vscode . window . showErrorMessage ( l10n . t ( 'Creating a pull request is only supported for worktree-based sessions.' ) ) ;
1893+ return ;
19601894 }
19611895 } catch ( error ) {
1962- logService . error ( `Failed to create pull request : ${ error instanceof Error ? error . message : String ( error ) } ` ) ;
1963- vscode . window . showErrorMessage ( l10n . t ( 'Failed to create pull request' ) , { modal : true } ) ;
1896+ logService . error ( `Failed to check worktree properties for createPR : ${ error instanceof Error ? error . message : String ( error ) } ` ) ;
1897+ return ;
19641898 }
1899+
1900+ await vscode . commands . executeCommand ( 'workbench.action.chat.openSessionWithPrompt.copilotcli' , {
1901+ resource,
1902+ prompt : builtinSlashSCommands . createPr ,
1903+ } ) ;
19651904 } ) ) ;
19661905
19671906 disposableStore . add ( vscode . commands . registerCommand ( 'github.copilot.chat.openPullRequestCopilotCLIAgentSession.openPR' , async ( sessionItemOrResource ?: vscode . ChatSessionItem | vscode . Uri ) => {
0 commit comments