skill-seekers 2.7.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- skill_seekers/__init__.py +22 -0
- skill_seekers/cli/__init__.py +39 -0
- skill_seekers/cli/adaptors/__init__.py +120 -0
- skill_seekers/cli/adaptors/base.py +221 -0
- skill_seekers/cli/adaptors/claude.py +485 -0
- skill_seekers/cli/adaptors/gemini.py +453 -0
- skill_seekers/cli/adaptors/markdown.py +269 -0
- skill_seekers/cli/adaptors/openai.py +503 -0
- skill_seekers/cli/ai_enhancer.py +310 -0
- skill_seekers/cli/api_reference_builder.py +373 -0
- skill_seekers/cli/architectural_pattern_detector.py +525 -0
- skill_seekers/cli/code_analyzer.py +1462 -0
- skill_seekers/cli/codebase_scraper.py +1225 -0
- skill_seekers/cli/config_command.py +563 -0
- skill_seekers/cli/config_enhancer.py +431 -0
- skill_seekers/cli/config_extractor.py +871 -0
- skill_seekers/cli/config_manager.py +452 -0
- skill_seekers/cli/config_validator.py +394 -0
- skill_seekers/cli/conflict_detector.py +528 -0
- skill_seekers/cli/constants.py +72 -0
- skill_seekers/cli/dependency_analyzer.py +757 -0
- skill_seekers/cli/doc_scraper.py +2332 -0
- skill_seekers/cli/enhance_skill.py +488 -0
- skill_seekers/cli/enhance_skill_local.py +1096 -0
- skill_seekers/cli/enhance_status.py +194 -0
- skill_seekers/cli/estimate_pages.py +433 -0
- skill_seekers/cli/generate_router.py +1209 -0
- skill_seekers/cli/github_fetcher.py +534 -0
- skill_seekers/cli/github_scraper.py +1466 -0
- skill_seekers/cli/guide_enhancer.py +723 -0
- skill_seekers/cli/how_to_guide_builder.py +1267 -0
- skill_seekers/cli/install_agent.py +461 -0
- skill_seekers/cli/install_skill.py +178 -0
- skill_seekers/cli/language_detector.py +614 -0
- skill_seekers/cli/llms_txt_detector.py +60 -0
- skill_seekers/cli/llms_txt_downloader.py +104 -0
- skill_seekers/cli/llms_txt_parser.py +150 -0
- skill_seekers/cli/main.py +558 -0
- skill_seekers/cli/markdown_cleaner.py +132 -0
- skill_seekers/cli/merge_sources.py +806 -0
- skill_seekers/cli/package_multi.py +77 -0
- skill_seekers/cli/package_skill.py +241 -0
- skill_seekers/cli/pattern_recognizer.py +1825 -0
- skill_seekers/cli/pdf_extractor_poc.py +1166 -0
- skill_seekers/cli/pdf_scraper.py +617 -0
- skill_seekers/cli/quality_checker.py +519 -0
- skill_seekers/cli/rate_limit_handler.py +438 -0
- skill_seekers/cli/resume_command.py +160 -0
- skill_seekers/cli/run_tests.py +230 -0
- skill_seekers/cli/setup_wizard.py +93 -0
- skill_seekers/cli/split_config.py +390 -0
- skill_seekers/cli/swift_patterns.py +560 -0
- skill_seekers/cli/test_example_extractor.py +1081 -0
- skill_seekers/cli/test_unified_simple.py +179 -0
- skill_seekers/cli/unified_codebase_analyzer.py +572 -0
- skill_seekers/cli/unified_scraper.py +932 -0
- skill_seekers/cli/unified_skill_builder.py +1605 -0
- skill_seekers/cli/upload_skill.py +162 -0
- skill_seekers/cli/utils.py +432 -0
- skill_seekers/mcp/__init__.py +33 -0
- skill_seekers/mcp/agent_detector.py +316 -0
- skill_seekers/mcp/git_repo.py +273 -0
- skill_seekers/mcp/server.py +231 -0
- skill_seekers/mcp/server_fastmcp.py +1249 -0
- skill_seekers/mcp/server_legacy.py +2302 -0
- skill_seekers/mcp/source_manager.py +285 -0
- skill_seekers/mcp/tools/__init__.py +115 -0
- skill_seekers/mcp/tools/config_tools.py +251 -0
- skill_seekers/mcp/tools/packaging_tools.py +826 -0
- skill_seekers/mcp/tools/scraping_tools.py +842 -0
- skill_seekers/mcp/tools/source_tools.py +828 -0
- skill_seekers/mcp/tools/splitting_tools.py +212 -0
- skill_seekers/py.typed +0 -0
- skill_seekers-2.7.3.dist-info/METADATA +2027 -0
- skill_seekers-2.7.3.dist-info/RECORD +79 -0
- skill_seekers-2.7.3.dist-info/WHEEL +5 -0
- skill_seekers-2.7.3.dist-info/entry_points.txt +19 -0
- skill_seekers-2.7.3.dist-info/licenses/LICENSE +21 -0
- skill_seekers-2.7.3.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Configuration Enhancer - AI-powered enhancement for config extraction results.
|
|
4
|
+
|
|
5
|
+
Provides dual-mode AI enhancement (API + LOCAL) for configuration analysis:
|
|
6
|
+
- Explain what each setting does
|
|
7
|
+
- Suggest best practices and improvements
|
|
8
|
+
- Security analysis (hardcoded secrets, exposed credentials)
|
|
9
|
+
- Migration suggestions (consolidate configs)
|
|
10
|
+
- Context-aware documentation
|
|
11
|
+
|
|
12
|
+
Similar to GuideEnhancer (C3.3) but for configuration files.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import json
|
|
16
|
+
import logging
|
|
17
|
+
import os
|
|
18
|
+
import subprocess
|
|
19
|
+
import sys
|
|
20
|
+
import tempfile
|
|
21
|
+
from dataclasses import dataclass, field
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
|
|
24
|
+
# Configure logging
|
|
25
|
+
logging.basicConfig(level=logging.INFO, format="%(levelname)s - %(message)s")
|
|
26
|
+
logger = logging.getLogger(__name__)
|
|
27
|
+
|
|
28
|
+
# Optional anthropic import
|
|
29
|
+
ANTHROPIC_AVAILABLE = False
|
|
30
|
+
try:
|
|
31
|
+
import anthropic
|
|
32
|
+
|
|
33
|
+
ANTHROPIC_AVAILABLE = True
|
|
34
|
+
except ImportError:
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass
|
|
39
|
+
class ConfigEnhancement:
|
|
40
|
+
"""AI-generated enhancement for a configuration"""
|
|
41
|
+
|
|
42
|
+
explanation: str = "" # What this setting does
|
|
43
|
+
best_practice: str = "" # Suggested improvement
|
|
44
|
+
security_concern: str = "" # Security issue (if any)
|
|
45
|
+
migration_suggestion: str = "" # Consolidation opportunity
|
|
46
|
+
context: str = "" # Pattern context and usage
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass
|
|
50
|
+
class EnhancedConfigFile:
|
|
51
|
+
"""Configuration file with AI enhancements"""
|
|
52
|
+
|
|
53
|
+
file_path: str
|
|
54
|
+
config_type: str
|
|
55
|
+
purpose: str
|
|
56
|
+
enhancement: ConfigEnhancement
|
|
57
|
+
setting_enhancements: dict[str, ConfigEnhancement] = field(default_factory=dict)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class ConfigEnhancer:
|
|
61
|
+
"""
|
|
62
|
+
AI enhancement for configuration extraction results.
|
|
63
|
+
|
|
64
|
+
Supports dual-mode operation:
|
|
65
|
+
- API mode: Uses Claude API (requires ANTHROPIC_API_KEY)
|
|
66
|
+
- LOCAL mode: Uses Claude Code CLI (no API key needed)
|
|
67
|
+
- AUTO mode: Automatically detects best available mode
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
def __init__(self, mode: str = "auto"):
|
|
71
|
+
"""
|
|
72
|
+
Initialize ConfigEnhancer.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
mode: Enhancement mode - "api", "local", or "auto" (default)
|
|
76
|
+
"""
|
|
77
|
+
self.mode = self._detect_mode(mode)
|
|
78
|
+
self.api_key = os.environ.get("ANTHROPIC_API_KEY")
|
|
79
|
+
self.client = None
|
|
80
|
+
|
|
81
|
+
if self.mode == "api" and ANTHROPIC_AVAILABLE and self.api_key:
|
|
82
|
+
self.client = anthropic.Anthropic(api_key=self.api_key)
|
|
83
|
+
|
|
84
|
+
def _detect_mode(self, requested_mode: str) -> str:
|
|
85
|
+
"""
|
|
86
|
+
Detect best enhancement mode.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
requested_mode: User-requested mode
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Actual mode to use
|
|
93
|
+
"""
|
|
94
|
+
if requested_mode in ["api", "local"]:
|
|
95
|
+
return requested_mode
|
|
96
|
+
|
|
97
|
+
# Auto-detect
|
|
98
|
+
if os.environ.get("ANTHROPIC_API_KEY") and ANTHROPIC_AVAILABLE:
|
|
99
|
+
logger.info("🤖 AI enhancement: API mode (Claude API detected)")
|
|
100
|
+
return "api"
|
|
101
|
+
else:
|
|
102
|
+
logger.info("🤖 AI enhancement: LOCAL mode (using Claude Code CLI)")
|
|
103
|
+
return "local"
|
|
104
|
+
|
|
105
|
+
def enhance_config_result(self, result: dict) -> dict:
|
|
106
|
+
"""
|
|
107
|
+
Enhance entire configuration extraction result.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
result: ConfigExtractionResult as dict
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
Enhanced result with AI insights
|
|
114
|
+
"""
|
|
115
|
+
logger.info(f"🔄 Enhancing {len(result.get('config_files', []))} config files...")
|
|
116
|
+
|
|
117
|
+
if self.mode == "api":
|
|
118
|
+
return self._enhance_via_api(result)
|
|
119
|
+
else:
|
|
120
|
+
return self._enhance_via_local(result)
|
|
121
|
+
|
|
122
|
+
# =========================================================================
|
|
123
|
+
# API MODE - Direct Claude API calls
|
|
124
|
+
# =========================================================================
|
|
125
|
+
|
|
126
|
+
def _enhance_via_api(self, result: dict) -> dict:
|
|
127
|
+
"""Enhance configs using Claude API"""
|
|
128
|
+
if not self.client:
|
|
129
|
+
logger.error("❌ API mode requested but no API key available")
|
|
130
|
+
return result
|
|
131
|
+
|
|
132
|
+
try:
|
|
133
|
+
# Create enhancement prompt
|
|
134
|
+
prompt = self._create_enhancement_prompt(result)
|
|
135
|
+
|
|
136
|
+
# Call Claude API
|
|
137
|
+
logger.info("📡 Calling Claude API for config analysis...")
|
|
138
|
+
response = self.client.messages.create(
|
|
139
|
+
model="claude-sonnet-4-20250514",
|
|
140
|
+
max_tokens=8000,
|
|
141
|
+
messages=[{"role": "user", "content": prompt}],
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
# Parse response
|
|
145
|
+
enhanced_result = self._parse_api_response(response.content[0].text, result)
|
|
146
|
+
logger.info("✅ API enhancement complete")
|
|
147
|
+
return enhanced_result
|
|
148
|
+
|
|
149
|
+
except Exception as e:
|
|
150
|
+
logger.error(f"❌ API enhancement failed: {e}")
|
|
151
|
+
return result
|
|
152
|
+
|
|
153
|
+
def _create_enhancement_prompt(self, result: dict) -> str:
|
|
154
|
+
"""Create prompt for Claude API"""
|
|
155
|
+
config_files = result.get("config_files", [])
|
|
156
|
+
|
|
157
|
+
# Summarize configs for prompt
|
|
158
|
+
config_summary = []
|
|
159
|
+
for cf in config_files[:10]: # Limit to first 10 files
|
|
160
|
+
settings_summary = []
|
|
161
|
+
for setting in cf.get("settings", [])[:5]: # First 5 settings per file
|
|
162
|
+
settings_summary.append(
|
|
163
|
+
f" - {setting['key']}: {setting['value']} ({setting['value_type']})"
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
config_summary.append(f"""
|
|
167
|
+
File: {cf["relative_path"]} ({cf["config_type"]})
|
|
168
|
+
Purpose: {cf["purpose"]}
|
|
169
|
+
Settings:
|
|
170
|
+
{chr(10).join(settings_summary)}
|
|
171
|
+
Patterns: {", ".join(cf.get("patterns", []))}
|
|
172
|
+
""")
|
|
173
|
+
|
|
174
|
+
prompt = f"""Analyze these configuration files and provide AI-enhanced insights.
|
|
175
|
+
|
|
176
|
+
CONFIGURATION FILES ({len(config_files)} total, showing first 10):
|
|
177
|
+
{chr(10).join(config_summary)}
|
|
178
|
+
|
|
179
|
+
YOUR TASK: Provide comprehensive analysis in JSON format with these 5 enhancements:
|
|
180
|
+
|
|
181
|
+
1. **EXPLANATIONS**: For each config file, explain its purpose and key settings
|
|
182
|
+
2. **BEST PRACTICES**: Suggest improvements (better structure, naming, organization)
|
|
183
|
+
3. **SECURITY ANALYSIS**: Identify hardcoded secrets, exposed credentials, security issues
|
|
184
|
+
4. **MIGRATION SUGGESTIONS**: Identify opportunities to consolidate or standardize configs
|
|
185
|
+
5. **CONTEXT**: Explain the detected patterns and when to use them
|
|
186
|
+
|
|
187
|
+
OUTPUT FORMAT (strict JSON):
|
|
188
|
+
{{
|
|
189
|
+
"file_enhancements": [
|
|
190
|
+
{{
|
|
191
|
+
"file_path": "path/to/config.json",
|
|
192
|
+
"explanation": "This file configures the database connection...",
|
|
193
|
+
"best_practice": "Consider using environment variables for host/port",
|
|
194
|
+
"security_concern": "⚠️ DATABASE_PASSWORD is hardcoded - move to .env",
|
|
195
|
+
"migration_suggestion": "Consolidate with config.yml (overlapping settings)",
|
|
196
|
+
"context": "Standard PostgreSQL configuration pattern"
|
|
197
|
+
}}
|
|
198
|
+
],
|
|
199
|
+
"overall_insights": {{
|
|
200
|
+
"config_count": {len(config_files)},
|
|
201
|
+
"security_issues_found": 3,
|
|
202
|
+
"consolidation_opportunities": ["Merge .env and config.json database settings"],
|
|
203
|
+
"recommended_actions": ["Move secrets to environment variables", "Standardize on YAML format"]
|
|
204
|
+
}}
|
|
205
|
+
}}
|
|
206
|
+
|
|
207
|
+
Focus on actionable insights that help developers understand and improve their configuration.
|
|
208
|
+
"""
|
|
209
|
+
return prompt
|
|
210
|
+
|
|
211
|
+
def _parse_api_response(self, response_text: str, original_result: dict) -> dict:
|
|
212
|
+
"""Parse Claude API response and merge with original result"""
|
|
213
|
+
try:
|
|
214
|
+
# Extract JSON from response
|
|
215
|
+
import re
|
|
216
|
+
|
|
217
|
+
json_match = re.search(r"\{.*\}", response_text, re.DOTALL)
|
|
218
|
+
if not json_match:
|
|
219
|
+
logger.warning("⚠️ No JSON found in API response")
|
|
220
|
+
return original_result
|
|
221
|
+
|
|
222
|
+
enhancements = json.loads(json_match.group())
|
|
223
|
+
|
|
224
|
+
# Merge enhancements into original result
|
|
225
|
+
original_result["ai_enhancements"] = enhancements
|
|
226
|
+
|
|
227
|
+
# Add enhancement flags to config files
|
|
228
|
+
file_enhancements = {
|
|
229
|
+
e["file_path"]: e for e in enhancements.get("file_enhancements", [])
|
|
230
|
+
}
|
|
231
|
+
for cf in original_result.get("config_files", []):
|
|
232
|
+
file_path = cf.get("relative_path", cf.get("file_path"))
|
|
233
|
+
if file_path in file_enhancements:
|
|
234
|
+
cf["ai_enhancement"] = file_enhancements[file_path]
|
|
235
|
+
|
|
236
|
+
return original_result
|
|
237
|
+
|
|
238
|
+
except json.JSONDecodeError as e:
|
|
239
|
+
logger.error(f"❌ Failed to parse API response as JSON: {e}")
|
|
240
|
+
return original_result
|
|
241
|
+
|
|
242
|
+
# =========================================================================
|
|
243
|
+
# LOCAL MODE - Claude Code CLI
|
|
244
|
+
# =========================================================================
|
|
245
|
+
|
|
246
|
+
def _enhance_via_local(self, result: dict) -> dict:
|
|
247
|
+
"""Enhance configs using Claude Code CLI"""
|
|
248
|
+
try:
|
|
249
|
+
# Create temporary prompt file
|
|
250
|
+
with tempfile.NamedTemporaryFile(mode="w", suffix=".md", delete=False) as f:
|
|
251
|
+
prompt_file = Path(f.name)
|
|
252
|
+
f.write(self._create_local_prompt(result))
|
|
253
|
+
|
|
254
|
+
# Create output file path
|
|
255
|
+
output_file = prompt_file.parent / f"{prompt_file.stem}_enhanced.json"
|
|
256
|
+
|
|
257
|
+
logger.info("🖥️ Launching Claude Code CLI for config analysis...")
|
|
258
|
+
logger.info("⏱️ This will take 30-60 seconds...")
|
|
259
|
+
|
|
260
|
+
# Run Claude Code CLI
|
|
261
|
+
result_data = self._run_claude_cli(prompt_file, output_file)
|
|
262
|
+
|
|
263
|
+
# Clean up
|
|
264
|
+
prompt_file.unlink()
|
|
265
|
+
if output_file.exists():
|
|
266
|
+
output_file.unlink()
|
|
267
|
+
|
|
268
|
+
if result_data:
|
|
269
|
+
# Merge LOCAL enhancements
|
|
270
|
+
result["ai_enhancements"] = result_data
|
|
271
|
+
logger.info("✅ LOCAL enhancement complete")
|
|
272
|
+
return result
|
|
273
|
+
else:
|
|
274
|
+
logger.warning("⚠️ LOCAL enhancement produced no results")
|
|
275
|
+
return result
|
|
276
|
+
|
|
277
|
+
except Exception as e:
|
|
278
|
+
logger.error(f"❌ LOCAL enhancement failed: {e}")
|
|
279
|
+
return result
|
|
280
|
+
|
|
281
|
+
def _create_local_prompt(self, result: dict) -> str:
|
|
282
|
+
"""Create prompt file for Claude Code CLI"""
|
|
283
|
+
config_files = result.get("config_files", [])
|
|
284
|
+
|
|
285
|
+
# Format config data for Claude
|
|
286
|
+
config_data = []
|
|
287
|
+
for cf in config_files[:10]:
|
|
288
|
+
config_data.append(f"""
|
|
289
|
+
### {cf["relative_path"]} ({cf["config_type"]})
|
|
290
|
+
- Purpose: {cf["purpose"]}
|
|
291
|
+
- Patterns: {", ".join(cf.get("patterns", []))}
|
|
292
|
+
- Settings count: {len(cf.get("settings", []))}
|
|
293
|
+
""")
|
|
294
|
+
|
|
295
|
+
prompt = f"""# Configuration Analysis Task
|
|
296
|
+
|
|
297
|
+
I need you to analyze these configuration files and provide AI-enhanced insights.
|
|
298
|
+
|
|
299
|
+
## Configuration Files ({len(config_files)} total)
|
|
300
|
+
|
|
301
|
+
{chr(10).join(config_data)}
|
|
302
|
+
|
|
303
|
+
## Your Task
|
|
304
|
+
|
|
305
|
+
Analyze these configs and create a JSON file with the following structure:
|
|
306
|
+
|
|
307
|
+
```json
|
|
308
|
+
{{
|
|
309
|
+
"file_enhancements": [
|
|
310
|
+
{{
|
|
311
|
+
"file_path": "path/to/file",
|
|
312
|
+
"explanation": "What this config does",
|
|
313
|
+
"best_practice": "Suggested improvements",
|
|
314
|
+
"security_concern": "Security issues (if any)",
|
|
315
|
+
"migration_suggestion": "Consolidation opportunities",
|
|
316
|
+
"context": "Pattern explanation"
|
|
317
|
+
}}
|
|
318
|
+
],
|
|
319
|
+
"overall_insights": {{
|
|
320
|
+
"config_count": {len(config_files)},
|
|
321
|
+
"security_issues_found": 0,
|
|
322
|
+
"consolidation_opportunities": [],
|
|
323
|
+
"recommended_actions": []
|
|
324
|
+
}}
|
|
325
|
+
}}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Please save the JSON output to a file named `config_enhancement.json` in the current directory.
|
|
329
|
+
|
|
330
|
+
Focus on actionable insights:
|
|
331
|
+
1. Explain what each config does
|
|
332
|
+
2. Suggest best practices
|
|
333
|
+
3. Identify security concerns (hardcoded secrets, exposed credentials)
|
|
334
|
+
4. Suggest consolidation opportunities
|
|
335
|
+
5. Explain the detected patterns
|
|
336
|
+
"""
|
|
337
|
+
return prompt
|
|
338
|
+
|
|
339
|
+
def _run_claude_cli(self, prompt_file: Path, _output_file: Path) -> dict | None:
|
|
340
|
+
"""Run Claude Code CLI and wait for completion"""
|
|
341
|
+
try:
|
|
342
|
+
# Run claude command
|
|
343
|
+
result = subprocess.run(
|
|
344
|
+
["claude", str(prompt_file)],
|
|
345
|
+
capture_output=True,
|
|
346
|
+
text=True,
|
|
347
|
+
timeout=300, # 5 minute timeout
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
if result.returncode != 0:
|
|
351
|
+
logger.error(f"❌ Claude CLI failed: {result.stderr}")
|
|
352
|
+
return None
|
|
353
|
+
|
|
354
|
+
# Try to find output file (Claude might save it with different name)
|
|
355
|
+
# Look for JSON files created in the last minute
|
|
356
|
+
import time
|
|
357
|
+
|
|
358
|
+
current_time = time.time()
|
|
359
|
+
potential_files = []
|
|
360
|
+
|
|
361
|
+
for json_file in prompt_file.parent.glob("*.json"):
|
|
362
|
+
if current_time - json_file.stat().st_mtime < 120: # Created in last 2 minutes
|
|
363
|
+
potential_files.append(json_file)
|
|
364
|
+
|
|
365
|
+
# Try to load the most recent JSON file
|
|
366
|
+
for json_file in sorted(potential_files, key=lambda f: f.stat().st_mtime, reverse=True):
|
|
367
|
+
try:
|
|
368
|
+
with open(json_file) as f:
|
|
369
|
+
data = json.load(f)
|
|
370
|
+
if "file_enhancements" in data or "overall_insights" in data:
|
|
371
|
+
logger.info(f"✅ Found enhancement data in {json_file.name}")
|
|
372
|
+
return data
|
|
373
|
+
except Exception:
|
|
374
|
+
continue
|
|
375
|
+
|
|
376
|
+
logger.warning("⚠️ Could not find enhancement output file")
|
|
377
|
+
return None
|
|
378
|
+
|
|
379
|
+
except subprocess.TimeoutExpired:
|
|
380
|
+
logger.error("❌ Claude CLI timeout (5 minutes)")
|
|
381
|
+
return None
|
|
382
|
+
except Exception as e:
|
|
383
|
+
logger.error(f"❌ Error running Claude CLI: {e}")
|
|
384
|
+
return None
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
def main():
|
|
388
|
+
"""Command-line interface for config enhancement"""
|
|
389
|
+
import argparse
|
|
390
|
+
|
|
391
|
+
parser = argparse.ArgumentParser(description="AI-enhance configuration extraction results")
|
|
392
|
+
parser.add_argument("result_file", help="Path to config extraction JSON result file")
|
|
393
|
+
parser.add_argument(
|
|
394
|
+
"--mode",
|
|
395
|
+
choices=["auto", "api", "local"],
|
|
396
|
+
default="auto",
|
|
397
|
+
help="Enhancement mode (default: auto)",
|
|
398
|
+
)
|
|
399
|
+
parser.add_argument(
|
|
400
|
+
"--output", help="Output file for enhanced results (default: <input>_enhanced.json)"
|
|
401
|
+
)
|
|
402
|
+
|
|
403
|
+
args = parser.parse_args()
|
|
404
|
+
|
|
405
|
+
# Load result file
|
|
406
|
+
try:
|
|
407
|
+
with open(args.result_file) as f:
|
|
408
|
+
result = json.load(f)
|
|
409
|
+
except Exception as e:
|
|
410
|
+
logger.error(f"❌ Failed to load result file: {e}")
|
|
411
|
+
return 1
|
|
412
|
+
|
|
413
|
+
# Enhance
|
|
414
|
+
enhancer = ConfigEnhancer(mode=args.mode)
|
|
415
|
+
enhanced_result = enhancer.enhance_config_result(result)
|
|
416
|
+
|
|
417
|
+
# Save
|
|
418
|
+
output_file = args.output or args.result_file.replace(".json", "_enhanced.json")
|
|
419
|
+
try:
|
|
420
|
+
with open(output_file, "w") as f:
|
|
421
|
+
json.dump(enhanced_result, f, indent=2)
|
|
422
|
+
logger.info(f"✅ Enhanced results saved to: {output_file}")
|
|
423
|
+
except Exception as e:
|
|
424
|
+
logger.error(f"❌ Failed to save results: {e}")
|
|
425
|
+
return 1
|
|
426
|
+
|
|
427
|
+
return 0
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
if __name__ == "__main__":
|
|
431
|
+
sys.exit(main())
|