diff options
| author | soryu <soryu@soryu.co> | 2026-03-05 16:05:01 +0000 |
|---|---|---|
| committer | soryu <soryu@soryu.co> | 2026-03-05 16:05:01 +0000 |
| commit | 0e30f1790cd3a1717dcb55ae137700de9bb0dfcb (patch) | |
| tree | 9cf028f113699c8ee1bdcc3d5b2b8367c7c82236 /makima/src | |
| parent | ec9738a069e61529be040eff065318972b8a11e2 (diff) | |
| download | soryu-0e30f1790cd3a1717dcb55ae137700de9bb0dfcb.tar.gz soryu-0e30f1790cd3a1717dcb55ae137700de9bb0dfcb.zip | |
fix: restore code entry in daemon reauth flow
The previous commit removed the manual auth code input, expecting OAuth
to complete automatically via token auto-detection. This restores the
code entry field as the primary path while keeping token auto-detection
as a parallel fallback.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'makima/src')
| -rw-r--r-- | makima/src/daemon/task/manager.rs | 88 |
1 files changed, 64 insertions, 24 deletions
diff --git a/makima/src/daemon/task/manager.rs b/makima/src/daemon/task/manager.rs index df5e167..dd7df8a 100644 --- a/makima/src/daemon/task/manager.rs +++ b/makima/src/daemon/task/manager.rs @@ -117,7 +117,6 @@ fn get_auth_flow_storage() -> &'static std::sync::Mutex<Option<std::sync::mpsc:: } /// Send an auth code to the pending OAuth flow. -/// Deprecated: The new setup-token flow outputs tokens directly, so this is no longer needed. pub fn send_auth_code(code: &str) -> bool { let storage = get_auth_flow_storage(); if let Ok(mut guard) = storage.lock() { @@ -128,7 +127,7 @@ pub fn send_auth_code(code: &str) -> bool { } } } - tracing::warn!("No pending auth flow to send code to (this is expected with the new token-based flow)"); + tracing::warn!("No pending auth flow to send code to"); false } @@ -189,7 +188,7 @@ struct OAuthFlowResult { /// The token is automatically detected, saved to disk, and reported via the token_rx channel. async fn get_oauth_login_url(claude_command: &str) -> Option<OAuthFlowResult> { use portable_pty::{native_pty_system, CommandBuilder, PtySize}; - use std::io::Read; + use std::io::{Read, Write}; tracing::info!("Spawning claude setup-token in PTY to get OAuth login URL"); @@ -235,8 +234,7 @@ async fn get_oauth_login_url(claude_command: &str) -> Option<OAuthFlowResult> { } }; - // Take the writer - we keep it alive but don't need to write auth codes anymore - let _writer = match pair.master.take_writer() { + let mut writer = match pair.master.take_writer() { Ok(writer) => writer, Err(e) => { tracing::error!(error = %e, "Failed to take PTY writer"); @@ -245,12 +243,12 @@ async fn get_oauth_login_url(claude_command: &str) -> Option<OAuthFlowResult> { }; // Create channels for communication + let (code_tx, code_rx) = std::sync::mpsc::channel::<String>(); let (url_tx, url_rx) = std::sync::mpsc::channel::<String>(); let (token_tx, token_rx) = tokio::sync::oneshot::channel::<String>(); - // Also store a legacy code sender for backward compatibility (in case old server sends SubmitAuthCode) + // Store the code sender globally so it can be used when AUTH_CODE message arrives { - let (code_tx, _code_rx) = std::sync::mpsc::channel::<String>(); let storage = get_auth_flow_storage(); if let Ok(mut guard) = storage.lock() { *guard = Some(code_tx); @@ -332,9 +330,36 @@ async fn get_oauth_login_url(claude_command: &str) -> Option<OAuthFlowResult> { tracing::info!("setup-token reader thread ended (token_saved={})", token_saved); }); - // Spawn cleanup thread - waits for reader to finish and cleans up the child process + // Spawn writer thread - waits for auth code and writes it to PTY std::thread::spawn(move || { - tracing::debug!("setup-token cleanup thread: waiting for reader thread to finish..."); + tracing::info!("setup-token writer thread started, waiting for auth code (10 min timeout)"); + + // Wait for auth code from frontend (with long timeout - user needs time to authenticate) + match code_rx.recv_timeout(std::time::Duration::from_secs(600)) { + Ok(code) => { + tracing::info!(code_len = code.len(), "Received auth code from frontend, writing to PTY"); + // Write code followed by carriage return (Enter key in raw terminal mode) + let code_with_enter = format!("{}\r", code); + if let Err(e) = writer.write_all(code_with_enter.as_bytes()) { + tracing::error!(error = %e, "Failed to write auth code to PTY"); + } else if let Err(e) = writer.flush() { + tracing::error!(error = %e, "Failed to flush PTY writer"); + } else { + tracing::info!("Auth code written to setup-token PTY successfully"); + // Give Ink a moment to process, then send another Enter in case first was buffered + std::thread::sleep(std::time::Duration::from_millis(100)); + let _ = writer.write_all(b"\r"); + let _ = writer.flush(); + tracing::info!("Sent additional Enter keypress"); + } + } + Err(e) => { + tracing::info!(error = %e, "Auth code receive ended (timeout or channel closed)"); + } + } + + // Wait for reader thread to finish + tracing::debug!("Waiting for reader thread to finish..."); let _ = reader_handle.join(); // Wait for child to fully exit @@ -347,9 +372,6 @@ async fn get_oauth_login_url(claude_command: &str) -> Option<OAuthFlowResult> { tracing::error!(error = %e, "Failed to wait for setup-token process"); } } - - // Keep _writer alive until here so PTY stays open - drop(_writer); }); // Wait for URL with timeout @@ -2015,18 +2037,36 @@ impl TaskManager { } }); } - DaemonCommand::SubmitAuthCode { request_id, code: _ } => { - // Deprecated: The new setup-token flow outputs tokens directly. - // This handler is kept for backward compatibility but is a no-op. - tracing::info!(request_id = %request_id, "Received auth code submission (deprecated - new flow auto-detects token)"); - let msg = DaemonMessage::ReauthStatus { - request_id, - status: "completed".to_string(), - login_url: None, - error: None, - token_saved: load_oauth_token().is_some(), - }; - let _ = self.ws_tx.send(msg).await; + DaemonCommand::SubmitAuthCode { request_id, code } => { + tracing::info!(request_id = %request_id, "Received auth code submission from server"); + let ws_tx = self.ws_tx.clone(); + + if send_auth_code(&code) { + tracing::info!(request_id = %request_id, "Auth code forwarded to setup-token for reauth"); + // Wait a short time then report completion + // (the setup-token process takes a moment to complete) + tokio::spawn(async move { + tokio::time::sleep(std::time::Duration::from_secs(3)).await; + let msg = DaemonMessage::ReauthStatus { + request_id, + status: "completed".to_string(), + login_url: None, + error: None, + token_saved: false, + }; + let _ = ws_tx.send(msg).await; + }); + } else { + tracing::warn!(request_id = %request_id, "No pending auth flow to receive code for reauth"); + let msg = DaemonMessage::ReauthStatus { + request_id, + status: "failed".to_string(), + login_url: None, + error: Some("No pending auth flow to receive the code. Try triggering reauth again.".to_string()), + token_saved: false, + }; + let _ = self.ws_tx.send(msg).await; + } } DaemonCommand::ApplyPatchToWorktree { target_task_id, |
