From 3ccce3eae6f79b824366845375e09fe9b72fadfe Mon Sep 17 00:00:00 2001 From: Markov Date: Mon, 23 Feb 2026 09:52:39 +0100 Subject: [PATCH] Add verbose logging (-v) for config, API key and requests --- picogent/cli.py | 10 ++++++++++ picogent/config.py | 21 +++++++++++++++++---- picogent/providers/anthropic.py | 9 +++++++++ 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/picogent/cli.py b/picogent/cli.py index 99acf09..abf8501 100644 --- a/picogent/cli.py +++ b/picogent/cli.py @@ -4,6 +4,7 @@ Command line interface for PicoGent import asyncio import argparse +import logging import sys import os from .agent import Agent @@ -13,6 +14,7 @@ from .config import Config async def main(): """Main CLI entry point""" parser = argparse.ArgumentParser(description="PicoGent - Minimal AI Coding Agent") + parser.add_argument("--verbose", "-v", action="store_true", help="Enable debug logging") parser.add_argument("message", nargs="*", help="Message to send to the agent") parser.add_argument("--config", "-c", default="config.json", help="Config file path") parser.add_argument("--session", "-s", help="Session file path (JSONL)") @@ -20,6 +22,14 @@ async def main(): args = parser.parse_args() + # Setup logging + log_level = logging.DEBUG if args.verbose else logging.INFO + logging.basicConfig( + level=log_level, + format="[%(name)s] %(message)s", + stream=sys.stderr + ) + # Join message parts message = " ".join(args.message) if args.message else None diff --git a/picogent/config.py b/picogent/config.py index 1cc09d8..0da5cb0 100644 --- a/picogent/config.py +++ b/picogent/config.py @@ -23,29 +23,42 @@ class Config: @classmethod def from_file(cls, config_path: str) -> "Config": """Load configuration from JSON file""" + import logging + logger = logging.getLogger("picogent.config") + + logger.info(f"Loading config from: {os.path.abspath(config_path)}") if not os.path.exists(config_path): raise FileNotFoundError(f"Config file not found: {config_path}") with open(config_path, 'r') as f: data = json.load(f) + provider = data.get('provider', 'anthropic') + model = data.get('model', 'claude-sonnet-4-20250514') + base_url = data.get('base_url', None) + logger.info(f"Provider: {provider} | Model: {model} | Base URL: {base_url}") + # Resolve environment variables in API key api_key = data.get('api_key', '') if api_key.startswith('env:'): env_var = api_key[4:] # Remove 'env:' prefix + logger.info(f"Resolving API key from env var: {env_var}") api_key = os.getenv(env_var, '') if not api_key: raise ValueError(f"Environment variable {env_var} is not set") - + logger.info(f"API key resolved: {api_key[:8]}...{api_key[-4:]} (len={len(api_key)})") + else: + logger.info(f"API key from config: {api_key[:8]}...{api_key[-4:]} (len={len(api_key)})" if len(api_key) > 12 else f"API key from config: *** (len={len(api_key)})") + return cls( - provider=data.get('provider', 'anthropic'), - model=data.get('model', 'claude-sonnet-4-20250514'), + provider=provider, + model=model, api_key=api_key, max_tokens=data.get('max_tokens', 8192), max_iterations=data.get('max_iterations', 20), workspace=data.get('workspace', '.'), system_prompt=data.get('system_prompt', 'You are a helpful coding assistant.'), - base_url=data.get('base_url', None) + base_url=base_url ) def to_dict(self) -> Dict[str, Any]: diff --git a/picogent/providers/anthropic.py b/picogent/providers/anthropic.py index 78f60ea..a94887b 100644 --- a/picogent/providers/anthropic.py +++ b/picogent/providers/anthropic.py @@ -4,9 +4,12 @@ Anthropic Claude provider using httpx import httpx import json +import logging from typing import Dict, List, Any, Optional from .base import BaseProvider +logger = logging.getLogger("picogent.anthropic") + class AnthropicProvider(BaseProvider): """Anthropic Claude provider using direct API calls""" @@ -42,6 +45,10 @@ class AnthropicProvider(BaseProvider): if tools: payload["tools"] = tools + logger.info(f"POST {self.base_url}/messages | model={self.model} | key={self.api_key[:8]}...{self.api_key[-4:]} (len={len(self.api_key)})") + logger.debug(f"Headers: x-api-key={self.api_key[:8]}..., anthropic-version={self.anthropic_version}") + logger.debug(f"Messages count: {len(messages)}, tools: {len(tools) if tools else 0}") + async with httpx.AsyncClient() as client: response = await client.post( f"{self.base_url}/messages", @@ -50,8 +57,10 @@ class AnthropicProvider(BaseProvider): timeout=120.0 ) + logger.info(f"Response status: {response.status_code}") if response.status_code != 200: error_text = response.text + logger.error(f"API error: {error_text}") raise Exception(f"Anthropic API error {response.status_code}: {error_text}") result = response.json()