summaryrefslogtreecommitdiff
path: root/makima/src
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-03-05 16:05:01 +0000
committersoryu <soryu@soryu.co>2026-03-05 16:05:01 +0000
commit0e30f1790cd3a1717dcb55ae137700de9bb0dfcb (patch)
tree9cf028f113699c8ee1bdcc3d5b2b8367c7c82236 /makima/src
parentec9738a069e61529be040eff065318972b8a11e2 (diff)
downloadsoryu-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.rs88
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,