aboutsummaryrefslogtreecommitdiffstats
path: root/packages/multillm-claude/src/multillm_claude
diff options
context:
space:
mode:
Diffstat (limited to 'packages/multillm-claude/src/multillm_claude')
-rw-r--r--packages/multillm-claude/src/multillm_claude/provider.py97
1 files changed, 89 insertions, 8 deletions
diff --git a/packages/multillm-claude/src/multillm_claude/provider.py b/packages/multillm-claude/src/multillm_claude/provider.py
index 051f845..f74564e 100644
--- a/packages/multillm-claude/src/multillm_claude/provider.py
+++ b/packages/multillm-claude/src/multillm_claude/provider.py
@@ -1,4 +1,5 @@
import os
+import sys
from typing import Any, AsyncIterator
from claude_agent_sdk import (
@@ -67,6 +68,17 @@ class ClaudeAgentProvider(BaseAgentProvider):
if merged_config.get("api_key"):
env["ANTHROPIC_API_KEY"] = merged_config["api_key"]
+ # Enable debug mode if requested
+ if os.environ.get("MULTILLM_DEBUG") or os.environ.get("DEBUG"):
+ env["DEBUG"] = "1"
+ print(f"[DEBUG] Claude Agent SDK options:", file=sys.stderr)
+ print(f" System prompt: {options.system_prompt if options else None}", file=sys.stderr)
+ print(f" Max turns: {options.max_turns if options else None}", file=sys.stderr)
+ print(f" Allowed tools: {options.allowed_tools if options else None}", file=sys.stderr)
+ print(f" Permission mode: {options.permission_mode if options else None}", file=sys.stderr)
+ print(f" Working dir: {options.working_directory if options else None}", file=sys.stderr)
+ print(f" Environment vars: {list(env.keys())}", file=sys.stderr)
+
if options is None:
return ClaudeAgentOptions(env=env) if env else ClaudeAgentOptions()
@@ -170,16 +182,85 @@ class ClaudeAgentProvider(BaseAgentProvider):
yield parsed
except ProcessError as e:
- error_msg = f"Claude Agent SDK process error: {e}"
- if hasattr(e, 'stderr') and e.stderr:
- error_msg += f"\nStderr: {e.stderr}"
- if hasattr(e, 'stdout') and e.stdout:
- error_msg += f"\nStdout: {e.stdout}"
- raise ProviderError(error_msg) from e
+ # Build detailed error message
+ error_parts = [f"Claude Agent SDK process error: {e}"]
+
+ # Print to stderr immediately so user sees it
+ print(f"\n{'='*70}", file=sys.stderr)
+ print("CLAUDE AGENT SDK ERROR", file=sys.stderr)
+ print(f"{'='*70}", file=sys.stderr)
+ print(f"Error: {e}", file=sys.stderr)
+
+ # Collect all available error information
+ error_info = {}
+ for attr in ['stderr', 'stdout', 'exit_code', 'command', 'output', 'message', 'args']:
+ if hasattr(e, attr):
+ val = getattr(e, attr)
+ if val:
+ error_info[attr] = val
+
+ # Print all error details to stderr
+ if error_info:
+ print("\nError Details:", file=sys.stderr)
+ for key, val in error_info.items():
+ print(f" {key}: {val}", file=sys.stderr)
+ # Also add to error message
+ error_parts.append(f"{key}: {val}")
+
+ # Check exception's __dict__ for any other attributes
+ if hasattr(e, '__dict__'):
+ other_attrs = {k: v for k, v in e.__dict__.items() if k not in error_info and not k.startswith('_')}
+ if other_attrs:
+ print("\nAdditional Info:", file=sys.stderr)
+ for key, val in other_attrs.items():
+ print(f" {key}: {val}", file=sys.stderr)
+ error_parts.append(f"{key}: {val}")
+
+ print(f"{'='*70}\n", file=sys.stderr)
+
+ raise ProviderError("\n".join(error_parts)) from e
+
except ClaudeSDKError as e:
- raise ProviderError(f"Claude Agent SDK error: {e}") from e
+ # Print to stderr immediately
+ print(f"\n{'='*70}", file=sys.stderr)
+ print("CLAUDE SDK ERROR", file=sys.stderr)
+ print(f"{'='*70}", file=sys.stderr)
+ print(f"Error: {e}", file=sys.stderr)
+
+ # Get all attributes from the error
+ error_parts = [f"Claude Agent SDK error: {e}"]
+ if hasattr(e, '__dict__'):
+ for key, val in e.__dict__.items():
+ if not key.startswith('_') and val:
+ print(f" {key}: {val}", file=sys.stderr)
+ error_parts.append(f"{key}: {val}")
+
+ print(f"{'='*70}\n", file=sys.stderr)
+
+ raise ProviderError("\n".join(error_parts)) from e
+
except Exception as e:
- raise ProviderError(f"Unexpected error: {e}") from e
+ # Print unexpected errors to stderr
+ print(f"\n{'='*70}", file=sys.stderr)
+ print("UNEXPECTED ERROR IN CLAUDE PROVIDER", file=sys.stderr)
+ print(f"{'='*70}", file=sys.stderr)
+ print(f"Type: {type(e).__name__}", file=sys.stderr)
+ print(f"Error: {e}", file=sys.stderr)
+
+ if hasattr(e, '__dict__'):
+ print("\nError attributes:", file=sys.stderr)
+ for key, val in e.__dict__.items():
+ if not key.startswith('_'):
+ print(f" {key}: {val}", file=sys.stderr)
+
+ # Print full traceback
+ import traceback
+ print("\nTraceback:", file=sys.stderr)
+ traceback.print_exc(file=sys.stderr)
+
+ print(f"{'='*70}\n", file=sys.stderr)
+
+ raise ProviderError(f"Unexpected error: {type(e).__name__}: {e}") from e
async def run_interactive(
self,