File size: 7,005 Bytes
ed1f7cd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
"""
Simplified Storage Utilities for API Keys and Settings
Provides basic storage utilities without complex warning systems
"""
import json
import os
from typing import Dict, Any, Optional
from datetime import datetime
import logging

class SecureStorageManager:
    """
    Simple storage manager for API keys and settings
    Focuses on environment variables and config file loading
    """
    
    def __init__(self):
        self.logger = logging.getLogger(__name__)
        
    def create_simple_warning_html(self) -> str:
        """Create a simple warning for AI settings section"""
        return """
        <div style="
            background-color: #fff3cd;
            border: 1px solid #ffeaa7;
            border-radius: 6px;
            padding: 12px;
            margin: 8px 0;
        ">
            <div style="color: #856404; display: flex; align-items: center; gap: 8px;">
                <span style="font-size: 18px;">⚠️</span>
                <div>
                    <strong>API Key Storage Notice</strong><br>
                    <small>API keys will be cleared when you refresh/reload the page or close the browser. 
                    Please keep your API keys and model information handy for re-entry when needed.</small>
                </div>
            </div>
        </div>
        """

    def load_from_environment(self) -> Dict[str, Any]:
        """Load API keys from environment variables"""
        config = {}
        
        # Claude API
        if os.getenv('CLAUDE_API_KEY'):
            config['claude'] = {
                'api_key': os.getenv('CLAUDE_API_KEY'),
                'model': os.getenv('CLAUDE_MODEL', 'claude-3-5-sonnet-20241022'),
                'api_url': os.getenv('CLAUDE_API_URL', 'https://api.anthropic.com')
            }
        
        # SambaNova API
        if os.getenv('SAMBANOVA_API_KEY'):
            config['sambanova'] = {
                'api_key': os.getenv('SAMBANOVA_API_KEY'),
                'model': os.getenv('SAMBANOVA_MODEL', 'Meta-Llama-3.1-70B-Instruct'),
                'api_url': os.getenv('SAMBANOVA_API_URL', 'https://api.sambanova.ai')
            }
        
        # LM Studio API
        if os.getenv('LM_STUDIO_URL'):
            config['lm_studio'] = {
                'api_url': os.getenv('LM_STUDIO_URL', 'http://localhost:1234/v1'),
                'model': os.getenv('LM_STUDIO_MODEL', 'local-model')
            }
        
        # Ollama API
        if os.getenv('OLLAMA_URL'):
            config['ollama'] = {
                'api_url': os.getenv('OLLAMA_URL', 'http://localhost:11434'),
                'model': os.getenv('OLLAMA_MODEL', 'llama3.1')
            }
        
        # Custom API
        if os.getenv('CUSTOM_API_URL'):
            config['custom'] = {
                'api_url': os.getenv('CUSTOM_API_URL'),
                'api_key': os.getenv('CUSTOM_API_KEY', ''),
                'model': os.getenv('CUSTOM_MODEL', 'default')
            }
        
        return config

    def load_config_from_file(self, config_path: str = "config.json") -> Optional[Dict[str, Any]]:
        """Load configuration from file"""
        try:
            if os.path.exists(config_path):
                with open(config_path, 'r') as f:
                    return json.load(f)
        except Exception as e:
            self.logger.error(f"Failed to load config file: {e}")
        return None

    def create_config_file_template(self) -> Dict[str, Any]:
        """Create a template for configuration file"""
        return {
            "api_keys": {
                "claude": {
                    "api_key": "your-claude-api-key-here",
                    "model": "claude-3-5-sonnet-20241022",
                    "api_url": "https://api.anthropic.com"
                },
                "sambanova": {
                    "api_key": "your-sambanova-api-key-here", 
                    "model": "Meta-Llama-3.1-70B-Instruct",
                    "api_url": "https://api.sambanova.ai"
                },
                "lm_studio": {
                    "api_url": "http://localhost:1234/v1",
                    "model": "local-model"
                },
                "ollama": {
                    "api_url": "http://localhost:11434",
                    "model": "llama3.1"
                }
            },
            "settings": {
                "temperature": 0.7,
                "max_tokens": 1000,
                "enable_insights": True,
                "enable_recommendations": True
            },
            "_metadata": {
                "version": "1.0",
                "created": datetime.now().isoformat(),
                "description": "Spend Analyzer MCP Configuration File"
            }
        }

    def save_config_template(self, config_path: str = "config.json.template") -> bool:
        """Save configuration template file"""
        try:
            template = self.create_config_file_template()
            with open(config_path, 'w') as f:
                json.dump(template, f, indent=2)
            self.logger.info(f"Configuration template saved to {config_path}")
            return True
        except Exception as e:
            self.logger.error(f"Failed to save config template: {e}")
            return False

    def get_environment_variables_guide(self) -> str:
        """Get guide for setting up environment variables"""
        return """
        # Environment Variables Setup Guide
        
        ## For Local Development:
        
        ### Windows (Command Prompt):
        ```cmd
        set CLAUDE_API_KEY=your-claude-api-key-here
        set SAMBANOVA_API_KEY=your-sambanova-api-key-here
        set LM_STUDIO_URL=http://localhost:1234/v1
        set OLLAMA_URL=http://localhost:11434
        ```
        
        ### Windows (PowerShell):
        ```powershell
        $env:CLAUDE_API_KEY="your-claude-api-key-here"
        $env:SAMBANOVA_API_KEY="your-sambanova-api-key-here"
        $env:LM_STUDIO_URL="http://localhost:1234/v1"
        $env:OLLAMA_URL="http://localhost:11434"
        ```
        
        ### macOS/Linux (Bash):
        ```bash
        export CLAUDE_API_KEY="your-claude-api-key-here"
        export SAMBANOVA_API_KEY="your-sambanova-api-key-here"
        export LM_STUDIO_URL="http://localhost:1234/v1"
        export OLLAMA_URL="http://localhost:11434"
        ```
        
        ### .env File (Recommended):
        Create a `.env` file in your project directory:
        ```
        CLAUDE_API_KEY=your-claude-api-key-here
        SAMBANOVA_API_KEY=your-sambanova-api-key-here
        LM_STUDIO_URL=http://localhost:1234/v1
        OLLAMA_URL=http://localhost:11434
        ```
        
        ## Security Best Practices:
        1. Never commit API keys to version control
        2. Use different keys for development and production
        3. Regularly rotate your API keys
        4. Monitor API usage for unusual activity
        5. Use least-privilege access principles
        """