mirror of
https://github.com/leonvanzyl/autocoder.git
synced 2026-01-30 06:12:06 +00:00
feat: Add authentication error handling to start.py
Add detection and helpful messaging for Claude CLI authentication errors in the Python launcher, complementing the shell script improvements. Changes: - Add is_auth_error() helper with regex patterns for common auth errors - Add print_auth_error_help() for consistent, actionable error messages - Update run_spec_creation() to capture stderr and detect auth failures - Update run_agent() to capture stderr and detect auth failures - Both functions now provide helpful "run claude login" guidance Error patterns detected: - "not logged in" / "not authenticated" - "authentication failed/required/error" - "login required" - "please run claude login" - "unauthorized" - "invalid token/credential/api key" - "expired token/session/credential" This aligns the Python UX with the shell script's non-blocking warning approach while adding proactive error detection. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
94
start.py
94
start.py
@@ -9,6 +9,7 @@ Supports two paths for new projects:
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
@@ -24,6 +25,53 @@ from registry import (
|
||||
register_project,
|
||||
)
|
||||
|
||||
# Patterns that indicate Claude CLI authentication errors
|
||||
AUTH_ERROR_PATTERNS = [
|
||||
r"not\s+logged\s+in",
|
||||
r"not\s+authenticated",
|
||||
r"authentication\s+(failed|required|error)",
|
||||
r"login\s+required",
|
||||
r"please\s+(run\s+)?['\"]?claude\s+login",
|
||||
r"unauthorized",
|
||||
r"invalid\s+(token|credential|api.?key)",
|
||||
r"expired\s+(token|session|credential)",
|
||||
r"could\s+not\s+authenticate",
|
||||
r"sign\s+in\s+(to|required)",
|
||||
]
|
||||
|
||||
|
||||
def is_auth_error(output: str) -> bool:
|
||||
"""
|
||||
Check if output contains Claude CLI authentication error messages.
|
||||
|
||||
Args:
|
||||
output: Combined stdout/stderr from subprocess
|
||||
|
||||
Returns:
|
||||
True if authentication error detected, False otherwise
|
||||
"""
|
||||
if not output:
|
||||
return False
|
||||
|
||||
output_lower = output.lower()
|
||||
for pattern in AUTH_ERROR_PATTERNS:
|
||||
if re.search(pattern, output_lower):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def print_auth_error_help() -> None:
|
||||
"""Print helpful message when authentication error is detected."""
|
||||
print("\n" + "=" * 50)
|
||||
print(" Authentication Error Detected")
|
||||
print("=" * 50)
|
||||
print("\nClaude CLI requires authentication to work.")
|
||||
print("\nTo fix this, run:")
|
||||
print(" claude login")
|
||||
print("\nThis will open a browser window to sign in.")
|
||||
print("After logging in, try running this command again.")
|
||||
print("=" * 50 + "\n")
|
||||
|
||||
|
||||
def check_spec_exists(project_dir: Path) -> bool:
|
||||
"""
|
||||
@@ -203,6 +251,7 @@ def run_spec_creation(project_dir: Path) -> bool:
|
||||
Run Claude Code with /create-spec command to create project specification.
|
||||
|
||||
The project path is passed as an argument so create-spec knows where to write files.
|
||||
Captures stderr to detect authentication errors and provide helpful guidance.
|
||||
"""
|
||||
print("\n" + "=" * 50)
|
||||
print(" Project Specification Setup")
|
||||
@@ -217,12 +266,25 @@ def run_spec_creation(project_dir: Path) -> bool:
|
||||
try:
|
||||
# Launch Claude Code with /create-spec command
|
||||
# Project path included in command string so it populates $ARGUMENTS
|
||||
subprocess.run(
|
||||
# Capture stderr to detect auth errors while letting stdout flow to terminal
|
||||
result = subprocess.run(
|
||||
["claude", f"/create-spec {project_dir}"],
|
||||
check=False, # Don't raise on non-zero exit
|
||||
cwd=str(Path(__file__).parent) # Run from project root
|
||||
cwd=str(Path(__file__).parent), # Run from project root
|
||||
stderr=subprocess.PIPE,
|
||||
text=True
|
||||
)
|
||||
|
||||
# Check for authentication errors in stderr
|
||||
stderr_output = result.stderr or ""
|
||||
if result.returncode != 0 and is_auth_error(stderr_output):
|
||||
print_auth_error_help()
|
||||
return False
|
||||
|
||||
# If there was stderr output but not an auth error, show it
|
||||
if stderr_output.strip() and result.returncode != 0:
|
||||
print(f"\nClaude CLI error: {stderr_output.strip()}")
|
||||
|
||||
# Check if spec was created in project prompts directory
|
||||
if check_spec_exists(project_dir):
|
||||
print("\n" + "-" * 50)
|
||||
@@ -232,6 +294,9 @@ def run_spec_creation(project_dir: Path) -> bool:
|
||||
print("\n" + "-" * 50)
|
||||
print("Spec creation incomplete.")
|
||||
print(f"Please ensure app_spec.txt exists in: {get_project_prompts_dir(project_dir)}")
|
||||
# If failed with non-zero exit and no spec, might be auth issue
|
||||
if result.returncode != 0:
|
||||
print("\nIf you're having authentication issues, try running: claude login")
|
||||
return False
|
||||
|
||||
except FileNotFoundError:
|
||||
@@ -348,6 +413,8 @@ def create_new_project_flow() -> tuple[str, Path] | None:
|
||||
def run_agent(project_name: str, project_dir: Path) -> None:
|
||||
"""Run the autonomous agent with the given project.
|
||||
|
||||
Captures stderr to detect authentication errors and provide helpful guidance.
|
||||
|
||||
Args:
|
||||
project_name: Name of the project
|
||||
project_dir: Absolute path to the project directory
|
||||
@@ -367,9 +434,28 @@ def run_agent(project_name: str, project_dir: Path) -> None:
|
||||
# Build the command - pass absolute path
|
||||
cmd = [sys.executable, "autonomous_agent_demo.py", "--project-dir", str(project_dir.resolve())]
|
||||
|
||||
# Run the agent
|
||||
# Run the agent with stderr capture to detect auth errors
|
||||
# stdout goes directly to terminal for real-time output
|
||||
try:
|
||||
subprocess.run(cmd, check=False)
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
check=False,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True
|
||||
)
|
||||
|
||||
# Check for authentication errors
|
||||
stderr_output = result.stderr or ""
|
||||
if result.returncode != 0:
|
||||
if is_auth_error(stderr_output):
|
||||
print_auth_error_help()
|
||||
elif stderr_output.strip():
|
||||
# Show any other errors
|
||||
print(f"\nAgent error:\n{stderr_output.strip()}")
|
||||
# Still hint about auth if exit was unexpected
|
||||
if "error" in stderr_output.lower() or "exception" in stderr_output.lower():
|
||||
print("\nIf this is an authentication issue, try running: claude login")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n\nAgent interrupted. Run again to resume.")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user