mirror of
https://github.com/outbackdingo/optimclaw.git
synced 2026-08-25 14:53:34 +00:00
fix(cli): show auth prompt in REPL when credential is missing
The AuthRequired SSE event was emitted but only reached the web gateway.
The REPL never saw it because it receives events through
forward_event_to_channel which converts ThreadEvents to StatusUpdates.
Fix: when forward_event_to_channel sees an ActionFailed with
"authentication_required" in the error, emit StatusUpdate::AuthRequired
to the channel. Also add AuthRequired/AuthCompleted rendering to the
REPL (was missing — fell through to unmatched arm).
CLI now shows:
⚿ Authentication required: github_token
Store the credential with: ironclaw secret set <name> <value>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
This commit is contained in:
@@ -1223,6 +1223,32 @@ async fn forward_event_to_channel(
|
||||
metadata,
|
||||
)
|
||||
.await;
|
||||
|
||||
// When the HTTP tool fails with authentication_required, show the
|
||||
// auth prompt in the CLI/REPL so the user can authenticate.
|
||||
if error.contains("authentication_required") {
|
||||
let cred_name = error
|
||||
.split("credential '")
|
||||
.nth(1)
|
||||
.and_then(|s| s.split('\'').next())
|
||||
.unwrap_or("unknown")
|
||||
.to_string();
|
||||
let _ = channels
|
||||
.send_status(
|
||||
channel_name,
|
||||
StatusUpdate::AuthRequired {
|
||||
extension_name: cred_name,
|
||||
instructions: Some(
|
||||
"Store the credential with: ironclaw secret set <name> <value>"
|
||||
.into(),
|
||||
),
|
||||
auth_url: None,
|
||||
setup_url: None,
|
||||
},
|
||||
metadata,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
EventKind::StepCompleted { tokens, .. } => {
|
||||
let tok_msg = format!(
|
||||
|
||||
@@ -887,6 +887,42 @@ impl Channel for ReplChannel {
|
||||
);
|
||||
}
|
||||
}
|
||||
StatusUpdate::AuthRequired {
|
||||
extension_name,
|
||||
instructions,
|
||||
auth_url,
|
||||
..
|
||||
} => {
|
||||
eprintln!();
|
||||
eprintln!(
|
||||
" \x1b[33m\u{26BF} Authentication required: {}\x1b[0m",
|
||||
extension_name
|
||||
);
|
||||
if let Some(url) = auth_url {
|
||||
eprintln!(" \x1b[36mAuth URL: {}\x1b[0m", url);
|
||||
}
|
||||
if let Some(instr) = instructions {
|
||||
eprintln!(" \x1b[90m{}\x1b[0m", instr);
|
||||
}
|
||||
eprintln!();
|
||||
}
|
||||
StatusUpdate::AuthCompleted {
|
||||
extension_name,
|
||||
success,
|
||||
message,
|
||||
} => {
|
||||
if success {
|
||||
eprintln!(
|
||||
" \x1b[32m\u{2713} {} authenticated: {}\x1b[0m",
|
||||
extension_name, message
|
||||
);
|
||||
} else {
|
||||
eprintln!(
|
||||
" \x1b[31m\u{2717} {} auth failed: {}\x1b[0m",
|
||||
extension_name, message
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user