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