Implemented Phase 1 of ClaudeTools Discord bot with: Core Features: - Discord.py bot with message content intents - Claude API integration with streaming responses - Thread-based conversations with context management - @mention handling with automatic thread creation - Tool definitions for future ClaudeTools/remediation integration Architecture: - bot/main.py: Entry point with Discord client setup - bot/config.py: Pydantic Settings for environment config - bot/claude/client.py: Anthropic SDK wrapper with streaming - bot/claude/tools.py: Tool definitions and system prompt - bot/handlers/message_handler.py: Discord message handling Configuration: - requirements.txt: Python dependencies (discord.py, anthropic, httpx) - .env.example: Environment variable template - .gitignore: Sensitive data protection - README.md: Comprehensive setup and usage guide Next Steps (Phase 2): - Implement tool execution (ClaudeTools API client) - Add user role mapping and permissions - Implement audit logging Deployment Target: BEAST (Windows) as NSSM service Test: @ClaudeTools hello should create thread and stream response Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
83 lines
2.5 KiB
Python
83 lines
2.5 KiB
Python
"""Configuration management for ClaudeTools Discord Bot."""
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
from pydantic import Field
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
"""Bot configuration from environment variables."""
|
|
|
|
# Discord
|
|
discord_token: str = Field(..., description="Discord bot token")
|
|
discord_guild_id: Optional[int] = Field(None, description="Discord guild/server ID")
|
|
|
|
# Anthropic Claude API
|
|
anthropic_api_key: str = Field(..., description="Anthropic API key")
|
|
claude_model: str = Field(
|
|
default="claude-sonnet-4-5-20250929",
|
|
description="Claude model to use"
|
|
)
|
|
|
|
# ClaudeTools API
|
|
claudetools_api_url: str = Field(
|
|
default="http://172.16.3.30:8001",
|
|
description="ClaudeTools API base URL"
|
|
)
|
|
claudetools_api_key: str = Field(..., description="ClaudeTools API key")
|
|
|
|
# File Paths
|
|
vault_path: Path = Field(
|
|
default=Path("D:/vault"),
|
|
description="Path to SOPS vault"
|
|
)
|
|
claudetools_root: Path = Field(
|
|
default=Path("D:/claudetools"),
|
|
description="Path to ClaudeTools repository"
|
|
)
|
|
|
|
# Git Bash (for remediation scripts on Windows)
|
|
git_bash_path: Path = Field(
|
|
default=Path("C:/Program Files/Git/bin/bash.exe"),
|
|
description="Path to Git Bash executable"
|
|
)
|
|
|
|
# Logging
|
|
log_level: str = Field(default="INFO", description="Logging level")
|
|
log_file: Optional[Path] = Field(
|
|
default=Path("logs/bot.log"),
|
|
description="Log file path"
|
|
)
|
|
|
|
model_config = SettingsConfigDict(
|
|
env_file=".env",
|
|
env_file_encoding="utf-8",
|
|
case_sensitive=False,
|
|
extra="ignore"
|
|
)
|
|
|
|
def validate_paths(self) -> None:
|
|
"""Validate that required paths exist."""
|
|
if not self.git_bash_path.exists():
|
|
raise FileNotFoundError(
|
|
f"Git Bash not found at {self.git_bash_path}. "
|
|
"Set GIT_BASH_PATH environment variable."
|
|
)
|
|
|
|
if not self.vault_path.exists():
|
|
raise FileNotFoundError(
|
|
f"Vault not found at {self.vault_path}. "
|
|
"Set VAULT_PATH environment variable."
|
|
)
|
|
|
|
if not self.claudetools_root.exists():
|
|
raise FileNotFoundError(
|
|
f"ClaudeTools not found at {self.claudetools_root}. "
|
|
"Set CLAUDETOOLS_ROOT environment variable."
|
|
)
|
|
|
|
|
|
# Global settings instance
|
|
settings = Settings()
|