Add verbose logging (-v) for config, API key and requests
This commit is contained in:
parent
4f07bf7bec
commit
3ccce3eae6
@ -4,6 +4,7 @@ Command line interface for PicoGent
|
|||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import argparse
|
import argparse
|
||||||
|
import logging
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
from .agent import Agent
|
from .agent import Agent
|
||||||
@ -13,6 +14,7 @@ from .config import Config
|
|||||||
async def main():
|
async def main():
|
||||||
"""Main CLI entry point"""
|
"""Main CLI entry point"""
|
||||||
parser = argparse.ArgumentParser(description="PicoGent - Minimal AI Coding Agent")
|
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("message", nargs="*", help="Message to send to the agent")
|
||||||
parser.add_argument("--config", "-c", default="config.json", help="Config file path")
|
parser.add_argument("--config", "-c", default="config.json", help="Config file path")
|
||||||
parser.add_argument("--session", "-s", help="Session file path (JSONL)")
|
parser.add_argument("--session", "-s", help="Session file path (JSONL)")
|
||||||
@ -20,6 +22,14 @@ async def main():
|
|||||||
|
|
||||||
args = parser.parse_args()
|
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
|
# Join message parts
|
||||||
message = " ".join(args.message) if args.message else None
|
message = " ".join(args.message) if args.message else None
|
||||||
|
|
||||||
|
|||||||
@ -23,29 +23,42 @@ class Config:
|
|||||||
@classmethod
|
@classmethod
|
||||||
def from_file(cls, config_path: str) -> "Config":
|
def from_file(cls, config_path: str) -> "Config":
|
||||||
"""Load configuration from JSON file"""
|
"""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):
|
if not os.path.exists(config_path):
|
||||||
raise FileNotFoundError(f"Config file not found: {config_path}")
|
raise FileNotFoundError(f"Config file not found: {config_path}")
|
||||||
|
|
||||||
with open(config_path, 'r') as f:
|
with open(config_path, 'r') as f:
|
||||||
data = json.load(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
|
# Resolve environment variables in API key
|
||||||
api_key = data.get('api_key', '')
|
api_key = data.get('api_key', '')
|
||||||
if api_key.startswith('env:'):
|
if api_key.startswith('env:'):
|
||||||
env_var = api_key[4:] # Remove 'env:' prefix
|
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, '')
|
api_key = os.getenv(env_var, '')
|
||||||
if not api_key:
|
if not api_key:
|
||||||
raise ValueError(f"Environment variable {env_var} is not set")
|
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(
|
return cls(
|
||||||
provider=data.get('provider', 'anthropic'),
|
provider=provider,
|
||||||
model=data.get('model', 'claude-sonnet-4-20250514'),
|
model=model,
|
||||||
api_key=api_key,
|
api_key=api_key,
|
||||||
max_tokens=data.get('max_tokens', 8192),
|
max_tokens=data.get('max_tokens', 8192),
|
||||||
max_iterations=data.get('max_iterations', 20),
|
max_iterations=data.get('max_iterations', 20),
|
||||||
workspace=data.get('workspace', '.'),
|
workspace=data.get('workspace', '.'),
|
||||||
system_prompt=data.get('system_prompt', 'You are a helpful coding assistant.'),
|
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]:
|
def to_dict(self) -> Dict[str, Any]:
|
||||||
|
|||||||
@ -4,9 +4,12 @@ Anthropic Claude provider using httpx
|
|||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
from typing import Dict, List, Any, Optional
|
from typing import Dict, List, Any, Optional
|
||||||
from .base import BaseProvider
|
from .base import BaseProvider
|
||||||
|
|
||||||
|
logger = logging.getLogger("picogent.anthropic")
|
||||||
|
|
||||||
|
|
||||||
class AnthropicProvider(BaseProvider):
|
class AnthropicProvider(BaseProvider):
|
||||||
"""Anthropic Claude provider using direct API calls"""
|
"""Anthropic Claude provider using direct API calls"""
|
||||||
@ -42,6 +45,10 @@ class AnthropicProvider(BaseProvider):
|
|||||||
if tools:
|
if tools:
|
||||||
payload["tools"] = 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:
|
async with httpx.AsyncClient() as client:
|
||||||
response = await client.post(
|
response = await client.post(
|
||||||
f"{self.base_url}/messages",
|
f"{self.base_url}/messages",
|
||||||
@ -50,8 +57,10 @@ class AnthropicProvider(BaseProvider):
|
|||||||
timeout=120.0
|
timeout=120.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
logger.info(f"Response status: {response.status_code}")
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
error_text = response.text
|
error_text = response.text
|
||||||
|
logger.error(f"API error: {error_text}")
|
||||||
raise Exception(f"Anthropic API error {response.status_code}: {error_text}")
|
raise Exception(f"Anthropic API error {response.status_code}: {error_text}")
|
||||||
|
|
||||||
result = response.json()
|
result = response.json()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user