@@ -156,7 +156,10 @@ public MainWindow()
156156 _cli . Command = _settings . Command ;
157157 _cli . UseApiKey = _settings . UseApiKey ;
158158 _cli . ApiKey = string . IsNullOrWhiteSpace ( _settings . ApiKey ) ? null : _settings . ApiKey ;
159- AppendCliLog ( $ "System: Loaded CLI settings: '{ _cli . Command } '{ ( string . IsNullOrWhiteSpace ( _settings . SelectedProfile ) ? "" : " • profile=" + _settings . SelectedProfile ) } ") ;
159+ _cli . UseWsl = OperatingSystem . IsWindows ( ) && _settings . UseWsl ;
160+ var loadProfileSuffix = string . IsNullOrWhiteSpace ( _settings . SelectedProfile ) ? string . Empty : " • profile=" + _settings . SelectedProfile ;
161+ var loadWslSuffix = _cli . UseWsl ? " • WSL" : string . Empty ;
162+ AppendCliLog ( $ "System: Loaded CLI settings: '{ _cli . Command } '{ loadProfileSuffix } { loadWslSuffix } ") ;
160163 SelectedProfile = _settings . SelectedProfile ;
161164 _currentModel = TryExtractModelFromArgs ( _cli . AdditionalArgs ) ;
162165 _verboseLogging = _settings . VerboseLoggingEnabled ;
@@ -1247,7 +1250,16 @@ private async Task CheckCodexVersionAsync()
12471250 var latest = CodexVersionService . TryReadLatestVersion ( ) ;
12481251 if ( ! latest . Ok || string . IsNullOrWhiteSpace ( latest . Version ) ) return ;
12491252
1250- var installed = await CodexVersionService . TryGetInstalledVersionAsync ( _cli . Command , CurrentWorkspacePath ?? Directory . GetCurrentDirectory ( ) ) ;
1253+ ( bool Ok , string ? Version , string ? Error ) installed ;
1254+ if ( _cli . UseWsl && OperatingSystem . IsWindows ( ) )
1255+ {
1256+ var psi = await _cli . BuildProcessStartInfoAsync ( CurrentWorkspacePath ?? Directory . GetCurrentDirectory ( ) , new [ ] { "--version" } , redirectStdIn : false ) ;
1257+ installed = await CodexVersionService . TryGetInstalledVersionAsync ( psi ) ;
1258+ }
1259+ else
1260+ {
1261+ installed = await CodexVersionService . TryGetInstalledVersionAsync ( _cli . Command , CurrentWorkspacePath ?? Directory . GetCurrentDirectory ( ) ) ;
1262+ }
12511263 if ( ! installed . Ok || string . IsNullOrWhiteSpace ( installed . Version ) ) return ;
12521264
12531265 if ( CodexVersionService . IsNewer ( latest . Version , installed . Version ) )
@@ -2168,6 +2180,7 @@ private async Task RestartCliAsync()
21682180 _cli . AdditionalArgs = composed ;
21692181
21702182 // Proactive authentication: API key login or interactive chat login
2183+ // 1) If user provided API key in settings, use it non-interactively
21712184 if ( _cli . UseApiKey && ! string . IsNullOrWhiteSpace ( _cli . ApiKey ) )
21722185 {
21732186 try
@@ -2196,29 +2209,41 @@ private async Task RestartCliAsync()
21962209 }
21972210 else
21982211 {
2199- try
2212+ // 2) No API key in settings: probe ~/.codex/auth.json
2213+ var authProbe = Services . CodexAuthService . ProbeAuth ( ) ;
2214+ if ( authProbe . Exists && authProbe . HasTokens )
22002215 {
2201- AppendCliLog ( "System: Authenticating CLI via 'codex login'…" ) ;
2202- var exit = await RunCodexAuthLoginAsync ( ) ;
2203- if ( exit == 0 )
2216+ // Tokens present — assume already authenticated; skip proactive login
2217+ AppendCliLog ( "System: Found existing Codex auth tokens; skipping login." ) ;
2218+ }
2219+ else
2220+ {
2221+ // Regardless of API key present in auth.json, settings dictate NOT to use API key.
2222+ // Fall back to interactive login to avoid implicit API key usage.
2223+ try
22042224 {
2205- AppendCliLog ( "System: CLI authenticated (chat login)." ) ;
2225+ AppendCliLog ( "System: Authenticating CLI via 'codex login'…" ) ;
2226+ var exit = await RunCodexAuthLoginAsync ( ) ;
2227+ if ( exit == 0 )
2228+ {
2229+ AppendCliLog ( "System: CLI authenticated (chat login)." ) ;
2230+ }
2231+ else
2232+ {
2233+ AppendCliLog ( $ "System: CLI login failed (exit { exit } ).") ;
2234+ _cli . AdditionalArgs = prevArgs ; // restore before abort
2235+ SessionStatus = "error" ;
2236+ return ;
2237+ }
22062238 }
2207- else
2239+ catch ( Exception ex )
22082240 {
2209- AppendCliLog ( $ "System: CLI login failed (exit { exit } )." ) ;
2241+ AppendCliLog ( "System: CLI login error: " + ex . Message ) ;
22102242 _cli . AdditionalArgs = prevArgs ; // restore before abort
22112243 SessionStatus = "error" ;
22122244 return ;
22132245 }
22142246 }
2215- catch ( Exception ex )
2216- {
2217- AppendCliLog ( "System: CLI login error: " + ex . Message ) ;
2218- _cli . AdditionalArgs = prevArgs ; // restore before abort
2219- SessionStatus = "error" ;
2220- return ;
2221- }
22222247 }
22232248
22242249 await _cli . StartAsync ( CurrentWorkspacePath , CancellationToken . None ) ;
@@ -2489,24 +2514,15 @@ private async Task HandleUnauthorizedAsync()
24892514
24902515 private async Task < int > RunCodexAuthLoginAsync ( )
24912516 {
2492- var cwd = HasWorkspace ? CurrentWorkspacePath : Directory . GetCurrentDirectory ( ) ;
2517+ var cwd = HasWorkspace && ! string . IsNullOrWhiteSpace ( CurrentWorkspacePath )
2518+ ? CurrentWorkspacePath !
2519+ : Directory . GetCurrentDirectory ( ) ;
24932520
2494- async Task < int > RunAsync ( string args )
2521+ async Task < int > RunAsync ( params string [ ] commandArgs )
24952522 {
24962523 try
24972524 {
2498- var psi = new ProcessStartInfo
2499- {
2500- FileName = _cli . Command ,
2501- Arguments = args ,
2502- WorkingDirectory = cwd ! ,
2503- RedirectStandardOutput = true ,
2504- RedirectStandardError = true ,
2505- RedirectStandardInput = true ,
2506- UseShellExecute = false ,
2507- CreateNoWindow = true
2508- } ;
2509-
2525+ var psi = await _cli . BuildProcessStartInfoAsync ( cwd , commandArgs , redirectStdIn : true ) ;
25102526 using var p = new Process { StartInfo = psi , EnableRaisingEvents = true } ;
25112527
25122528 void HandleLine ( string ? line )
@@ -2569,31 +2585,20 @@ void HandleLine(string? line)
25692585 }
25702586
25712587 // Try modern subcommand first, then fallback
2572- var exit = await RunAsync ( "auth login" ) ;
2588+ var exit = await RunAsync ( "auth" , " login") ;
25732589 if ( exit == 0 ) return exit ;
25742590 // Fallback: some versions may use `login`
25752591 return await RunAsync ( "login" ) ;
25762592 }
25772593
25782594 private async Task < int > RunCodexLoginWithApiKeyAsync ( string apiKey )
25792595 {
2580- var cwd = HasWorkspace ? CurrentWorkspacePath : Directory . GetCurrentDirectory ( ) ;
2596+ var cwd = HasWorkspace && ! string . IsNullOrWhiteSpace ( CurrentWorkspacePath )
2597+ ? CurrentWorkspacePath !
2598+ : Directory . GetCurrentDirectory ( ) ;
25812599 try
25822600 {
2583- var psi = new ProcessStartInfo
2584- {
2585- FileName = _cli . Command ,
2586- WorkingDirectory = cwd ! ,
2587- RedirectStandardOutput = true ,
2588- RedirectStandardError = true ,
2589- UseShellExecute = false ,
2590- CreateNoWindow = true
2591- } ;
2592-
2593- // Prefer: codex login --api-key <key>
2594- psi . ArgumentList . Add ( "login" ) ;
2595- psi . ArgumentList . Add ( "--api-key" ) ;
2596- psi . ArgumentList . Add ( apiKey ) ;
2601+ var psi = await _cli . BuildProcessStartInfoAsync ( cwd , new [ ] { "login" , "--api-key" , apiKey } , redirectStdIn : false ) ;
25972602
25982603 using ( var p = new Process { StartInfo = psi , EnableRaisingEvents = true } )
25992604 {
@@ -2607,19 +2612,7 @@ private async Task<int> RunCodexLoginWithApiKeyAsync(string apiKey)
26072612 }
26082613
26092614 // Fallback: codex auth login --api-key <key>
2610- var psi2 = new ProcessStartInfo
2611- {
2612- FileName = _cli . Command ,
2613- WorkingDirectory = cwd ! ,
2614- RedirectStandardOutput = true ,
2615- RedirectStandardError = true ,
2616- UseShellExecute = false ,
2617- CreateNoWindow = true
2618- } ;
2619- psi2 . ArgumentList . Add ( "auth" ) ;
2620- psi2 . ArgumentList . Add ( "login" ) ;
2621- psi2 . ArgumentList . Add ( "--api-key" ) ;
2622- psi2 . ArgumentList . Add ( apiKey ) ;
2615+ var psi2 = await _cli . BuildProcessStartInfoAsync ( cwd , new [ ] { "auth" , "login" , "--api-key" , apiKey } , redirectStdIn : false ) ;
26232616
26242617 using var p2 = new Process { StartInfo = psi2 , EnableRaisingEvents = true } ;
26252618 p2 . OutputDataReceived += ( _ , ev ) => { if ( ! string . IsNullOrWhiteSpace ( ev . Data ) ) AppendCliLog ( ev . Data ! ) ; } ;
@@ -2728,13 +2721,19 @@ private async void OnOpenCliSettingsClick(object? sender, Avalonia.Interactivity
27282721 ShowMcpResultsInLog = _settings . ShowMcpResultsInLog ,
27292722 ShowMcpResultsOnlyWhenNoEdits = _settings . ShowMcpResultsOnlyWhenNoEdits ,
27302723 Profiles = Services . CodexConfigService . TryGetProfiles ( ) ,
2731- SelectedProfile = _settings . SelectedProfile
2724+ SelectedProfile = _settings . SelectedProfile ,
2725+ UseWsl = _cli . UseWsl ,
2726+ CanUseWsl = OperatingSystem . IsWindows ( )
27322727 } ;
27332728 dialog . DataContext = vm ;
27342729 var result = await dialog . ShowDialog < CliSettings ? > ( this ) ;
27352730 if ( result is null ) return ;
27362731 _cli . Command = result . Command ;
2737- AppendCliLog ( $ "System: CLI settings updated: '{ _cli . Command } '{ ( string . IsNullOrWhiteSpace ( result . SelectedProfile ) ? "" : " • profile=" + result . SelectedProfile ) } (--proto enabled)") ;
2732+ var profileSuffix = string . IsNullOrWhiteSpace ( result . SelectedProfile ) ? string . Empty : " • profile=" + result . SelectedProfile ;
2733+ _settings . UseWsl = OperatingSystem . IsWindows ( ) && result . UseWsl ;
2734+ _cli . UseWsl = OperatingSystem . IsWindows ( ) && _settings . UseWsl ;
2735+ var wslSuffix = _cli . UseWsl ? " • WSL" : string . Empty ;
2736+ AppendCliLog ( $ "System: CLI settings updated: '{ _cli . Command } '{ profileSuffix } { wslSuffix } (--proto enabled)") ;
27382737 // persist settings
27392738 _settings . Command = _cli . Command ;
27402739 // AdditionalArgs removed (profiles/config.toml driven)
0 commit comments