pomera-ai-commander 0.1.0 → 1.2.1

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.
Files changed (191) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +105 -680
  3. package/bin/pomera-ai-commander.js +62 -62
  4. package/core/__init__.py +65 -65
  5. package/core/app_context.py +482 -482
  6. package/core/async_text_processor.py +421 -421
  7. package/core/backup_manager.py +655 -655
  8. package/core/backup_recovery_manager.py +1033 -1033
  9. package/core/content_hash_cache.py +508 -508
  10. package/core/context_menu.py +313 -313
  11. package/core/data_validator.py +1066 -1066
  12. package/core/database_connection_manager.py +744 -744
  13. package/core/database_curl_settings_manager.py +608 -608
  14. package/core/database_promera_ai_settings_manager.py +446 -446
  15. package/core/database_schema.py +411 -411
  16. package/core/database_schema_manager.py +395 -395
  17. package/core/database_settings_manager.py +1507 -1507
  18. package/core/database_settings_manager_interface.py +456 -456
  19. package/core/dialog_manager.py +734 -734
  20. package/core/efficient_line_numbers.py +510 -510
  21. package/core/error_handler.py +746 -746
  22. package/core/error_service.py +431 -431
  23. package/core/event_consolidator.py +511 -511
  24. package/core/mcp/__init__.py +43 -43
  25. package/core/mcp/protocol.py +288 -288
  26. package/core/mcp/schema.py +251 -251
  27. package/core/mcp/server_stdio.py +299 -299
  28. package/core/mcp/tool_registry.py +2372 -2345
  29. package/core/memory_efficient_text_widget.py +711 -711
  30. package/core/migration_manager.py +914 -914
  31. package/core/migration_test_suite.py +1085 -1085
  32. package/core/migration_validator.py +1143 -1143
  33. package/core/optimized_find_replace.py +714 -714
  34. package/core/optimized_pattern_engine.py +424 -424
  35. package/core/optimized_search_highlighter.py +552 -552
  36. package/core/performance_monitor.py +674 -674
  37. package/core/persistence_manager.py +712 -712
  38. package/core/progressive_stats_calculator.py +632 -632
  39. package/core/regex_pattern_cache.py +529 -529
  40. package/core/regex_pattern_library.py +350 -350
  41. package/core/search_operation_manager.py +434 -434
  42. package/core/settings_defaults_registry.py +1087 -1087
  43. package/core/settings_integrity_validator.py +1111 -1111
  44. package/core/settings_serializer.py +557 -557
  45. package/core/settings_validator.py +1823 -1823
  46. package/core/smart_stats_calculator.py +709 -709
  47. package/core/statistics_update_manager.py +619 -619
  48. package/core/stats_config_manager.py +858 -858
  49. package/core/streaming_text_handler.py +723 -723
  50. package/core/task_scheduler.py +596 -596
  51. package/core/update_pattern_library.py +168 -168
  52. package/core/visibility_monitor.py +596 -596
  53. package/core/widget_cache.py +498 -498
  54. package/mcp.json +51 -61
  55. package/package.json +61 -57
  56. package/pomera.py +7482 -7482
  57. package/pomera_mcp_server.py +183 -144
  58. package/requirements.txt +32 -0
  59. package/tools/__init__.py +4 -4
  60. package/tools/ai_tools.py +2891 -2891
  61. package/tools/ascii_art_generator.py +352 -352
  62. package/tools/base64_tools.py +183 -183
  63. package/tools/base_tool.py +511 -511
  64. package/tools/case_tool.py +308 -308
  65. package/tools/column_tools.py +395 -395
  66. package/tools/cron_tool.py +884 -884
  67. package/tools/curl_history.py +600 -600
  68. package/tools/curl_processor.py +1207 -1207
  69. package/tools/curl_settings.py +502 -502
  70. package/tools/curl_tool.py +5467 -5467
  71. package/tools/diff_viewer.py +1071 -1071
  72. package/tools/email_extraction_tool.py +248 -248
  73. package/tools/email_header_analyzer.py +425 -425
  74. package/tools/extraction_tools.py +250 -250
  75. package/tools/find_replace.py +1750 -1750
  76. package/tools/folder_file_reporter.py +1463 -1463
  77. package/tools/folder_file_reporter_adapter.py +480 -480
  78. package/tools/generator_tools.py +1216 -1216
  79. package/tools/hash_generator.py +255 -255
  80. package/tools/html_tool.py +656 -656
  81. package/tools/jsonxml_tool.py +729 -729
  82. package/tools/line_tools.py +419 -419
  83. package/tools/markdown_tools.py +561 -561
  84. package/tools/mcp_widget.py +1417 -1417
  85. package/tools/notes_widget.py +973 -973
  86. package/tools/number_base_converter.py +372 -372
  87. package/tools/regex_extractor.py +571 -571
  88. package/tools/slug_generator.py +310 -310
  89. package/tools/sorter_tools.py +458 -458
  90. package/tools/string_escape_tool.py +392 -392
  91. package/tools/text_statistics_tool.py +365 -365
  92. package/tools/text_wrapper.py +430 -430
  93. package/tools/timestamp_converter.py +421 -421
  94. package/tools/tool_loader.py +710 -710
  95. package/tools/translator_tools.py +522 -522
  96. package/tools/url_link_extractor.py +261 -261
  97. package/tools/url_parser.py +204 -204
  98. package/tools/whitespace_tools.py +355 -355
  99. package/tools/word_frequency_counter.py +146 -146
  100. package/core/__pycache__/__init__.cpython-313.pyc +0 -0
  101. package/core/__pycache__/app_context.cpython-313.pyc +0 -0
  102. package/core/__pycache__/async_text_processor.cpython-313.pyc +0 -0
  103. package/core/__pycache__/backup_manager.cpython-313.pyc +0 -0
  104. package/core/__pycache__/backup_recovery_manager.cpython-313.pyc +0 -0
  105. package/core/__pycache__/content_hash_cache.cpython-313.pyc +0 -0
  106. package/core/__pycache__/context_menu.cpython-313.pyc +0 -0
  107. package/core/__pycache__/data_validator.cpython-313.pyc +0 -0
  108. package/core/__pycache__/database_connection_manager.cpython-313.pyc +0 -0
  109. package/core/__pycache__/database_curl_settings_manager.cpython-313.pyc +0 -0
  110. package/core/__pycache__/database_promera_ai_settings_manager.cpython-313.pyc +0 -0
  111. package/core/__pycache__/database_schema.cpython-313.pyc +0 -0
  112. package/core/__pycache__/database_schema_manager.cpython-313.pyc +0 -0
  113. package/core/__pycache__/database_settings_manager.cpython-313.pyc +0 -0
  114. package/core/__pycache__/database_settings_manager_interface.cpython-313.pyc +0 -0
  115. package/core/__pycache__/dialog_manager.cpython-313.pyc +0 -0
  116. package/core/__pycache__/efficient_line_numbers.cpython-313.pyc +0 -0
  117. package/core/__pycache__/error_handler.cpython-313.pyc +0 -0
  118. package/core/__pycache__/error_service.cpython-313.pyc +0 -0
  119. package/core/__pycache__/event_consolidator.cpython-313.pyc +0 -0
  120. package/core/__pycache__/memory_efficient_text_widget.cpython-313.pyc +0 -0
  121. package/core/__pycache__/migration_manager.cpython-313.pyc +0 -0
  122. package/core/__pycache__/migration_test_suite.cpython-313.pyc +0 -0
  123. package/core/__pycache__/migration_validator.cpython-313.pyc +0 -0
  124. package/core/__pycache__/optimized_find_replace.cpython-313.pyc +0 -0
  125. package/core/__pycache__/optimized_pattern_engine.cpython-313.pyc +0 -0
  126. package/core/__pycache__/optimized_search_highlighter.cpython-313.pyc +0 -0
  127. package/core/__pycache__/performance_monitor.cpython-313.pyc +0 -0
  128. package/core/__pycache__/persistence_manager.cpython-313.pyc +0 -0
  129. package/core/__pycache__/progressive_stats_calculator.cpython-313.pyc +0 -0
  130. package/core/__pycache__/regex_pattern_cache.cpython-313.pyc +0 -0
  131. package/core/__pycache__/regex_pattern_library.cpython-313.pyc +0 -0
  132. package/core/__pycache__/search_operation_manager.cpython-313.pyc +0 -0
  133. package/core/__pycache__/settings_defaults_registry.cpython-313.pyc +0 -0
  134. package/core/__pycache__/settings_integrity_validator.cpython-313.pyc +0 -0
  135. package/core/__pycache__/settings_serializer.cpython-313.pyc +0 -0
  136. package/core/__pycache__/settings_validator.cpython-313.pyc +0 -0
  137. package/core/__pycache__/smart_stats_calculator.cpython-313.pyc +0 -0
  138. package/core/__pycache__/statistics_update_manager.cpython-313.pyc +0 -0
  139. package/core/__pycache__/stats_config_manager.cpython-313.pyc +0 -0
  140. package/core/__pycache__/streaming_text_handler.cpython-313.pyc +0 -0
  141. package/core/__pycache__/task_scheduler.cpython-313.pyc +0 -0
  142. package/core/__pycache__/visibility_monitor.cpython-313.pyc +0 -0
  143. package/core/__pycache__/widget_cache.cpython-313.pyc +0 -0
  144. package/core/mcp/__pycache__/__init__.cpython-313.pyc +0 -0
  145. package/core/mcp/__pycache__/protocol.cpython-313.pyc +0 -0
  146. package/core/mcp/__pycache__/schema.cpython-313.pyc +0 -0
  147. package/core/mcp/__pycache__/server_stdio.cpython-313.pyc +0 -0
  148. package/core/mcp/__pycache__/tool_registry.cpython-313.pyc +0 -0
  149. package/tools/__pycache__/__init__.cpython-313.pyc +0 -0
  150. package/tools/__pycache__/ai_tools.cpython-313.pyc +0 -0
  151. package/tools/__pycache__/ascii_art_generator.cpython-313.pyc +0 -0
  152. package/tools/__pycache__/base64_tools.cpython-313.pyc +0 -0
  153. package/tools/__pycache__/base_tool.cpython-313.pyc +0 -0
  154. package/tools/__pycache__/case_tool.cpython-313.pyc +0 -0
  155. package/tools/__pycache__/column_tools.cpython-313.pyc +0 -0
  156. package/tools/__pycache__/cron_tool.cpython-313.pyc +0 -0
  157. package/tools/__pycache__/curl_history.cpython-313.pyc +0 -0
  158. package/tools/__pycache__/curl_processor.cpython-313.pyc +0 -0
  159. package/tools/__pycache__/curl_settings.cpython-313.pyc +0 -0
  160. package/tools/__pycache__/curl_tool.cpython-313.pyc +0 -0
  161. package/tools/__pycache__/diff_viewer.cpython-313.pyc +0 -0
  162. package/tools/__pycache__/email_extraction_tool.cpython-313.pyc +0 -0
  163. package/tools/__pycache__/email_header_analyzer.cpython-313.pyc +0 -0
  164. package/tools/__pycache__/extraction_tools.cpython-313.pyc +0 -0
  165. package/tools/__pycache__/find_replace.cpython-313.pyc +0 -0
  166. package/tools/__pycache__/folder_file_reporter.cpython-313.pyc +0 -0
  167. package/tools/__pycache__/folder_file_reporter_adapter.cpython-313.pyc +0 -0
  168. package/tools/__pycache__/generator_tools.cpython-313.pyc +0 -0
  169. package/tools/__pycache__/hash_generator.cpython-313.pyc +0 -0
  170. package/tools/__pycache__/html_tool.cpython-313.pyc +0 -0
  171. package/tools/__pycache__/huggingface_helper.cpython-313.pyc +0 -0
  172. package/tools/__pycache__/jsonxml_tool.cpython-313.pyc +0 -0
  173. package/tools/__pycache__/line_tools.cpython-313.pyc +0 -0
  174. package/tools/__pycache__/list_comparator.cpython-313.pyc +0 -0
  175. package/tools/__pycache__/markdown_tools.cpython-313.pyc +0 -0
  176. package/tools/__pycache__/mcp_widget.cpython-313.pyc +0 -0
  177. package/tools/__pycache__/notes_widget.cpython-313.pyc +0 -0
  178. package/tools/__pycache__/number_base_converter.cpython-313.pyc +0 -0
  179. package/tools/__pycache__/regex_extractor.cpython-313.pyc +0 -0
  180. package/tools/__pycache__/slug_generator.cpython-313.pyc +0 -0
  181. package/tools/__pycache__/sorter_tools.cpython-313.pyc +0 -0
  182. package/tools/__pycache__/string_escape_tool.cpython-313.pyc +0 -0
  183. package/tools/__pycache__/text_statistics_tool.cpython-313.pyc +0 -0
  184. package/tools/__pycache__/text_wrapper.cpython-313.pyc +0 -0
  185. package/tools/__pycache__/timestamp_converter.cpython-313.pyc +0 -0
  186. package/tools/__pycache__/tool_loader.cpython-313.pyc +0 -0
  187. package/tools/__pycache__/translator_tools.cpython-313.pyc +0 -0
  188. package/tools/__pycache__/url_link_extractor.cpython-313.pyc +0 -0
  189. package/tools/__pycache__/url_parser.cpython-313.pyc +0 -0
  190. package/tools/__pycache__/whitespace_tools.cpython-313.pyc +0 -0
  191. 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)