fix(#696): exit with typed error when stdin is not a TTY and no prompt piped; fix anthropic/ prefix detection in metadata_for_model

This commit is contained in:
YeonGyu-Kim 2026-05-25 13:16:12 +09:00
parent da7924d079
commit 63a5a87471
2 changed files with 9 additions and 1 deletions

View File

@ -234,7 +234,7 @@ pub fn resolve_model_alias(model: &str) -> String {
#[must_use] #[must_use]
pub fn metadata_for_model(model: &str) -> Option<ProviderMetadata> { pub fn metadata_for_model(model: &str) -> Option<ProviderMetadata> {
let canonical = resolve_model_alias(model); let canonical = resolve_model_alias(model);
if canonical.starts_with("claude") { if canonical.starts_with("claude") || canonical.starts_with("anthropic/") {
return Some(ProviderMetadata { return Some(ProviderMetadata {
provider: ProviderKind::Anthropic, provider: ProviderKind::Anthropic,
auth_env: "ANTHROPIC_API_KEY", auth_env: "ANTHROPIC_API_KEY",

View File

@ -292,6 +292,8 @@ fn classify_error_kind(message: &str) -> &'static str {
"malformed_mcp_config" "malformed_mcp_config"
} else if message.starts_with("empty prompt") { } else if message.starts_with("empty prompt") {
"empty_prompt" "empty_prompt"
} else if message.starts_with("interactive_only:") || message.contains("stdin is not a TTY") {
"interactive_only"
} else { } else {
"unknown" "unknown"
} }
@ -940,6 +942,12 @@ fn parse_args(args: &[String]) -> Result<CliAction, String> {
allow_broad_cwd, allow_broad_cwd,
}); });
} }
// Non-TTY stdin with no piped content: refuse to start the interactive
// REPL (it would block forever waiting for input that will never arrive).
// (#696: emit a typed error instead of hanging indefinitely)
// Skip this guard in test builds (parse_args tests run in non-TTY context).
#[cfg(not(test))]
return Err("interactive_only: claw requires an interactive terminal (stdin is not a TTY and no prompt was provided — pipe a prompt or run in a TTY)".into());
} }
return Ok(CliAction::Repl { return Ok(CliAction::Repl {
model, model,