@@ -217,6 +217,60 @@ describe("connectGitHubCopilot", () => {
217217 expect ( vscode . authentication . getSession ) . toHaveBeenCalledTimes ( 1 )
218218 } )
219219
220+ describe ( "overlapping sign-in requests with different intent" , ( ) => {
221+ const session = ( label : string ) => ( { id : "s" , accessToken : "t" , scopes : [ ] , account : { id : "a" , label } } )
222+ const pendingSession = ( ) => {
223+ let finish : ( value : ReturnType < typeof session > ) => void = ( ) => { }
224+ const promise = new Promise ( ( resolve ) => ( finish = resolve ) ) as never
225+ return { promise, finish : ( label : string ) => finish ( session ( label ) ) }
226+ }
227+
228+ it ( "gives a Reconnect its own forced session instead of the pending plain sign-in's" , async ( ) => {
229+ const plain = pendingSession ( )
230+ const fresh = pendingSession ( )
231+ vi . mocked ( vscode . authentication . getSession )
232+ . mockImplementationOnce ( ( ) => plain . promise )
233+ . mockImplementationOnce ( ( ) => fresh . promise )
234+ vi . mocked ( vscode . lm . selectChatModels ) . mockResolvedValue ( [ ] )
235+ const onFresh = vi . fn ( )
236+
237+ const first = connectGitHubCopilot ( )
238+ const second = connectGitHubCopilot ( onFresh , true )
239+ plain . finish ( "Plain User" )
240+ fresh . finish ( "Fresh User" )
241+
242+ await expect ( first ) . resolves . toMatchObject ( { account : "Plain User" } )
243+ await expect ( second ) . resolves . toMatchObject ( { account : "Fresh User" } )
244+ expect ( vscode . authentication . getSession ) . toHaveBeenCalledTimes ( 2 )
245+ expect ( vscode . authentication . getSession ) . toHaveBeenLastCalledWith ( "github" , [ "user:email" ] , {
246+ forceNewSession : true ,
247+ clearSessionPreference : true ,
248+ } )
249+ expect ( onFresh ) . toHaveBeenCalledWith ( "Fresh User" )
250+ } )
251+
252+ it ( "still shares one attempt between concurrent Reconnect requests" , async ( ) => {
253+ const fresh = pendingSession ( )
254+ vi . mocked ( vscode . authentication . getSession ) . mockImplementationOnce ( ( ) => fresh . promise )
255+ vi . mocked ( vscode . lm . selectChatModels ) . mockResolvedValue ( [ ] )
256+
257+ const results = [ connectGitHubCopilot ( undefined , true ) , connectGitHubCopilot ( undefined , true ) ]
258+ fresh . finish ( "Fresh User" )
259+
260+ await Promise . all ( results )
261+ expect ( vscode . authentication . getSession ) . toHaveBeenCalledTimes ( 1 )
262+ } )
263+
264+ it ( "lets a failed attempt of one kind be retried without disturbing the other" , async ( ) => {
265+ vi . mocked ( vscode . authentication . getSession ) . mockRejectedValueOnce ( new Error ( "cancelled" ) )
266+ await expect ( connectGitHubCopilot ( undefined , true ) ) . rejects . toThrow ( "cancelled" )
267+
268+ vi . mocked ( vscode . authentication . getSession ) . mockResolvedValueOnce ( session ( "Retry User" ) )
269+ vi . mocked ( vscode . lm . selectChatModels ) . mockResolvedValue ( [ ] )
270+ await expect ( connectGitHubCopilot ( undefined , true ) ) . resolves . toMatchObject ( { account : "Retry User" } )
271+ } )
272+ } )
273+
220274 it ( "allows a new sign-in once the previous one has settled" , async ( ) => {
221275 vi . mocked ( vscode . authentication . getSession ) . mockRejectedValueOnce ( new Error ( "Sign-in cancelled" ) )
222276 await expect ( connectGitHubCopilot ( ) ) . rejects . toThrow ( "Sign-in cancelled" )
@@ -306,8 +360,8 @@ describe("Copilot model capabilities", () => {
306360 expect ( getVsCodeLmModelInfo ( model ) . supportsImages ) . toBe ( false )
307361 } )
308362
309- it ( "falls back to the curated catalog only when the host reports nothing" , ( ) => {
310- expect ( getVsCodeLmModelInfo ( liveModel ( { family : curatedFamily } ) ) . supportsImages ) . toBe ( true )
363+ it ( "does not borrow the catalog's vision flag for a live model the host reports nothing about " , ( ) => {
364+ expect ( getVsCodeLmModelInfo ( liveModel ( { family : curatedFamily } ) ) . supportsImages ) . toBeUndefined ( )
311365 } )
312366
313367 it ( "leaves vision unset rather than guessing when no source states it" , ( ) => {
@@ -337,11 +391,6 @@ describe("Copilot model capabilities", () => {
337391 handler . dispose ( )
338392 }
339393 } )
340-
341- it ( "does not set a tool-count limit, since consumers are only told whether tools are supported" , ( ) => {
342- const info = getVsCodeLmModelInfo ( liveModel ( { capabilities : { supportsToolCalling : true } } ) )
343- expect ( info . maxTools ) . toBeUndefined ( )
344- } )
345394 } )
346395
347396 describe ( "context window" , ( ) => {
0 commit comments