aghilsabu commited on
Commit
8320683
·
1 Parent(s): 58e0ebb

feat: add core configuration and project structure

Browse files
Files changed (2) hide show
  1. src/__init__.py +3 -0
  2. src/config.py +197 -0
src/__init__.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ """CodeAtlas - AI-Powered Codebase Visualization"""
2
+
3
+ __version__ = "1.0.0"
src/config.py ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """CodeAtlas Configuration"""
2
+
3
+ import os
4
+ import json
5
+ import logging
6
+ from dataclasses import dataclass, field
7
+ from pathlib import Path
8
+ from typing import Optional, Dict
9
+
10
+ # Paths
11
+ BASE_DIR = Path(__file__).parent.parent
12
+ DATA_DIR = BASE_DIR / "data"
13
+ DIAGRAMS_DIR = DATA_DIR / "diagrams"
14
+ AUDIOS_DIR = DATA_DIR / "audios"
15
+ LOGS_DIR = DATA_DIR / "logs"
16
+ SESSION_FILE = BASE_DIR / ".session_state.json"
17
+
18
+ for dir_path in [DATA_DIR, DIAGRAMS_DIR, AUDIOS_DIR, LOGS_DIR]:
19
+ dir_path.mkdir(parents=True, exist_ok=True)
20
+
21
+ # Logging
22
+ LOG_FILE = LOGS_DIR / "codeatlas.log"
23
+ logging.basicConfig(
24
+ level=logging.INFO,
25
+ format="%(asctime)s | %(levelname)-8s | %(name)s | %(message)s",
26
+ handlers=[
27
+ logging.StreamHandler(),
28
+ logging.FileHandler(LOG_FILE, encoding="utf-8"),
29
+ ],
30
+ )
31
+ logger = logging.getLogger("codeatlas")
32
+
33
+
34
+ @dataclass
35
+ class ModelConfig:
36
+ """Configuration for AI models."""
37
+
38
+ # Gemini Models (latest first)
39
+ GEMINI_MODELS: Dict[str, str] = field(default_factory=lambda: {
40
+ "Gemini 3.0 Pro": "gemini-3.0-pro",
41
+ "Gemini 2.5 Pro": "gemini-2.5-pro",
42
+ "Gemini 2.5 Flash": "gemini-2.5-flash",
43
+ "Gemini 2.5 Flash Lite": "gemini-2.5-flash-lite",
44
+ "Gemini 2.0 Flash": "gemini-2.0-flash",
45
+ "Gemini 2.0 Flash Lite": "gemini-2.0-flash-lite",
46
+ })
47
+
48
+ # OpenAI Models (latest first)
49
+ OPENAI_MODELS: Dict[str, str] = field(default_factory=lambda: {
50
+ "GPT-5.1": "gpt-5.1",
51
+ "GPT-5 Mini": "gpt-5-mini",
52
+ "GPT-5 Nano": "gpt-5-nano",
53
+ })
54
+
55
+ DEFAULT_MODEL: str = "Gemini 2.5 Pro"
56
+
57
+ @property
58
+ def all_models(self) -> Dict[str, str]:
59
+ """Get all available models."""
60
+ return {**self.GEMINI_MODELS, **self.OPENAI_MODELS}
61
+
62
+ def is_openai_model(self, model_name: str) -> bool:
63
+ """Check if a model is from OpenAI."""
64
+ return model_name.startswith(("gpt-", "o1", "o3"))
65
+
66
+ def get_model_id(self, display_name: str) -> str:
67
+ """Get model ID from display name."""
68
+ return self.all_models.get(display_name, self.GEMINI_MODELS[self.DEFAULT_MODEL])
69
+
70
+
71
+ @dataclass
72
+ class ProcessingConfig:
73
+ """Configuration for code processing."""
74
+
75
+ # File extensions to process
76
+ ALLOWED_EXTENSIONS: set = field(default_factory=lambda: {
77
+ ".py", ".js", ".ts", ".jsx", ".tsx", ".java", ".cpp", ".c", ".h",
78
+ ".cs", ".go", ".rs", ".php", ".rb", ".sql", ".yaml", ".yml",
79
+ ".json", ".md", ".txt", ".sh", ".bash", ".zsh"
80
+ })
81
+
82
+ # Special files to include regardless of extension
83
+ ALLOWED_FILES: set = field(default_factory=lambda: {
84
+ "Dockerfile", "Makefile", "README", "LICENSE", ".gitignore"
85
+ })
86
+
87
+ # Directories to ignore
88
+ BLOCKED_DIRS: set = field(default_factory=lambda: {
89
+ "node_modules", "__pycache__", ".git", "dist", "build", "venv",
90
+ ".venv", "env", ".env", ".idea", ".vscode", "coverage", ".next",
91
+ "target", "bin", "obj", ".gradle", ".m2", "vendor", "Pods",
92
+ "test", "tests", "__tests__", "spec", "specs", "testing",
93
+ "test_data", "testdata", "fixtures", "mocks", "mock",
94
+ "e2e", "integration", "unit", "cypress", "playwright"
95
+ })
96
+
97
+ # Files to ignore
98
+ BLOCKED_PATTERNS: set = field(default_factory=lambda: {
99
+ "package-lock.json", "yarn.lock", "pnpm-lock.yaml", "composer.lock",
100
+ "Gemfile.lock", "Cargo.lock", "poetry.lock", ".DS_Store",
101
+ ".eslintrc", ".prettierrc", "tsconfig.json", "jest.config.js",
102
+ "babel.config.js", ".babelrc", "webpack.config.js", "vite.config.js",
103
+ "setup.cfg", "pyproject.toml", "tox.ini", ".coveragerc"
104
+ })
105
+
106
+ # Test file patterns
107
+ TEST_FILE_PATTERNS: set = field(default_factory=lambda: {
108
+ "test_", "_test.", ".test.", ".spec.", "_spec.",
109
+ "conftest.py", "pytest.ini", "setup.py"
110
+ })
111
+
112
+ # Size limits
113
+ MAX_FILE_SIZE: int = 50 * 1024 # 50KB
114
+ MAX_CONTEXT_SIZE: int = 3_500_000 # ~1M tokens
115
+ LARGE_REPO_THRESHOLD: int = 10_000_000 # 10MB
116
+
117
+
118
+ @dataclass
119
+ class Config:
120
+ """Main configuration class."""
121
+
122
+ # API Keys (from environment or session)
123
+ gemini_api_key: Optional[str] = field(
124
+ default_factory=lambda: os.environ.get("GEMINI_API_KEY", "")
125
+ )
126
+ openai_api_key: Optional[str] = field(
127
+ default_factory=lambda: os.environ.get("OPENAI_API_KEY", "")
128
+ )
129
+ elevenlabs_api_key: Optional[str] = field(
130
+ default_factory=lambda: os.environ.get("ELEVENLABS_API_KEY", "")
131
+ )
132
+
133
+ # Model configuration
134
+ models: ModelConfig = field(default_factory=ModelConfig)
135
+
136
+ # Processing configuration
137
+ processing: ProcessingConfig = field(default_factory=ProcessingConfig)
138
+
139
+ # Current model selection
140
+ current_model: str = "Gemini 2.5 Pro"
141
+
142
+ # Paths
143
+ diagrams_dir: Path = DIAGRAMS_DIR
144
+ audios_dir: Path = AUDIOS_DIR
145
+ session_file: Path = SESSION_FILE
146
+
147
+ # Server settings
148
+ server_host: str = "0.0.0.0"
149
+ server_port: int = 7860
150
+
151
+ def save_to_session(self) -> bool:
152
+ """Save current config to session file."""
153
+ try:
154
+ data = {
155
+ "api_key": self.gemini_api_key,
156
+ "openai_api_key": self.openai_api_key,
157
+ "elevenlabs_api_key": self.elevenlabs_api_key,
158
+ "model": self.current_model,
159
+ }
160
+ with open(self.session_file, "w") as f:
161
+ json.dump(data, f)
162
+ return True
163
+ except Exception as e:
164
+ logger.warning(f"Failed to save session: {e}")
165
+ return False
166
+
167
+ def load_from_session(self) -> "Config":
168
+ """Load config from session file."""
169
+ try:
170
+ if self.session_file.exists():
171
+ with open(self.session_file, "r") as f:
172
+ data = json.load(f)
173
+ self.gemini_api_key = data.get("api_key", self.gemini_api_key)
174
+ self.openai_api_key = data.get("openai_api_key", self.openai_api_key)
175
+ self.elevenlabs_api_key = data.get("elevenlabs_api_key", self.elevenlabs_api_key)
176
+ self.current_model = data.get("model", self.current_model)
177
+ except Exception as e:
178
+ logger.warning(f"Failed to load session: {e}")
179
+ return self
180
+
181
+ def get_api_key_for_model(self, model_name: str) -> str:
182
+ """Get the appropriate API key for a model."""
183
+ if self.models.is_openai_model(model_name):
184
+ return self.openai_api_key or ""
185
+ return self.gemini_api_key or ""
186
+
187
+
188
+ # Global config instance
189
+ _config: Optional[Config] = None
190
+
191
+
192
+ def get_config() -> Config:
193
+ """Get the global configuration instance."""
194
+ global _config
195
+ if _config is None:
196
+ _config = Config().load_from_session()
197
+ return _config