@@ -416,11 +416,37 @@ function captureSelection() {
416416 } ;
417417}
418418
419+ /**
420+ * Reveal the chat view for its side effect only, and never reject.
421+ *
422+ * `executeCommand` returns a Thenable, so a bare call in a void context turns any rejection into an
423+ * unhandled promise rejection in the extension host — noisy, and attributed to nothing in particular,
424+ * which is the part that makes it useless.
425+ *
426+ * Every caller here is a BACKGROUND reveal: the work it accompanies (a selection added, a session
427+ * resumed, a login launched) has already succeeded by the time this runs. Failing that work because
428+ * the panel would not come forward would be worse than the panel not coming forward.
429+ *
430+ * Logged, never swallowed. `.catch(() => {})` would hide the one failure that is genuinely hard to
431+ * diagnose — a chat surface that silently never appears — so `why` names the caller in the log.
432+ *
433+ * NOT for a command handler whose whole job IS the reveal: `levelcode.ai.focus` returns the thenable
434+ * instead, so VS Code reports the failure to the user who asked for it. See moveChatToSidebar.
435+ */
436+ function focusChatView ( why ) {
437+ return Promise . resolve ( vscode . commands . executeCommand ( 'levelcodeAi.chat.focus' ) )
438+ . then ( undefined , ( e ) => {
439+ const msg = String ( ( e && e . message ) || e ) ;
440+ console . warn ( '[levelcode-ai] chat.focus.failed' , { why, msg } ) ;
441+ dbg ( 'chat.focus.failed' , { why, msg } ) ;
442+ } ) ;
443+ }
444+
419445function addSelection ( ) {
420446 const sel = captureSelection ( ) ;
421447 if ( ! sel ) { vscode . window . showInformationMessage ( 'LevelCode AI: select some code first.' ) ; return ; }
422448 pendingContext = sel . block ;
423- vscode . commands . executeCommand ( 'levelcodeAi.chat.focus ') ;
449+ focusChatView ( 'addSelection ') ;
424450 post ( { type : 'context' , label : sel . label } ) ;
425451}
426452
@@ -465,7 +491,7 @@ async function addContext() {
465491 }
466492 }
467493 }
468- vscode . commands . executeCommand ( 'levelcodeAi.chat.focus ') ;
494+ focusChatView ( 'addContext ') ;
469495 postContextFiles ( ) ;
470496}
471497
@@ -1052,7 +1078,7 @@ async function resumeSession(id) {
10521078 post ( { type : 'sessionResumed' , id, title : ( r . entry && r . entry . title ) || 'Session' , note : r . note || '' , tier : r . plan && r . plan . tier , turns } ) ;
10531079 postContextFiles ( ) ;
10541080 refreshSessions ( ) ; // the resumed session bumps to the top — keep both surfaces current
1055- vscode . commands . executeCommand ( 'levelcodeAi.chat.focus ') ;
1081+ focusChatView ( 'resumeSession ') ;
10561082 dbg ( 'sessions.resumed' , { id, tier : r . plan && r . plan . tier , restored : agentMessages . length , shown : turns . length } ) ;
10571083}
10581084
@@ -2295,7 +2321,7 @@ async function openChatInEditor(opts) {
22952321 // resolveWebviewView then makes it live, and without this the chat would have no surface at all.
22962322 activeWebview = undefined ;
22972323 pendingTranscriptReplay = 'Back in the sidebar' ;
2298- vscode . commands . executeCommand ( 'levelcodeAi.chat.focus ') ;
2324+ focusChatView ( 'editorClosed ') ;
22992325 }
23002326 dbg ( 'chat.closedEditor' , { } ) ;
23012327 } ) ;
@@ -2432,7 +2458,7 @@ class SessionsViewProvider {
24322458 // The real session index for this workspace (empty on a fresh install — the view shows its
24332459 // own empty state). Posted to THIS view's webview, not the chat's.
24342460 case 'listSessions' : view . webview . postMessage ( { type : 'sessions' , entries : sessionList ( ) } ) ; break ;
2435- case 'newSession' : newChat ( ) ; vscode . commands . executeCommand ( 'levelcodeAi.chat.focus ') ; break ;
2461+ case 'newSession' : newChat ( ) ; focusChatView ( 'sessions.newSession ') ; break ;
24362462 case 'sessionAction' : await handleSessionAction ( msg . action , msg . id ) ; break ;
24372463 // Memory tab (§M3): list the recorded outcomes + facts; act on them; open the file.
24382464 case 'listMemory' : { const mm = sessionsManager ( ) ; view . webview . postMessage ( { type : 'memoryList' , items : mm ? mm . memoryItems ( ) : [ ] , facts : mm ? mm . factsList ( ) : [ ] } ) ; break ; }
@@ -2528,7 +2554,7 @@ async function postAccount(open) {
25282554// second login and no interceptable code ever travels through the custom scheme.
25292555async function handleLaunch ( ) {
25302556 dbg ( 'account.launch' , { } ) ;
2531- vscode . commands . executeCommand ( 'levelcodeAi.chat.focus ') ;
2557+ focusChatView ( 'account.launch ') ;
25322558 const token = ctx ? await ctx . secrets . get ( ACCOUNT_TOKEN_KEY ) : null ;
25332559 if ( ! token ) { await accountSignIn ( ) ; }
25342560}
0 commit comments