pomera-ai-commander 1.1.1 → 1.2.2
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.
- package/LICENSE +21 -21
- package/README.md +105 -680
- package/bin/pomera-ai-commander.js +62 -62
- package/core/__init__.py +65 -65
- package/core/app_context.py +482 -482
- package/core/async_text_processor.py +421 -421
- package/core/backup_manager.py +655 -655
- package/core/backup_recovery_manager.py +1199 -1033
- package/core/content_hash_cache.py +508 -508
- package/core/context_menu.py +313 -313
- package/core/data_directory.py +549 -0
- package/core/data_validator.py +1066 -1066
- package/core/database_connection_manager.py +744 -744
- package/core/database_curl_settings_manager.py +608 -608
- package/core/database_promera_ai_settings_manager.py +446 -446
- package/core/database_schema.py +411 -411
- package/core/database_schema_manager.py +395 -395
- package/core/database_settings_manager.py +1507 -1507
- package/core/database_settings_manager_interface.py +456 -456
- package/core/dialog_manager.py +734 -734
- package/core/diff_utils.py +239 -0
- package/core/efficient_line_numbers.py +540 -510
- package/core/error_handler.py +746 -746
- package/core/error_service.py +431 -431
- package/core/event_consolidator.py +511 -511
- package/core/mcp/__init__.py +43 -43
- package/core/mcp/find_replace_diff.py +334 -0
- package/core/mcp/protocol.py +288 -288
- package/core/mcp/schema.py +251 -251
- package/core/mcp/server_stdio.py +299 -299
- package/core/mcp/tool_registry.py +2699 -2345
- package/core/memento.py +275 -0
- package/core/memory_efficient_text_widget.py +711 -711
- package/core/migration_manager.py +914 -914
- package/core/migration_test_suite.py +1085 -1085
- package/core/migration_validator.py +1143 -1143
- package/core/optimized_find_replace.py +714 -714
- package/core/optimized_pattern_engine.py +424 -424
- package/core/optimized_search_highlighter.py +552 -552
- package/core/performance_monitor.py +674 -674
- package/core/persistence_manager.py +712 -712
- package/core/progressive_stats_calculator.py +632 -632
- package/core/regex_pattern_cache.py +529 -529
- package/core/regex_pattern_library.py +350 -350
- package/core/search_operation_manager.py +434 -434
- package/core/settings_defaults_registry.py +1087 -1087
- package/core/settings_integrity_validator.py +1111 -1111
- package/core/settings_serializer.py +557 -557
- package/core/settings_validator.py +1823 -1823
- package/core/smart_stats_calculator.py +709 -709
- package/core/statistics_update_manager.py +619 -619
- package/core/stats_config_manager.py +858 -858
- package/core/streaming_text_handler.py +723 -723
- package/core/task_scheduler.py +596 -596
- package/core/update_pattern_library.py +168 -168
- package/core/visibility_monitor.py +596 -596
- package/core/widget_cache.py +498 -498
- package/mcp.json +51 -61
- package/migrate_data.py +127 -0
- package/package.json +64 -57
- package/pomera.py +7883 -7482
- package/pomera_mcp_server.py +183 -144
- package/requirements.txt +33 -0
- package/scripts/Dockerfile.alpine +43 -0
- package/scripts/Dockerfile.gui-test +54 -0
- package/scripts/Dockerfile.linux +43 -0
- package/scripts/Dockerfile.test-linux +80 -0
- package/scripts/Dockerfile.ubuntu +39 -0
- package/scripts/README.md +53 -0
- package/scripts/build-all.bat +113 -0
- package/scripts/build-docker.bat +53 -0
- package/scripts/build-docker.sh +55 -0
- package/scripts/build-optimized.bat +101 -0
- package/scripts/build.sh +78 -0
- package/scripts/docker-compose.test.yml +27 -0
- package/scripts/docker-compose.yml +32 -0
- package/scripts/postinstall.js +62 -0
- package/scripts/requirements-minimal.txt +33 -0
- package/scripts/test-linux-simple.bat +28 -0
- package/scripts/validate-release-workflow.py +450 -0
- package/tools/__init__.py +4 -4
- package/tools/ai_tools.py +2891 -2891
- package/tools/ascii_art_generator.py +352 -352
- package/tools/base64_tools.py +183 -183
- package/tools/base_tool.py +511 -511
- package/tools/case_tool.py +308 -308
- package/tools/column_tools.py +395 -395
- package/tools/cron_tool.py +884 -884
- package/tools/curl_history.py +600 -600
- package/tools/curl_processor.py +1207 -1207
- package/tools/curl_settings.py +502 -502
- package/tools/curl_tool.py +5467 -5467
- package/tools/diff_viewer.py +1817 -1072
- package/tools/email_extraction_tool.py +248 -248
- package/tools/email_header_analyzer.py +425 -425
- package/tools/extraction_tools.py +250 -250
- package/tools/find_replace.py +2289 -1750
- package/tools/folder_file_reporter.py +1463 -1463
- package/tools/folder_file_reporter_adapter.py +480 -480
- package/tools/generator_tools.py +1216 -1216
- package/tools/hash_generator.py +255 -255
- package/tools/html_tool.py +656 -656
- package/tools/jsonxml_tool.py +729 -729
- package/tools/line_tools.py +419 -419
- package/tools/markdown_tools.py +561 -561
- package/tools/mcp_widget.py +1417 -1417
- package/tools/notes_widget.py +978 -973
- package/tools/number_base_converter.py +372 -372
- package/tools/regex_extractor.py +571 -571
- package/tools/slug_generator.py +310 -310
- package/tools/sorter_tools.py +458 -458
- package/tools/string_escape_tool.py +392 -392
- package/tools/text_statistics_tool.py +365 -365
- package/tools/text_wrapper.py +430 -430
- package/tools/timestamp_converter.py +421 -421
- package/tools/tool_loader.py +710 -710
- package/tools/translator_tools.py +522 -522
- package/tools/url_link_extractor.py +261 -261
- package/tools/url_parser.py +204 -204
- package/tools/whitespace_tools.py +355 -355
- package/tools/word_frequency_counter.py +146 -146
- package/core/__pycache__/__init__.cpython-313.pyc +0 -0
- package/core/__pycache__/app_context.cpython-313.pyc +0 -0
- package/core/__pycache__/async_text_processor.cpython-313.pyc +0 -0
- package/core/__pycache__/backup_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/backup_recovery_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/content_hash_cache.cpython-313.pyc +0 -0
- package/core/__pycache__/context_menu.cpython-313.pyc +0 -0
- package/core/__pycache__/data_validator.cpython-313.pyc +0 -0
- package/core/__pycache__/database_connection_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/database_curl_settings_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/database_promera_ai_settings_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/database_schema.cpython-313.pyc +0 -0
- package/core/__pycache__/database_schema_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/database_settings_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/database_settings_manager_interface.cpython-313.pyc +0 -0
- package/core/__pycache__/dialog_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/efficient_line_numbers.cpython-313.pyc +0 -0
- package/core/__pycache__/error_handler.cpython-313.pyc +0 -0
- package/core/__pycache__/error_service.cpython-313.pyc +0 -0
- package/core/__pycache__/event_consolidator.cpython-313.pyc +0 -0
- package/core/__pycache__/memory_efficient_text_widget.cpython-313.pyc +0 -0
- package/core/__pycache__/migration_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/migration_test_suite.cpython-313.pyc +0 -0
- package/core/__pycache__/migration_validator.cpython-313.pyc +0 -0
- package/core/__pycache__/optimized_find_replace.cpython-313.pyc +0 -0
- package/core/__pycache__/optimized_pattern_engine.cpython-313.pyc +0 -0
- package/core/__pycache__/optimized_search_highlighter.cpython-313.pyc +0 -0
- package/core/__pycache__/performance_monitor.cpython-313.pyc +0 -0
- package/core/__pycache__/persistence_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/progressive_stats_calculator.cpython-313.pyc +0 -0
- package/core/__pycache__/regex_pattern_cache.cpython-313.pyc +0 -0
- package/core/__pycache__/regex_pattern_library.cpython-313.pyc +0 -0
- package/core/__pycache__/search_operation_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/settings_defaults_registry.cpython-313.pyc +0 -0
- package/core/__pycache__/settings_integrity_validator.cpython-313.pyc +0 -0
- package/core/__pycache__/settings_serializer.cpython-313.pyc +0 -0
- package/core/__pycache__/settings_validator.cpython-313.pyc +0 -0
- package/core/__pycache__/smart_stats_calculator.cpython-313.pyc +0 -0
- package/core/__pycache__/statistics_update_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/stats_config_manager.cpython-313.pyc +0 -0
- package/core/__pycache__/streaming_text_handler.cpython-313.pyc +0 -0
- package/core/__pycache__/task_scheduler.cpython-313.pyc +0 -0
- package/core/__pycache__/visibility_monitor.cpython-313.pyc +0 -0
- package/core/__pycache__/widget_cache.cpython-313.pyc +0 -0
- package/core/mcp/__pycache__/__init__.cpython-313.pyc +0 -0
- package/core/mcp/__pycache__/protocol.cpython-313.pyc +0 -0
- package/core/mcp/__pycache__/schema.cpython-313.pyc +0 -0
- package/core/mcp/__pycache__/server_stdio.cpython-313.pyc +0 -0
- package/core/mcp/__pycache__/tool_registry.cpython-313.pyc +0 -0
- package/tools/__pycache__/__init__.cpython-313.pyc +0 -0
- package/tools/__pycache__/ai_tools.cpython-313.pyc +0 -0
- package/tools/__pycache__/ascii_art_generator.cpython-313.pyc +0 -0
- package/tools/__pycache__/base64_tools.cpython-313.pyc +0 -0
- package/tools/__pycache__/base_tool.cpython-313.pyc +0 -0
- package/tools/__pycache__/case_tool.cpython-313.pyc +0 -0
- package/tools/__pycache__/column_tools.cpython-313.pyc +0 -0
- package/tools/__pycache__/cron_tool.cpython-313.pyc +0 -0
- package/tools/__pycache__/curl_history.cpython-313.pyc +0 -0
- package/tools/__pycache__/curl_processor.cpython-313.pyc +0 -0
- package/tools/__pycache__/curl_settings.cpython-313.pyc +0 -0
- package/tools/__pycache__/curl_tool.cpython-313.pyc +0 -0
- package/tools/__pycache__/diff_viewer.cpython-313.pyc +0 -0
- package/tools/__pycache__/email_extraction_tool.cpython-313.pyc +0 -0
- package/tools/__pycache__/email_header_analyzer.cpython-313.pyc +0 -0
- package/tools/__pycache__/extraction_tools.cpython-313.pyc +0 -0
- package/tools/__pycache__/find_replace.cpython-313.pyc +0 -0
- package/tools/__pycache__/folder_file_reporter.cpython-313.pyc +0 -0
- package/tools/__pycache__/folder_file_reporter_adapter.cpython-313.pyc +0 -0
- package/tools/__pycache__/generator_tools.cpython-313.pyc +0 -0
- package/tools/__pycache__/hash_generator.cpython-313.pyc +0 -0
- package/tools/__pycache__/html_tool.cpython-313.pyc +0 -0
- package/tools/__pycache__/huggingface_helper.cpython-313.pyc +0 -0
- package/tools/__pycache__/jsonxml_tool.cpython-313.pyc +0 -0
- package/tools/__pycache__/line_tools.cpython-313.pyc +0 -0
- package/tools/__pycache__/list_comparator.cpython-313.pyc +0 -0
- package/tools/__pycache__/markdown_tools.cpython-313.pyc +0 -0
- package/tools/__pycache__/mcp_widget.cpython-313.pyc +0 -0
- package/tools/__pycache__/notes_widget.cpython-313.pyc +0 -0
- package/tools/__pycache__/number_base_converter.cpython-313.pyc +0 -0
- package/tools/__pycache__/regex_extractor.cpython-313.pyc +0 -0
- package/tools/__pycache__/slug_generator.cpython-313.pyc +0 -0
- package/tools/__pycache__/sorter_tools.cpython-313.pyc +0 -0
- package/tools/__pycache__/string_escape_tool.cpython-313.pyc +0 -0
- package/tools/__pycache__/text_statistics_tool.cpython-313.pyc +0 -0
- package/tools/__pycache__/text_wrapper.cpython-313.pyc +0 -0
- package/tools/__pycache__/timestamp_converter.cpython-313.pyc +0 -0
- package/tools/__pycache__/tool_loader.cpython-313.pyc +0 -0
- package/tools/__pycache__/translator_tools.cpython-313.pyc +0 -0
- package/tools/__pycache__/url_link_extractor.cpython-313.pyc +0 -0
- package/tools/__pycache__/url_parser.cpython-313.pyc +0 -0
- package/tools/__pycache__/whitespace_tools.cpython-313.pyc +0 -0
- package/tools/__pycache__/word_frequency_counter.cpython-313.pyc +0 -0
|
@@ -1,609 +1,609 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Database-Compatible cURL Tool Settings Management Module
|
|
3
|
-
|
|
4
|
-
This module provides an updated CurlSettingsManager that works with the database backend
|
|
5
|
-
while maintaining full backward compatibility with the existing interface.
|
|
6
|
-
|
|
7
|
-
Author: Pomera AI Commander
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
import json
|
|
11
|
-
import os
|
|
12
|
-
from typing import Dict, List, Any, Optional
|
|
13
|
-
import logging
|
|
14
|
-
from datetime import datetime
|
|
15
|
-
|
|
16
|
-
from .database_settings_manager import DatabaseSettingsManager
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class DatabaseCurlSettingsManager:
|
|
20
|
-
"""
|
|
21
|
-
Database-compatible settings manager for the cURL Tool.
|
|
22
|
-
|
|
23
|
-
This class maintains the same interface as the original CurlSettingsManager
|
|
24
|
-
but uses the database backend for improved concurrency and data integrity.
|
|
25
|
-
|
|
26
|
-
Handles:
|
|
27
|
-
- Settings persistence through database backend
|
|
28
|
-
- Default configuration values
|
|
29
|
-
- Settings validation
|
|
30
|
-
- Configuration backup and restore
|
|
31
|
-
- Full backward compatibility with existing cURL tool code
|
|
32
|
-
"""
|
|
33
|
-
|
|
34
|
-
def __init__(self, database_settings_manager: DatabaseSettingsManager, logger=None):
|
|
35
|
-
"""
|
|
36
|
-
Initialize the database-compatible cURL settings manager.
|
|
37
|
-
|
|
38
|
-
Args:
|
|
39
|
-
database_settings_manager: DatabaseSettingsManager instance
|
|
40
|
-
logger: Logger instance for debugging
|
|
41
|
-
"""
|
|
42
|
-
self.database_manager = database_settings_manager
|
|
43
|
-
self.logger = logger or logging.getLogger(__name__)
|
|
44
|
-
self.tool_key = "cURL Tool" # Key in tool_settings section
|
|
45
|
-
|
|
46
|
-
# Default settings configuration (same as original)
|
|
47
|
-
self.default_settings = {
|
|
48
|
-
# Request settings
|
|
49
|
-
"default_timeout": 30,
|
|
50
|
-
"follow_redirects": True,
|
|
51
|
-
"verify_ssl": True,
|
|
52
|
-
"max_redirects": 10,
|
|
53
|
-
"user_agent": "Pomera cURL Tool/1.0",
|
|
54
|
-
|
|
55
|
-
# History settings
|
|
56
|
-
"save_history": True,
|
|
57
|
-
"max_history_items": 100,
|
|
58
|
-
"auto_cleanup_history": True,
|
|
59
|
-
"history_retention_days": 30,
|
|
60
|
-
"history": [], # Request history array
|
|
61
|
-
"collections": {}, # Request collections
|
|
62
|
-
"history_last_updated": None,
|
|
63
|
-
|
|
64
|
-
# Authentication settings
|
|
65
|
-
"persist_auth": True,
|
|
66
|
-
"auth_timeout_minutes": 60,
|
|
67
|
-
"clear_auth_on_exit": False,
|
|
68
|
-
|
|
69
|
-
# UI settings
|
|
70
|
-
"remember_window_size": True,
|
|
71
|
-
"default_body_type": "JSON",
|
|
72
|
-
"auto_format_json": True,
|
|
73
|
-
"syntax_highlighting": True,
|
|
74
|
-
"show_response_time": True,
|
|
75
|
-
|
|
76
|
-
# Download settings
|
|
77
|
-
"default_download_path": "",
|
|
78
|
-
"use_remote_filename": True,
|
|
79
|
-
"resume_downloads": True,
|
|
80
|
-
"download_chunk_size": 8192,
|
|
81
|
-
|
|
82
|
-
# Export/Import settings
|
|
83
|
-
"curl_export_format": "standard", # standard, minimal, verbose
|
|
84
|
-
"include_comments_in_export": True,
|
|
85
|
-
"auto_escape_special_chars": True,
|
|
86
|
-
"complex_options": "", # Additional cURL options not handled by UI
|
|
87
|
-
|
|
88
|
-
# Debug settings
|
|
89
|
-
"enable_debug_logging": False,
|
|
90
|
-
"log_request_headers": True,
|
|
91
|
-
"log_response_headers": True,
|
|
92
|
-
"max_log_size_mb": 10,
|
|
93
|
-
|
|
94
|
-
# Advanced settings
|
|
95
|
-
"connection_pool_size": 10,
|
|
96
|
-
"retry_attempts": 3,
|
|
97
|
-
"retry_delay_seconds": 1,
|
|
98
|
-
"enable_http2": False,
|
|
99
|
-
|
|
100
|
-
# Version and metadata
|
|
101
|
-
"settings_version": "1.0",
|
|
102
|
-
"last_updated": None,
|
|
103
|
-
"created_date": None
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
# Initialize settings if they don't exist
|
|
107
|
-
self._initialize_settings()
|
|
108
|
-
|
|
109
|
-
def _initialize_settings(self) -> None:
|
|
110
|
-
"""Initialize cURL tool settings if they don't exist in database."""
|
|
111
|
-
try:
|
|
112
|
-
# Check if tool settings exist
|
|
113
|
-
existing_settings = self.database_manager.get_tool_settings(self.tool_key)
|
|
114
|
-
|
|
115
|
-
if not existing_settings:
|
|
116
|
-
# Initialize with defaults
|
|
117
|
-
self.logger.info("Initializing cURL tool settings with defaults")
|
|
118
|
-
default_with_timestamp = self.default_settings.copy()
|
|
119
|
-
default_with_timestamp["created_date"] = datetime.now().isoformat()
|
|
120
|
-
default_with_timestamp["last_updated"] = datetime.now().isoformat()
|
|
121
|
-
|
|
122
|
-
# Set tool settings in database
|
|
123
|
-
for key, value in default_with_timestamp.items():
|
|
124
|
-
self.database_manager.set_tool_setting(self.tool_key, key, value)
|
|
125
|
-
else:
|
|
126
|
-
# Ensure all default keys exist (for backward compatibility)
|
|
127
|
-
self._ensure_all_defaults_exist(existing_settings)
|
|
128
|
-
|
|
129
|
-
except Exception as e:
|
|
130
|
-
self.logger.error(f"Failed to initialize cURL settings: {e}")
|
|
131
|
-
|
|
132
|
-
def _ensure_all_defaults_exist(self, existing_settings: Dict[str, Any]) -> None:
|
|
133
|
-
"""Ensure all default settings exist, adding missing ones."""
|
|
134
|
-
try:
|
|
135
|
-
missing_keys = set(self.default_settings.keys()) - set(existing_settings.keys())
|
|
136
|
-
|
|
137
|
-
if missing_keys:
|
|
138
|
-
self.logger.info(f"Adding missing cURL settings: {missing_keys}")
|
|
139
|
-
for key in missing_keys:
|
|
140
|
-
self.database_manager.set_tool_setting(self.tool_key, key, self.default_settings[key])
|
|
141
|
-
|
|
142
|
-
# Update last_updated timestamp
|
|
143
|
-
self.database_manager.set_tool_setting(self.tool_key, "last_updated", datetime.now().isoformat())
|
|
144
|
-
|
|
145
|
-
except Exception as e:
|
|
146
|
-
self.logger.error(f"Failed to ensure default settings: {e}")
|
|
147
|
-
|
|
148
|
-
# Backward Compatible API Methods
|
|
149
|
-
|
|
150
|
-
def load_settings(self) -> Dict[str, Any]:
|
|
151
|
-
"""
|
|
152
|
-
Load settings from database backend.
|
|
153
|
-
|
|
154
|
-
Returns:
|
|
155
|
-
Dictionary of current settings
|
|
156
|
-
"""
|
|
157
|
-
try:
|
|
158
|
-
settings = self.database_manager.get_tool_settings(self.tool_key)
|
|
159
|
-
|
|
160
|
-
if not settings:
|
|
161
|
-
# Return defaults if no settings found
|
|
162
|
-
settings = self.default_settings.copy()
|
|
163
|
-
settings["created_date"] = datetime.now().isoformat()
|
|
164
|
-
self.logger.info("No cURL settings found, using defaults")
|
|
165
|
-
|
|
166
|
-
# Validate and fix any invalid settings
|
|
167
|
-
self._validate_settings(settings)
|
|
168
|
-
|
|
169
|
-
self.logger.debug(f"cURL Tool settings loaded from database")
|
|
170
|
-
return settings
|
|
171
|
-
|
|
172
|
-
except Exception as e:
|
|
173
|
-
self.logger.error(f"Error loading cURL settings: {e}")
|
|
174
|
-
# Fall back to defaults
|
|
175
|
-
settings = self.default_settings.copy()
|
|
176
|
-
settings["created_date"] = datetime.now().isoformat()
|
|
177
|
-
return settings
|
|
178
|
-
|
|
179
|
-
def save_settings(self, settings_dict: Optional[Dict[str, Any]] = None) -> bool:
|
|
180
|
-
"""
|
|
181
|
-
Save current settings to database backend.
|
|
182
|
-
|
|
183
|
-
Args:
|
|
184
|
-
settings_dict: Optional settings dictionary to save
|
|
185
|
-
|
|
186
|
-
Returns:
|
|
187
|
-
True if successful, False otherwise
|
|
188
|
-
"""
|
|
189
|
-
try:
|
|
190
|
-
if settings_dict is None:
|
|
191
|
-
# If no specific settings provided, this is a no-op since database is always current
|
|
192
|
-
return True
|
|
193
|
-
|
|
194
|
-
# Update last modified timestamp
|
|
195
|
-
settings_dict["last_updated"] = datetime.now().isoformat()
|
|
196
|
-
|
|
197
|
-
# Save each setting to database
|
|
198
|
-
for key, value in settings_dict.items():
|
|
199
|
-
self.database_manager.set_tool_setting(self.tool_key, key, value)
|
|
200
|
-
|
|
201
|
-
self.logger.debug(f"cURL Tool settings saved to database")
|
|
202
|
-
return True
|
|
203
|
-
|
|
204
|
-
except Exception as e:
|
|
205
|
-
self.logger.error(f"Error saving cURL settings: {e}")
|
|
206
|
-
return False
|
|
207
|
-
|
|
208
|
-
def get_setting(self, key: str, default: Any = None) -> Any:
|
|
209
|
-
"""
|
|
210
|
-
Get a setting value.
|
|
211
|
-
|
|
212
|
-
Args:
|
|
213
|
-
key: Setting key
|
|
214
|
-
default: Default value if key not found
|
|
215
|
-
|
|
216
|
-
Returns:
|
|
217
|
-
Setting value or default
|
|
218
|
-
"""
|
|
219
|
-
try:
|
|
220
|
-
settings = self.database_manager.get_tool_settings(self.tool_key)
|
|
221
|
-
return settings.get(key, default)
|
|
222
|
-
except Exception as e:
|
|
223
|
-
self.logger.error(f"Error getting cURL setting {key}: {e}")
|
|
224
|
-
return default
|
|
225
|
-
|
|
226
|
-
def set_setting(self, key: str, value: Any) -> bool:
|
|
227
|
-
"""
|
|
228
|
-
Set a setting value.
|
|
229
|
-
|
|
230
|
-
Args:
|
|
231
|
-
key: Setting key
|
|
232
|
-
value: Setting value
|
|
233
|
-
|
|
234
|
-
Returns:
|
|
235
|
-
True if successful, False otherwise
|
|
236
|
-
"""
|
|
237
|
-
try:
|
|
238
|
-
# Validate the setting
|
|
239
|
-
if self._validate_setting(key, value):
|
|
240
|
-
self.database_manager.set_tool_setting(self.tool_key, key, value)
|
|
241
|
-
# Update timestamp
|
|
242
|
-
self.database_manager.set_tool_setting(self.tool_key, "last_updated", datetime.now().isoformat())
|
|
243
|
-
return True
|
|
244
|
-
else:
|
|
245
|
-
self.logger.warning(f"Invalid cURL setting value: {key} = {value}")
|
|
246
|
-
return False
|
|
247
|
-
|
|
248
|
-
except Exception as e:
|
|
249
|
-
self.logger.error(f"Error setting cURL setting {key}: {e}")
|
|
250
|
-
return False
|
|
251
|
-
|
|
252
|
-
def reset_to_defaults(self) -> bool:
|
|
253
|
-
"""
|
|
254
|
-
Reset all settings to defaults.
|
|
255
|
-
|
|
256
|
-
Returns:
|
|
257
|
-
True if successful, False otherwise
|
|
258
|
-
"""
|
|
259
|
-
try:
|
|
260
|
-
# Get current creation date if it exists
|
|
261
|
-
current_settings = self.database_manager.get_tool_settings(self.tool_key)
|
|
262
|
-
created_date = current_settings.get("created_date") if current_settings else None
|
|
263
|
-
|
|
264
|
-
# Reset to defaults
|
|
265
|
-
defaults = self.default_settings.copy()
|
|
266
|
-
if created_date:
|
|
267
|
-
defaults["created_date"] = created_date
|
|
268
|
-
defaults["last_updated"] = datetime.now().isoformat()
|
|
269
|
-
|
|
270
|
-
# Save defaults to database
|
|
271
|
-
return self.save_settings(defaults)
|
|
272
|
-
|
|
273
|
-
except Exception as e:
|
|
274
|
-
self.logger.error(f"Error resetting cURL settings: {e}")
|
|
275
|
-
return False
|
|
276
|
-
|
|
277
|
-
def export_settings(self, filepath: str) -> bool:
|
|
278
|
-
"""
|
|
279
|
-
Export settings to a file.
|
|
280
|
-
|
|
281
|
-
Args:
|
|
282
|
-
filepath: Path to export file
|
|
283
|
-
|
|
284
|
-
Returns:
|
|
285
|
-
True if successful, False otherwise
|
|
286
|
-
"""
|
|
287
|
-
try:
|
|
288
|
-
settings = self.load_settings()
|
|
289
|
-
|
|
290
|
-
with open(filepath, 'w', encoding='utf-8') as f:
|
|
291
|
-
json.dump(settings, f, indent=4, ensure_ascii=False)
|
|
292
|
-
|
|
293
|
-
self.logger.info(f"cURL settings exported to {filepath}")
|
|
294
|
-
return True
|
|
295
|
-
|
|
296
|
-
except Exception as e:
|
|
297
|
-
self.logger.error(f"Error exporting cURL settings: {e}")
|
|
298
|
-
return False
|
|
299
|
-
|
|
300
|
-
def import_settings(self, filepath: str) -> bool:
|
|
301
|
-
"""
|
|
302
|
-
Import settings from a file.
|
|
303
|
-
|
|
304
|
-
Args:
|
|
305
|
-
filepath: Path to import file
|
|
306
|
-
|
|
307
|
-
Returns:
|
|
308
|
-
True if successful, False otherwise
|
|
309
|
-
"""
|
|
310
|
-
try:
|
|
311
|
-
if not os.path.exists(filepath):
|
|
312
|
-
self.logger.error(f"Import file not found: {filepath}")
|
|
313
|
-
return False
|
|
314
|
-
|
|
315
|
-
with open(filepath, 'r', encoding='utf-8') as f:
|
|
316
|
-
imported_settings = json.load(f)
|
|
317
|
-
|
|
318
|
-
# Validate imported settings
|
|
319
|
-
if self._validate_settings(imported_settings):
|
|
320
|
-
imported_settings["last_updated"] = datetime.now().isoformat()
|
|
321
|
-
return self.save_settings(imported_settings)
|
|
322
|
-
else:
|
|
323
|
-
self.logger.error("Invalid settings in import file")
|
|
324
|
-
return False
|
|
325
|
-
|
|
326
|
-
except Exception as e:
|
|
327
|
-
self.logger.error(f"Error importing cURL settings: {e}")
|
|
328
|
-
return False
|
|
329
|
-
|
|
330
|
-
def create_backup(self) -> Optional[str]:
|
|
331
|
-
"""
|
|
332
|
-
Create a backup of current settings.
|
|
333
|
-
|
|
334
|
-
Returns:
|
|
335
|
-
Path to backup file if successful, None otherwise
|
|
336
|
-
"""
|
|
337
|
-
try:
|
|
338
|
-
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
339
|
-
backup_path = f"curl_tool_settings_backup_{timestamp}.json"
|
|
340
|
-
|
|
341
|
-
if self.export_settings(backup_path):
|
|
342
|
-
self.logger.info(f"cURL settings backup created: {backup_path}")
|
|
343
|
-
return backup_path
|
|
344
|
-
else:
|
|
345
|
-
return None
|
|
346
|
-
|
|
347
|
-
except Exception as e:
|
|
348
|
-
self.logger.error(f"Error creating cURL settings backup: {e}")
|
|
349
|
-
return None
|
|
350
|
-
|
|
351
|
-
def restore_backup(self, backup_path: str) -> bool:
|
|
352
|
-
"""
|
|
353
|
-
Restore settings from a backup file.
|
|
354
|
-
|
|
355
|
-
Args:
|
|
356
|
-
backup_path: Path to backup file
|
|
357
|
-
|
|
358
|
-
Returns:
|
|
359
|
-
True if successful, False otherwise
|
|
360
|
-
"""
|
|
361
|
-
return self.import_settings(backup_path)
|
|
362
|
-
|
|
363
|
-
# History Management Methods (cURL-specific)
|
|
364
|
-
|
|
365
|
-
def add_history_entry(self, entry: Dict[str, Any]) -> bool:
|
|
366
|
-
"""
|
|
367
|
-
Add an entry to the request history.
|
|
368
|
-
|
|
369
|
-
Args:
|
|
370
|
-
entry: History entry dictionary
|
|
371
|
-
|
|
372
|
-
Returns:
|
|
373
|
-
True if successful, False otherwise
|
|
374
|
-
"""
|
|
375
|
-
try:
|
|
376
|
-
settings = self.load_settings()
|
|
377
|
-
history = settings.get("history", [])
|
|
378
|
-
|
|
379
|
-
# Add timestamp if not present
|
|
380
|
-
if "timestamp" not in entry:
|
|
381
|
-
entry["timestamp"] = datetime.now().isoformat()
|
|
382
|
-
|
|
383
|
-
# Add to beginning of history
|
|
384
|
-
history.insert(0, entry)
|
|
385
|
-
|
|
386
|
-
# Limit history size
|
|
387
|
-
max_items = settings.get("max_history_items", 100)
|
|
388
|
-
if len(history) > max_items:
|
|
389
|
-
history = history[:max_items]
|
|
390
|
-
|
|
391
|
-
# Update database
|
|
392
|
-
self.database_manager.set_tool_setting(self.tool_key, "history", history)
|
|
393
|
-
self.database_manager.set_tool_setting(self.tool_key, "history_last_updated", datetime.now().isoformat())
|
|
394
|
-
|
|
395
|
-
return True
|
|
396
|
-
|
|
397
|
-
except Exception as e:
|
|
398
|
-
self.logger.error(f"Error adding cURL history entry: {e}")
|
|
399
|
-
return False
|
|
400
|
-
|
|
401
|
-
def get_history(self) -> List[Dict[str, Any]]:
|
|
402
|
-
"""
|
|
403
|
-
Get the request history.
|
|
404
|
-
|
|
405
|
-
Returns:
|
|
406
|
-
List of history entries
|
|
407
|
-
"""
|
|
408
|
-
try:
|
|
409
|
-
settings = self.load_settings()
|
|
410
|
-
return settings.get("history", [])
|
|
411
|
-
except Exception as e:
|
|
412
|
-
self.logger.error(f"Error getting cURL history: {e}")
|
|
413
|
-
return []
|
|
414
|
-
|
|
415
|
-
def clear_history(self) -> bool:
|
|
416
|
-
"""
|
|
417
|
-
Clear the request history.
|
|
418
|
-
|
|
419
|
-
Returns:
|
|
420
|
-
True if successful, False otherwise
|
|
421
|
-
"""
|
|
422
|
-
try:
|
|
423
|
-
self.database_manager.set_tool_setting(self.tool_key, "history", [])
|
|
424
|
-
self.database_manager.set_tool_setting(self.tool_key, "history_last_updated", datetime.now().isoformat())
|
|
425
|
-
return True
|
|
426
|
-
except Exception as e:
|
|
427
|
-
self.logger.error(f"Error clearing cURL history: {e}")
|
|
428
|
-
return False
|
|
429
|
-
|
|
430
|
-
# Collections Management Methods (cURL-specific)
|
|
431
|
-
|
|
432
|
-
def save_collection(self, name: str, requests: List[Dict[str, Any]]) -> bool:
|
|
433
|
-
"""
|
|
434
|
-
Save a collection of requests.
|
|
435
|
-
|
|
436
|
-
Args:
|
|
437
|
-
name: Collection name
|
|
438
|
-
requests: List of request dictionaries
|
|
439
|
-
|
|
440
|
-
Returns:
|
|
441
|
-
True if successful, False otherwise
|
|
442
|
-
"""
|
|
443
|
-
try:
|
|
444
|
-
settings = self.load_settings()
|
|
445
|
-
collections = settings.get("collections", {})
|
|
446
|
-
|
|
447
|
-
collections[name] = {
|
|
448
|
-
"requests": requests,
|
|
449
|
-
"created": datetime.now().isoformat(),
|
|
450
|
-
"modified": datetime.now().isoformat()
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
self.database_manager.set_tool_setting(self.tool_key, "collections", collections)
|
|
454
|
-
return True
|
|
455
|
-
|
|
456
|
-
except Exception as e:
|
|
457
|
-
self.logger.error(f"Error saving cURL collection {name}: {e}")
|
|
458
|
-
return False
|
|
459
|
-
|
|
460
|
-
def get_collections(self) -> Dict[str, Any]:
|
|
461
|
-
"""
|
|
462
|
-
Get all saved collections.
|
|
463
|
-
|
|
464
|
-
Returns:
|
|
465
|
-
Dictionary of collections
|
|
466
|
-
"""
|
|
467
|
-
try:
|
|
468
|
-
settings = self.load_settings()
|
|
469
|
-
return settings.get("collections", {})
|
|
470
|
-
except Exception as e:
|
|
471
|
-
self.logger.error(f"Error getting cURL collections: {e}")
|
|
472
|
-
return {}
|
|
473
|
-
|
|
474
|
-
def delete_collection(self, name: str) -> bool:
|
|
475
|
-
"""
|
|
476
|
-
Delete a saved collection.
|
|
477
|
-
|
|
478
|
-
Args:
|
|
479
|
-
name: Collection name
|
|
480
|
-
|
|
481
|
-
Returns:
|
|
482
|
-
True if successful, False otherwise
|
|
483
|
-
"""
|
|
484
|
-
try:
|
|
485
|
-
settings = self.load_settings()
|
|
486
|
-
collections = settings.get("collections", {})
|
|
487
|
-
|
|
488
|
-
if name in collections:
|
|
489
|
-
del collections[name]
|
|
490
|
-
self.database_manager.set_tool_setting(self.tool_key, "collections", collections)
|
|
491
|
-
return True
|
|
492
|
-
else:
|
|
493
|
-
self.logger.warning(f"Collection not found: {name}")
|
|
494
|
-
return False
|
|
495
|
-
|
|
496
|
-
except Exception as e:
|
|
497
|
-
self.logger.error(f"Error deleting cURL collection {name}: {e}")
|
|
498
|
-
return False
|
|
499
|
-
|
|
500
|
-
# Private validation methods
|
|
501
|
-
|
|
502
|
-
def _validate_settings(self, settings: Dict[str, Any]) -> bool:
|
|
503
|
-
"""
|
|
504
|
-
Validate settings dictionary.
|
|
505
|
-
|
|
506
|
-
Args:
|
|
507
|
-
settings: Settings dictionary to validate
|
|
508
|
-
|
|
509
|
-
Returns:
|
|
510
|
-
True if valid, False otherwise
|
|
511
|
-
"""
|
|
512
|
-
try:
|
|
513
|
-
# Ensure required keys exist
|
|
514
|
-
for key, default_value in self.default_settings.items():
|
|
515
|
-
if key not in settings:
|
|
516
|
-
settings[key] = default_value
|
|
517
|
-
|
|
518
|
-
# Validate specific settings
|
|
519
|
-
if not isinstance(settings.get("max_history_items"), int) or settings["max_history_items"] < 1:
|
|
520
|
-
settings["max_history_items"] = 100
|
|
521
|
-
|
|
522
|
-
if not isinstance(settings.get("default_timeout"), (int, float)) or settings["default_timeout"] < 1:
|
|
523
|
-
settings["default_timeout"] = 30
|
|
524
|
-
|
|
525
|
-
if not isinstance(settings.get("max_redirects"), int) or settings["max_redirects"] < 0:
|
|
526
|
-
settings["max_redirects"] = 10
|
|
527
|
-
|
|
528
|
-
# Ensure history is a list
|
|
529
|
-
if not isinstance(settings.get("history"), list):
|
|
530
|
-
settings["history"] = []
|
|
531
|
-
|
|
532
|
-
# Ensure collections is a dict
|
|
533
|
-
if not isinstance(settings.get("collections"), dict):
|
|
534
|
-
settings["collections"] = {}
|
|
535
|
-
|
|
536
|
-
return True
|
|
537
|
-
|
|
538
|
-
except Exception as e:
|
|
539
|
-
self.logger.error(f"Error validating cURL settings: {e}")
|
|
540
|
-
return False
|
|
541
|
-
|
|
542
|
-
def _validate_setting(self, key: str, value: Any) -> bool:
|
|
543
|
-
"""
|
|
544
|
-
Validate a single setting value.
|
|
545
|
-
|
|
546
|
-
Args:
|
|
547
|
-
key: Setting key
|
|
548
|
-
value: Setting value
|
|
549
|
-
|
|
550
|
-
Returns:
|
|
551
|
-
True if valid, False otherwise
|
|
552
|
-
"""
|
|
553
|
-
try:
|
|
554
|
-
# Type validation based on key
|
|
555
|
-
if key in ["max_history_items", "max_redirects", "retry_attempts", "connection_pool_size"]:
|
|
556
|
-
return isinstance(value, int) and value >= 0
|
|
557
|
-
|
|
558
|
-
elif key in ["default_timeout", "retry_delay_seconds"]:
|
|
559
|
-
return isinstance(value, (int, float)) and value > 0
|
|
560
|
-
|
|
561
|
-
elif key in ["follow_redirects", "verify_ssl", "save_history", "auto_cleanup_history"]:
|
|
562
|
-
return isinstance(value, bool)
|
|
563
|
-
|
|
564
|
-
elif key in ["user_agent", "default_download_path", "curl_export_format", "complex_options"]:
|
|
565
|
-
return isinstance(value, str)
|
|
566
|
-
|
|
567
|
-
elif key in ["history", "MODELS_LIST"]:
|
|
568
|
-
return isinstance(value, list)
|
|
569
|
-
|
|
570
|
-
elif key in ["collections"]:
|
|
571
|
-
return isinstance(value, dict)
|
|
572
|
-
|
|
573
|
-
else:
|
|
574
|
-
# Allow any value for unknown keys
|
|
575
|
-
return True
|
|
576
|
-
|
|
577
|
-
except Exception as e:
|
|
578
|
-
self.logger.error(f"Error validating cURL setting {key}: {e}")
|
|
579
|
-
return False
|
|
580
|
-
|
|
581
|
-
# Property for backward compatibility
|
|
582
|
-
@property
|
|
583
|
-
def settings(self) -> Dict[str, Any]:
|
|
584
|
-
"""
|
|
585
|
-
Get current settings as a dictionary.
|
|
586
|
-
|
|
587
|
-
This property maintains backward compatibility with code that accesses
|
|
588
|
-
settings_manager.settings directly.
|
|
589
|
-
|
|
590
|
-
Returns:
|
|
591
|
-
Current settings dictionary
|
|
592
|
-
"""
|
|
593
|
-
return self.load_settings()
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
# Factory function for creating database-compatible cURL settings manager
|
|
597
|
-
def create_database_curl_settings_manager(database_settings_manager: DatabaseSettingsManager,
|
|
598
|
-
logger=None) -> DatabaseCurlSettingsManager:
|
|
599
|
-
"""
|
|
600
|
-
Create a database-compatible cURL settings manager.
|
|
601
|
-
|
|
602
|
-
Args:
|
|
603
|
-
database_settings_manager: DatabaseSettingsManager instance
|
|
604
|
-
logger: Optional logger instance
|
|
605
|
-
|
|
606
|
-
Returns:
|
|
607
|
-
DatabaseCurlSettingsManager instance
|
|
608
|
-
"""
|
|
1
|
+
"""
|
|
2
|
+
Database-Compatible cURL Tool Settings Management Module
|
|
3
|
+
|
|
4
|
+
This module provides an updated CurlSettingsManager that works with the database backend
|
|
5
|
+
while maintaining full backward compatibility with the existing interface.
|
|
6
|
+
|
|
7
|
+
Author: Pomera AI Commander
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
import os
|
|
12
|
+
from typing import Dict, List, Any, Optional
|
|
13
|
+
import logging
|
|
14
|
+
from datetime import datetime
|
|
15
|
+
|
|
16
|
+
from .database_settings_manager import DatabaseSettingsManager
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class DatabaseCurlSettingsManager:
|
|
20
|
+
"""
|
|
21
|
+
Database-compatible settings manager for the cURL Tool.
|
|
22
|
+
|
|
23
|
+
This class maintains the same interface as the original CurlSettingsManager
|
|
24
|
+
but uses the database backend for improved concurrency and data integrity.
|
|
25
|
+
|
|
26
|
+
Handles:
|
|
27
|
+
- Settings persistence through database backend
|
|
28
|
+
- Default configuration values
|
|
29
|
+
- Settings validation
|
|
30
|
+
- Configuration backup and restore
|
|
31
|
+
- Full backward compatibility with existing cURL tool code
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def __init__(self, database_settings_manager: DatabaseSettingsManager, logger=None):
|
|
35
|
+
"""
|
|
36
|
+
Initialize the database-compatible cURL settings manager.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
database_settings_manager: DatabaseSettingsManager instance
|
|
40
|
+
logger: Logger instance for debugging
|
|
41
|
+
"""
|
|
42
|
+
self.database_manager = database_settings_manager
|
|
43
|
+
self.logger = logger or logging.getLogger(__name__)
|
|
44
|
+
self.tool_key = "cURL Tool" # Key in tool_settings section
|
|
45
|
+
|
|
46
|
+
# Default settings configuration (same as original)
|
|
47
|
+
self.default_settings = {
|
|
48
|
+
# Request settings
|
|
49
|
+
"default_timeout": 30,
|
|
50
|
+
"follow_redirects": True,
|
|
51
|
+
"verify_ssl": True,
|
|
52
|
+
"max_redirects": 10,
|
|
53
|
+
"user_agent": "Pomera cURL Tool/1.0",
|
|
54
|
+
|
|
55
|
+
# History settings
|
|
56
|
+
"save_history": True,
|
|
57
|
+
"max_history_items": 100,
|
|
58
|
+
"auto_cleanup_history": True,
|
|
59
|
+
"history_retention_days": 30,
|
|
60
|
+
"history": [], # Request history array
|
|
61
|
+
"collections": {}, # Request collections
|
|
62
|
+
"history_last_updated": None,
|
|
63
|
+
|
|
64
|
+
# Authentication settings
|
|
65
|
+
"persist_auth": True,
|
|
66
|
+
"auth_timeout_minutes": 60,
|
|
67
|
+
"clear_auth_on_exit": False,
|
|
68
|
+
|
|
69
|
+
# UI settings
|
|
70
|
+
"remember_window_size": True,
|
|
71
|
+
"default_body_type": "JSON",
|
|
72
|
+
"auto_format_json": True,
|
|
73
|
+
"syntax_highlighting": True,
|
|
74
|
+
"show_response_time": True,
|
|
75
|
+
|
|
76
|
+
# Download settings
|
|
77
|
+
"default_download_path": "",
|
|
78
|
+
"use_remote_filename": True,
|
|
79
|
+
"resume_downloads": True,
|
|
80
|
+
"download_chunk_size": 8192,
|
|
81
|
+
|
|
82
|
+
# Export/Import settings
|
|
83
|
+
"curl_export_format": "standard", # standard, minimal, verbose
|
|
84
|
+
"include_comments_in_export": True,
|
|
85
|
+
"auto_escape_special_chars": True,
|
|
86
|
+
"complex_options": "", # Additional cURL options not handled by UI
|
|
87
|
+
|
|
88
|
+
# Debug settings
|
|
89
|
+
"enable_debug_logging": False,
|
|
90
|
+
"log_request_headers": True,
|
|
91
|
+
"log_response_headers": True,
|
|
92
|
+
"max_log_size_mb": 10,
|
|
93
|
+
|
|
94
|
+
# Advanced settings
|
|
95
|
+
"connection_pool_size": 10,
|
|
96
|
+
"retry_attempts": 3,
|
|
97
|
+
"retry_delay_seconds": 1,
|
|
98
|
+
"enable_http2": False,
|
|
99
|
+
|
|
100
|
+
# Version and metadata
|
|
101
|
+
"settings_version": "1.0",
|
|
102
|
+
"last_updated": None,
|
|
103
|
+
"created_date": None
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
# Initialize settings if they don't exist
|
|
107
|
+
self._initialize_settings()
|
|
108
|
+
|
|
109
|
+
def _initialize_settings(self) -> None:
|
|
110
|
+
"""Initialize cURL tool settings if they don't exist in database."""
|
|
111
|
+
try:
|
|
112
|
+
# Check if tool settings exist
|
|
113
|
+
existing_settings = self.database_manager.get_tool_settings(self.tool_key)
|
|
114
|
+
|
|
115
|
+
if not existing_settings:
|
|
116
|
+
# Initialize with defaults
|
|
117
|
+
self.logger.info("Initializing cURL tool settings with defaults")
|
|
118
|
+
default_with_timestamp = self.default_settings.copy()
|
|
119
|
+
default_with_timestamp["created_date"] = datetime.now().isoformat()
|
|
120
|
+
default_with_timestamp["last_updated"] = datetime.now().isoformat()
|
|
121
|
+
|
|
122
|
+
# Set tool settings in database
|
|
123
|
+
for key, value in default_with_timestamp.items():
|
|
124
|
+
self.database_manager.set_tool_setting(self.tool_key, key, value)
|
|
125
|
+
else:
|
|
126
|
+
# Ensure all default keys exist (for backward compatibility)
|
|
127
|
+
self._ensure_all_defaults_exist(existing_settings)
|
|
128
|
+
|
|
129
|
+
except Exception as e:
|
|
130
|
+
self.logger.error(f"Failed to initialize cURL settings: {e}")
|
|
131
|
+
|
|
132
|
+
def _ensure_all_defaults_exist(self, existing_settings: Dict[str, Any]) -> None:
|
|
133
|
+
"""Ensure all default settings exist, adding missing ones."""
|
|
134
|
+
try:
|
|
135
|
+
missing_keys = set(self.default_settings.keys()) - set(existing_settings.keys())
|
|
136
|
+
|
|
137
|
+
if missing_keys:
|
|
138
|
+
self.logger.info(f"Adding missing cURL settings: {missing_keys}")
|
|
139
|
+
for key in missing_keys:
|
|
140
|
+
self.database_manager.set_tool_setting(self.tool_key, key, self.default_settings[key])
|
|
141
|
+
|
|
142
|
+
# Update last_updated timestamp
|
|
143
|
+
self.database_manager.set_tool_setting(self.tool_key, "last_updated", datetime.now().isoformat())
|
|
144
|
+
|
|
145
|
+
except Exception as e:
|
|
146
|
+
self.logger.error(f"Failed to ensure default settings: {e}")
|
|
147
|
+
|
|
148
|
+
# Backward Compatible API Methods
|
|
149
|
+
|
|
150
|
+
def load_settings(self) -> Dict[str, Any]:
|
|
151
|
+
"""
|
|
152
|
+
Load settings from database backend.
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
Dictionary of current settings
|
|
156
|
+
"""
|
|
157
|
+
try:
|
|
158
|
+
settings = self.database_manager.get_tool_settings(self.tool_key)
|
|
159
|
+
|
|
160
|
+
if not settings:
|
|
161
|
+
# Return defaults if no settings found
|
|
162
|
+
settings = self.default_settings.copy()
|
|
163
|
+
settings["created_date"] = datetime.now().isoformat()
|
|
164
|
+
self.logger.info("No cURL settings found, using defaults")
|
|
165
|
+
|
|
166
|
+
# Validate and fix any invalid settings
|
|
167
|
+
self._validate_settings(settings)
|
|
168
|
+
|
|
169
|
+
self.logger.debug(f"cURL Tool settings loaded from database")
|
|
170
|
+
return settings
|
|
171
|
+
|
|
172
|
+
except Exception as e:
|
|
173
|
+
self.logger.error(f"Error loading cURL settings: {e}")
|
|
174
|
+
# Fall back to defaults
|
|
175
|
+
settings = self.default_settings.copy()
|
|
176
|
+
settings["created_date"] = datetime.now().isoformat()
|
|
177
|
+
return settings
|
|
178
|
+
|
|
179
|
+
def save_settings(self, settings_dict: Optional[Dict[str, Any]] = None) -> bool:
|
|
180
|
+
"""
|
|
181
|
+
Save current settings to database backend.
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
settings_dict: Optional settings dictionary to save
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
True if successful, False otherwise
|
|
188
|
+
"""
|
|
189
|
+
try:
|
|
190
|
+
if settings_dict is None:
|
|
191
|
+
# If no specific settings provided, this is a no-op since database is always current
|
|
192
|
+
return True
|
|
193
|
+
|
|
194
|
+
# Update last modified timestamp
|
|
195
|
+
settings_dict["last_updated"] = datetime.now().isoformat()
|
|
196
|
+
|
|
197
|
+
# Save each setting to database
|
|
198
|
+
for key, value in settings_dict.items():
|
|
199
|
+
self.database_manager.set_tool_setting(self.tool_key, key, value)
|
|
200
|
+
|
|
201
|
+
self.logger.debug(f"cURL Tool settings saved to database")
|
|
202
|
+
return True
|
|
203
|
+
|
|
204
|
+
except Exception as e:
|
|
205
|
+
self.logger.error(f"Error saving cURL settings: {e}")
|
|
206
|
+
return False
|
|
207
|
+
|
|
208
|
+
def get_setting(self, key: str, default: Any = None) -> Any:
|
|
209
|
+
"""
|
|
210
|
+
Get a setting value.
|
|
211
|
+
|
|
212
|
+
Args:
|
|
213
|
+
key: Setting key
|
|
214
|
+
default: Default value if key not found
|
|
215
|
+
|
|
216
|
+
Returns:
|
|
217
|
+
Setting value or default
|
|
218
|
+
"""
|
|
219
|
+
try:
|
|
220
|
+
settings = self.database_manager.get_tool_settings(self.tool_key)
|
|
221
|
+
return settings.get(key, default)
|
|
222
|
+
except Exception as e:
|
|
223
|
+
self.logger.error(f"Error getting cURL setting {key}: {e}")
|
|
224
|
+
return default
|
|
225
|
+
|
|
226
|
+
def set_setting(self, key: str, value: Any) -> bool:
|
|
227
|
+
"""
|
|
228
|
+
Set a setting value.
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
key: Setting key
|
|
232
|
+
value: Setting value
|
|
233
|
+
|
|
234
|
+
Returns:
|
|
235
|
+
True if successful, False otherwise
|
|
236
|
+
"""
|
|
237
|
+
try:
|
|
238
|
+
# Validate the setting
|
|
239
|
+
if self._validate_setting(key, value):
|
|
240
|
+
self.database_manager.set_tool_setting(self.tool_key, key, value)
|
|
241
|
+
# Update timestamp
|
|
242
|
+
self.database_manager.set_tool_setting(self.tool_key, "last_updated", datetime.now().isoformat())
|
|
243
|
+
return True
|
|
244
|
+
else:
|
|
245
|
+
self.logger.warning(f"Invalid cURL setting value: {key} = {value}")
|
|
246
|
+
return False
|
|
247
|
+
|
|
248
|
+
except Exception as e:
|
|
249
|
+
self.logger.error(f"Error setting cURL setting {key}: {e}")
|
|
250
|
+
return False
|
|
251
|
+
|
|
252
|
+
def reset_to_defaults(self) -> bool:
|
|
253
|
+
"""
|
|
254
|
+
Reset all settings to defaults.
|
|
255
|
+
|
|
256
|
+
Returns:
|
|
257
|
+
True if successful, False otherwise
|
|
258
|
+
"""
|
|
259
|
+
try:
|
|
260
|
+
# Get current creation date if it exists
|
|
261
|
+
current_settings = self.database_manager.get_tool_settings(self.tool_key)
|
|
262
|
+
created_date = current_settings.get("created_date") if current_settings else None
|
|
263
|
+
|
|
264
|
+
# Reset to defaults
|
|
265
|
+
defaults = self.default_settings.copy()
|
|
266
|
+
if created_date:
|
|
267
|
+
defaults["created_date"] = created_date
|
|
268
|
+
defaults["last_updated"] = datetime.now().isoformat()
|
|
269
|
+
|
|
270
|
+
# Save defaults to database
|
|
271
|
+
return self.save_settings(defaults)
|
|
272
|
+
|
|
273
|
+
except Exception as e:
|
|
274
|
+
self.logger.error(f"Error resetting cURL settings: {e}")
|
|
275
|
+
return False
|
|
276
|
+
|
|
277
|
+
def export_settings(self, filepath: str) -> bool:
|
|
278
|
+
"""
|
|
279
|
+
Export settings to a file.
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
filepath: Path to export file
|
|
283
|
+
|
|
284
|
+
Returns:
|
|
285
|
+
True if successful, False otherwise
|
|
286
|
+
"""
|
|
287
|
+
try:
|
|
288
|
+
settings = self.load_settings()
|
|
289
|
+
|
|
290
|
+
with open(filepath, 'w', encoding='utf-8') as f:
|
|
291
|
+
json.dump(settings, f, indent=4, ensure_ascii=False)
|
|
292
|
+
|
|
293
|
+
self.logger.info(f"cURL settings exported to {filepath}")
|
|
294
|
+
return True
|
|
295
|
+
|
|
296
|
+
except Exception as e:
|
|
297
|
+
self.logger.error(f"Error exporting cURL settings: {e}")
|
|
298
|
+
return False
|
|
299
|
+
|
|
300
|
+
def import_settings(self, filepath: str) -> bool:
|
|
301
|
+
"""
|
|
302
|
+
Import settings from a file.
|
|
303
|
+
|
|
304
|
+
Args:
|
|
305
|
+
filepath: Path to import file
|
|
306
|
+
|
|
307
|
+
Returns:
|
|
308
|
+
True if successful, False otherwise
|
|
309
|
+
"""
|
|
310
|
+
try:
|
|
311
|
+
if not os.path.exists(filepath):
|
|
312
|
+
self.logger.error(f"Import file not found: {filepath}")
|
|
313
|
+
return False
|
|
314
|
+
|
|
315
|
+
with open(filepath, 'r', encoding='utf-8') as f:
|
|
316
|
+
imported_settings = json.load(f)
|
|
317
|
+
|
|
318
|
+
# Validate imported settings
|
|
319
|
+
if self._validate_settings(imported_settings):
|
|
320
|
+
imported_settings["last_updated"] = datetime.now().isoformat()
|
|
321
|
+
return self.save_settings(imported_settings)
|
|
322
|
+
else:
|
|
323
|
+
self.logger.error("Invalid settings in import file")
|
|
324
|
+
return False
|
|
325
|
+
|
|
326
|
+
except Exception as e:
|
|
327
|
+
self.logger.error(f"Error importing cURL settings: {e}")
|
|
328
|
+
return False
|
|
329
|
+
|
|
330
|
+
def create_backup(self) -> Optional[str]:
|
|
331
|
+
"""
|
|
332
|
+
Create a backup of current settings.
|
|
333
|
+
|
|
334
|
+
Returns:
|
|
335
|
+
Path to backup file if successful, None otherwise
|
|
336
|
+
"""
|
|
337
|
+
try:
|
|
338
|
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
339
|
+
backup_path = f"curl_tool_settings_backup_{timestamp}.json"
|
|
340
|
+
|
|
341
|
+
if self.export_settings(backup_path):
|
|
342
|
+
self.logger.info(f"cURL settings backup created: {backup_path}")
|
|
343
|
+
return backup_path
|
|
344
|
+
else:
|
|
345
|
+
return None
|
|
346
|
+
|
|
347
|
+
except Exception as e:
|
|
348
|
+
self.logger.error(f"Error creating cURL settings backup: {e}")
|
|
349
|
+
return None
|
|
350
|
+
|
|
351
|
+
def restore_backup(self, backup_path: str) -> bool:
|
|
352
|
+
"""
|
|
353
|
+
Restore settings from a backup file.
|
|
354
|
+
|
|
355
|
+
Args:
|
|
356
|
+
backup_path: Path to backup file
|
|
357
|
+
|
|
358
|
+
Returns:
|
|
359
|
+
True if successful, False otherwise
|
|
360
|
+
"""
|
|
361
|
+
return self.import_settings(backup_path)
|
|
362
|
+
|
|
363
|
+
# History Management Methods (cURL-specific)
|
|
364
|
+
|
|
365
|
+
def add_history_entry(self, entry: Dict[str, Any]) -> bool:
|
|
366
|
+
"""
|
|
367
|
+
Add an entry to the request history.
|
|
368
|
+
|
|
369
|
+
Args:
|
|
370
|
+
entry: History entry dictionary
|
|
371
|
+
|
|
372
|
+
Returns:
|
|
373
|
+
True if successful, False otherwise
|
|
374
|
+
"""
|
|
375
|
+
try:
|
|
376
|
+
settings = self.load_settings()
|
|
377
|
+
history = settings.get("history", [])
|
|
378
|
+
|
|
379
|
+
# Add timestamp if not present
|
|
380
|
+
if "timestamp" not in entry:
|
|
381
|
+
entry["timestamp"] = datetime.now().isoformat()
|
|
382
|
+
|
|
383
|
+
# Add to beginning of history
|
|
384
|
+
history.insert(0, entry)
|
|
385
|
+
|
|
386
|
+
# Limit history size
|
|
387
|
+
max_items = settings.get("max_history_items", 100)
|
|
388
|
+
if len(history) > max_items:
|
|
389
|
+
history = history[:max_items]
|
|
390
|
+
|
|
391
|
+
# Update database
|
|
392
|
+
self.database_manager.set_tool_setting(self.tool_key, "history", history)
|
|
393
|
+
self.database_manager.set_tool_setting(self.tool_key, "history_last_updated", datetime.now().isoformat())
|
|
394
|
+
|
|
395
|
+
return True
|
|
396
|
+
|
|
397
|
+
except Exception as e:
|
|
398
|
+
self.logger.error(f"Error adding cURL history entry: {e}")
|
|
399
|
+
return False
|
|
400
|
+
|
|
401
|
+
def get_history(self) -> List[Dict[str, Any]]:
|
|
402
|
+
"""
|
|
403
|
+
Get the request history.
|
|
404
|
+
|
|
405
|
+
Returns:
|
|
406
|
+
List of history entries
|
|
407
|
+
"""
|
|
408
|
+
try:
|
|
409
|
+
settings = self.load_settings()
|
|
410
|
+
return settings.get("history", [])
|
|
411
|
+
except Exception as e:
|
|
412
|
+
self.logger.error(f"Error getting cURL history: {e}")
|
|
413
|
+
return []
|
|
414
|
+
|
|
415
|
+
def clear_history(self) -> bool:
|
|
416
|
+
"""
|
|
417
|
+
Clear the request history.
|
|
418
|
+
|
|
419
|
+
Returns:
|
|
420
|
+
True if successful, False otherwise
|
|
421
|
+
"""
|
|
422
|
+
try:
|
|
423
|
+
self.database_manager.set_tool_setting(self.tool_key, "history", [])
|
|
424
|
+
self.database_manager.set_tool_setting(self.tool_key, "history_last_updated", datetime.now().isoformat())
|
|
425
|
+
return True
|
|
426
|
+
except Exception as e:
|
|
427
|
+
self.logger.error(f"Error clearing cURL history: {e}")
|
|
428
|
+
return False
|
|
429
|
+
|
|
430
|
+
# Collections Management Methods (cURL-specific)
|
|
431
|
+
|
|
432
|
+
def save_collection(self, name: str, requests: List[Dict[str, Any]]) -> bool:
|
|
433
|
+
"""
|
|
434
|
+
Save a collection of requests.
|
|
435
|
+
|
|
436
|
+
Args:
|
|
437
|
+
name: Collection name
|
|
438
|
+
requests: List of request dictionaries
|
|
439
|
+
|
|
440
|
+
Returns:
|
|
441
|
+
True if successful, False otherwise
|
|
442
|
+
"""
|
|
443
|
+
try:
|
|
444
|
+
settings = self.load_settings()
|
|
445
|
+
collections = settings.get("collections", {})
|
|
446
|
+
|
|
447
|
+
collections[name] = {
|
|
448
|
+
"requests": requests,
|
|
449
|
+
"created": datetime.now().isoformat(),
|
|
450
|
+
"modified": datetime.now().isoformat()
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
self.database_manager.set_tool_setting(self.tool_key, "collections", collections)
|
|
454
|
+
return True
|
|
455
|
+
|
|
456
|
+
except Exception as e:
|
|
457
|
+
self.logger.error(f"Error saving cURL collection {name}: {e}")
|
|
458
|
+
return False
|
|
459
|
+
|
|
460
|
+
def get_collections(self) -> Dict[str, Any]:
|
|
461
|
+
"""
|
|
462
|
+
Get all saved collections.
|
|
463
|
+
|
|
464
|
+
Returns:
|
|
465
|
+
Dictionary of collections
|
|
466
|
+
"""
|
|
467
|
+
try:
|
|
468
|
+
settings = self.load_settings()
|
|
469
|
+
return settings.get("collections", {})
|
|
470
|
+
except Exception as e:
|
|
471
|
+
self.logger.error(f"Error getting cURL collections: {e}")
|
|
472
|
+
return {}
|
|
473
|
+
|
|
474
|
+
def delete_collection(self, name: str) -> bool:
|
|
475
|
+
"""
|
|
476
|
+
Delete a saved collection.
|
|
477
|
+
|
|
478
|
+
Args:
|
|
479
|
+
name: Collection name
|
|
480
|
+
|
|
481
|
+
Returns:
|
|
482
|
+
True if successful, False otherwise
|
|
483
|
+
"""
|
|
484
|
+
try:
|
|
485
|
+
settings = self.load_settings()
|
|
486
|
+
collections = settings.get("collections", {})
|
|
487
|
+
|
|
488
|
+
if name in collections:
|
|
489
|
+
del collections[name]
|
|
490
|
+
self.database_manager.set_tool_setting(self.tool_key, "collections", collections)
|
|
491
|
+
return True
|
|
492
|
+
else:
|
|
493
|
+
self.logger.warning(f"Collection not found: {name}")
|
|
494
|
+
return False
|
|
495
|
+
|
|
496
|
+
except Exception as e:
|
|
497
|
+
self.logger.error(f"Error deleting cURL collection {name}: {e}")
|
|
498
|
+
return False
|
|
499
|
+
|
|
500
|
+
# Private validation methods
|
|
501
|
+
|
|
502
|
+
def _validate_settings(self, settings: Dict[str, Any]) -> bool:
|
|
503
|
+
"""
|
|
504
|
+
Validate settings dictionary.
|
|
505
|
+
|
|
506
|
+
Args:
|
|
507
|
+
settings: Settings dictionary to validate
|
|
508
|
+
|
|
509
|
+
Returns:
|
|
510
|
+
True if valid, False otherwise
|
|
511
|
+
"""
|
|
512
|
+
try:
|
|
513
|
+
# Ensure required keys exist
|
|
514
|
+
for key, default_value in self.default_settings.items():
|
|
515
|
+
if key not in settings:
|
|
516
|
+
settings[key] = default_value
|
|
517
|
+
|
|
518
|
+
# Validate specific settings
|
|
519
|
+
if not isinstance(settings.get("max_history_items"), int) or settings["max_history_items"] < 1:
|
|
520
|
+
settings["max_history_items"] = 100
|
|
521
|
+
|
|
522
|
+
if not isinstance(settings.get("default_timeout"), (int, float)) or settings["default_timeout"] < 1:
|
|
523
|
+
settings["default_timeout"] = 30
|
|
524
|
+
|
|
525
|
+
if not isinstance(settings.get("max_redirects"), int) or settings["max_redirects"] < 0:
|
|
526
|
+
settings["max_redirects"] = 10
|
|
527
|
+
|
|
528
|
+
# Ensure history is a list
|
|
529
|
+
if not isinstance(settings.get("history"), list):
|
|
530
|
+
settings["history"] = []
|
|
531
|
+
|
|
532
|
+
# Ensure collections is a dict
|
|
533
|
+
if not isinstance(settings.get("collections"), dict):
|
|
534
|
+
settings["collections"] = {}
|
|
535
|
+
|
|
536
|
+
return True
|
|
537
|
+
|
|
538
|
+
except Exception as e:
|
|
539
|
+
self.logger.error(f"Error validating cURL settings: {e}")
|
|
540
|
+
return False
|
|
541
|
+
|
|
542
|
+
def _validate_setting(self, key: str, value: Any) -> bool:
|
|
543
|
+
"""
|
|
544
|
+
Validate a single setting value.
|
|
545
|
+
|
|
546
|
+
Args:
|
|
547
|
+
key: Setting key
|
|
548
|
+
value: Setting value
|
|
549
|
+
|
|
550
|
+
Returns:
|
|
551
|
+
True if valid, False otherwise
|
|
552
|
+
"""
|
|
553
|
+
try:
|
|
554
|
+
# Type validation based on key
|
|
555
|
+
if key in ["max_history_items", "max_redirects", "retry_attempts", "connection_pool_size"]:
|
|
556
|
+
return isinstance(value, int) and value >= 0
|
|
557
|
+
|
|
558
|
+
elif key in ["default_timeout", "retry_delay_seconds"]:
|
|
559
|
+
return isinstance(value, (int, float)) and value > 0
|
|
560
|
+
|
|
561
|
+
elif key in ["follow_redirects", "verify_ssl", "save_history", "auto_cleanup_history"]:
|
|
562
|
+
return isinstance(value, bool)
|
|
563
|
+
|
|
564
|
+
elif key in ["user_agent", "default_download_path", "curl_export_format", "complex_options"]:
|
|
565
|
+
return isinstance(value, str)
|
|
566
|
+
|
|
567
|
+
elif key in ["history", "MODELS_LIST"]:
|
|
568
|
+
return isinstance(value, list)
|
|
569
|
+
|
|
570
|
+
elif key in ["collections"]:
|
|
571
|
+
return isinstance(value, dict)
|
|
572
|
+
|
|
573
|
+
else:
|
|
574
|
+
# Allow any value for unknown keys
|
|
575
|
+
return True
|
|
576
|
+
|
|
577
|
+
except Exception as e:
|
|
578
|
+
self.logger.error(f"Error validating cURL setting {key}: {e}")
|
|
579
|
+
return False
|
|
580
|
+
|
|
581
|
+
# Property for backward compatibility
|
|
582
|
+
@property
|
|
583
|
+
def settings(self) -> Dict[str, Any]:
|
|
584
|
+
"""
|
|
585
|
+
Get current settings as a dictionary.
|
|
586
|
+
|
|
587
|
+
This property maintains backward compatibility with code that accesses
|
|
588
|
+
settings_manager.settings directly.
|
|
589
|
+
|
|
590
|
+
Returns:
|
|
591
|
+
Current settings dictionary
|
|
592
|
+
"""
|
|
593
|
+
return self.load_settings()
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
# Factory function for creating database-compatible cURL settings manager
|
|
597
|
+
def create_database_curl_settings_manager(database_settings_manager: DatabaseSettingsManager,
|
|
598
|
+
logger=None) -> DatabaseCurlSettingsManager:
|
|
599
|
+
"""
|
|
600
|
+
Create a database-compatible cURL settings manager.
|
|
601
|
+
|
|
602
|
+
Args:
|
|
603
|
+
database_settings_manager: DatabaseSettingsManager instance
|
|
604
|
+
logger: Optional logger instance
|
|
605
|
+
|
|
606
|
+
Returns:
|
|
607
|
+
DatabaseCurlSettingsManager instance
|
|
608
|
+
"""
|
|
609
609
|
return DatabaseCurlSettingsManager(database_settings_manager, logger)
|