cursorflow 2.7.1__tar.gz → 2.7.2__tar.gz
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.
- {cursorflow-2.7.1 → cursorflow-2.7.2}/PKG-INFO +1 -1
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/cli.py +19 -11
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/output_manager.py +186 -70
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/query_engine.py +2 -5
- {cursorflow-2.7.1 → cursorflow-2.7.2}/pyproject.toml +1 -1
- {cursorflow-2.7.1 → cursorflow-2.7.2}/LICENSE +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/MANIFEST.in +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/README.md +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/__init__.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/auto_init.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/auto_updater.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/action_validator.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/agent.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/auth_handler.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/browser_controller.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/browser_engine.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/config_validator.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/css_iterator.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/cursor_integration.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/cursorflow.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/data_presenter.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/error_context_collector.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/error_correlator.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/event_correlator.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/file_change_monitor.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/hmr_detector.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/json_utils.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/log_collector.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/log_monitor.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/mockup_comparator.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/persistent_session.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/report_generator.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/core/trace_manager.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/install_cursorflow_rules.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/log_sources/local_file.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/log_sources/ssh_remote.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/post_install.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/rules/__init__.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/rules/cursorflow-installation.mdc +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/rules/cursorflow-usage.mdc +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow/updater.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/cursorflow.egg-info/SOURCES.txt +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/docs/user/USAGE_GUIDE.md +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/examples/comprehensive_screenshot_example.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/examples/element_inspection_example.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/examples/element_measurement_example.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/examples/enhanced_screenshot_example.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/examples/hot_reload_css_iteration.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/examples/mockup_comparison_example.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/examples/opensas_example.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/examples/react_example.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/examples/responsive_testing_example.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/examples/v2_comprehensive_demo.py +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/setup.cfg +0 -0
- {cursorflow-2.7.1 → cursorflow-2.7.2}/setup.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: cursorflow
|
3
|
-
Version: 2.7.
|
3
|
+
Version: 2.7.2
|
4
4
|
Summary: 🔥 Complete page intelligence for AI-driven development with Hot Reload Intelligence - captures DOM, network, console, performance, HMR events, and comprehensive page analysis
|
5
5
|
Author-email: GeekWarrior Development <rbush@cooltheory.com>
|
6
6
|
License-Expression: MIT
|
@@ -1151,6 +1151,8 @@ def inspect(base_url, path, selector, verbose):
|
|
1151
1151
|
results = asyncio.run(flow.execute_and_collect([
|
1152
1152
|
{"navigate": path},
|
1153
1153
|
{"wait_for_selector": "body"},
|
1154
|
+
{"wait_for_load_state": "networkidle"}, # Wait for dynamic content
|
1155
|
+
{"wait_for_timeout": 1000}, # Additional buffer for JS rendering (1s)
|
1154
1156
|
{"screenshot": "inspection"}
|
1155
1157
|
]))
|
1156
1158
|
|
@@ -1200,7 +1202,7 @@ def inspect(base_url, path, selector, verbose):
|
|
1200
1202
|
console.print(f"Classes: [blue].{classes}[/blue]")
|
1201
1203
|
|
1202
1204
|
# Selectors
|
1203
|
-
unique_selector = element.get('uniqueSelector', 'N/A')
|
1205
|
+
unique_selector = escape(str(element.get('uniqueSelector', 'N/A')))
|
1204
1206
|
console.print(f"Unique: [cyan]{unique_selector}[/cyan]")
|
1205
1207
|
|
1206
1208
|
# Dimensions
|
@@ -1216,20 +1218,22 @@ def inspect(base_url, path, selector, verbose):
|
|
1216
1218
|
console.print(f"\n🎨 Key CSS Properties:")
|
1217
1219
|
|
1218
1220
|
# Layout
|
1219
|
-
display = computed.get('display', 'N/A')
|
1220
|
-
position = computed.get('position', 'N/A')
|
1221
|
+
display = escape(str(computed.get('display', 'N/A')))
|
1222
|
+
position = escape(str(computed.get('position', 'N/A')))
|
1221
1223
|
console.print(f" display: {display}")
|
1222
1224
|
console.print(f" position: {position}")
|
1223
1225
|
|
1224
1226
|
# Flexbox
|
1225
1227
|
if 'flex' in computed:
|
1226
|
-
|
1228
|
+
flex_value = escape(str(computed.get('flex', 'N/A')))
|
1229
|
+
console.print(f" flex: {flex_value}")
|
1227
1230
|
if 'flexBasis' in computed:
|
1228
|
-
|
1231
|
+
flex_basis = escape(str(computed.get('flexBasis', 'N/A')))
|
1232
|
+
console.print(f" flex-basis: {flex_basis}")
|
1229
1233
|
|
1230
1234
|
# Dimensions
|
1231
|
-
width = computed.get('width', 'N/A')
|
1232
|
-
height = computed.get('height', 'N/A')
|
1235
|
+
width = escape(str(computed.get('width', 'N/A')))
|
1236
|
+
height = escape(str(computed.get('height', 'N/A')))
|
1233
1237
|
console.print(f" width: {width}")
|
1234
1238
|
console.print(f" height: {height}")
|
1235
1239
|
|
@@ -1237,20 +1241,23 @@ def inspect(base_url, path, selector, verbose):
|
|
1237
1241
|
margin = computed.get('margin', 'N/A')
|
1238
1242
|
padding = computed.get('padding', 'N/A')
|
1239
1243
|
if margin != 'N/A':
|
1244
|
+
margin = escape(str(margin))
|
1240
1245
|
console.print(f" margin: {margin}")
|
1241
1246
|
if padding != 'N/A':
|
1247
|
+
padding = escape(str(padding))
|
1242
1248
|
console.print(f" padding: {padding}")
|
1243
1249
|
|
1244
1250
|
# Show all styles in verbose mode
|
1245
1251
|
if verbose:
|
1246
1252
|
console.print(f"\n📋 All Computed Styles:")
|
1247
1253
|
for prop, value in sorted(computed.items())[:30]: # Limit to 30
|
1248
|
-
|
1254
|
+
safe_value = escape(str(value))
|
1255
|
+
console.print(f" {prop}: {safe_value}")
|
1249
1256
|
|
1250
1257
|
# Accessibility info
|
1251
1258
|
accessibility = element.get('accessibility', {})
|
1252
1259
|
if accessibility:
|
1253
|
-
role = accessibility.get('role', 'N/A')
|
1260
|
+
role = escape(str(accessibility.get('role', 'N/A')))
|
1254
1261
|
is_interactive = accessibility.get('isInteractive', False)
|
1255
1262
|
console.print(f"\n♿ Accessibility:")
|
1256
1263
|
console.print(f" Role: {role}")
|
@@ -1293,8 +1300,9 @@ def inspect(base_url, path, selector, verbose):
|
|
1293
1300
|
|
1294
1301
|
except Exception as e:
|
1295
1302
|
console.print(f"[red]❌ Inspection failed: {escape(str(e))}[/red]")
|
1296
|
-
|
1297
|
-
|
1303
|
+
if verbose:
|
1304
|
+
import traceback
|
1305
|
+
console.print(escape(traceback.format_exc()))
|
1298
1306
|
|
1299
1307
|
def _element_matches_selector(element: Dict, selector: str) -> bool:
|
1300
1308
|
"""Check if element matches the given selector"""
|
@@ -146,31 +146,28 @@ class OutputManager:
|
|
146
146
|
|
147
147
|
def _extract_summary(self, results: Dict) -> Dict:
|
148
148
|
"""Extract high-level summary data"""
|
149
|
-
comprehensive
|
149
|
+
# Load comprehensive data from disk if available
|
150
|
+
comprehensive = self._load_comprehensive_data(results)
|
150
151
|
artifacts = results.get('artifacts', {})
|
151
152
|
|
152
|
-
# Count errors
|
153
|
+
# Count errors from comprehensive_data
|
153
154
|
error_count = 0
|
154
155
|
warning_count = 0
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
error_count += len(errors.get('logs', []))
|
161
|
-
warnings = console_data.get('warnings', {})
|
162
|
-
warning_count += len(warnings.get('logs', []))
|
156
|
+
if comprehensive:
|
157
|
+
console_data = comprehensive.get('console_data', {})
|
158
|
+
all_console_logs = console_data.get('all_console_logs', [])
|
159
|
+
error_count = len([log for log in all_console_logs if log.get('type') == 'error'])
|
160
|
+
warning_count = len([log for log in all_console_logs if log.get('type') == 'warning'])
|
163
161
|
|
164
|
-
# Count network requests
|
162
|
+
# Count network requests from comprehensive_data
|
165
163
|
network_count = 0
|
166
164
|
failed_network_count = 0
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
failed_network_count += len(failed_requests.get('requests', []))
|
165
|
+
if comprehensive:
|
166
|
+
network_data = comprehensive.get('network_data', {})
|
167
|
+
all_network_events = network_data.get('all_network_events', [])
|
168
|
+
network_count = len(all_network_events)
|
169
|
+
# Count failures (4xx, 5xx)
|
170
|
+
failed_network_count = len([req for req in all_network_events if req.get('status', 0) >= 400])
|
174
171
|
|
175
172
|
# Count DOM elements
|
176
173
|
dom_element_count = 0
|
@@ -202,26 +199,50 @@ class OutputManager:
|
|
202
199
|
|
203
200
|
def _extract_errors(self, results: Dict) -> Dict:
|
204
201
|
"""Extract all error data with context"""
|
205
|
-
artifacts = results.get('artifacts', {})
|
206
202
|
errors = []
|
207
203
|
|
208
|
-
#
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
204
|
+
# Load comprehensive data from disk if available
|
205
|
+
comprehensive_data = self._load_comprehensive_data(results)
|
206
|
+
|
207
|
+
if comprehensive_data:
|
208
|
+
console_data = comprehensive_data.get('console_data', {})
|
209
|
+
all_console_logs = console_data.get('all_console_logs', [])
|
210
|
+
|
211
|
+
# Filter for errors
|
212
|
+
for log in all_console_logs:
|
213
|
+
if log.get('type') == 'error':
|
214
|
+
# Extract location info if present
|
215
|
+
location = log.get('location', {})
|
215
216
|
errors.append({
|
216
|
-
"message":
|
217
|
-
"source":
|
218
|
-
"line":
|
219
|
-
"column":
|
220
|
-
"stack_trace":
|
221
|
-
"timestamp":
|
222
|
-
"screenshot_name":
|
223
|
-
"url":
|
217
|
+
"message": log.get('text', ''),
|
218
|
+
"source": location.get('url', ''),
|
219
|
+
"line": location.get('lineNumber', 0),
|
220
|
+
"column": location.get('columnNumber', 0),
|
221
|
+
"stack_trace": log.get('stackTrace', {}).get('callFrames', []),
|
222
|
+
"timestamp": log.get('timestamp', 0),
|
223
|
+
"screenshot_name": 'comprehensive',
|
224
|
+
"url": location.get('url', '')
|
224
225
|
})
|
226
|
+
else:
|
227
|
+
# Fallback: Collect errors from screenshot artifacts (old structure)
|
228
|
+
# Only if comprehensive_data not available
|
229
|
+
artifacts = results.get('artifacts', {})
|
230
|
+
for screenshot in artifacts.get('screenshots', []):
|
231
|
+
if isinstance(screenshot, dict):
|
232
|
+
console_data = screenshot.get('console_data', {})
|
233
|
+
error_logs = console_data.get('errors', {}).get('logs', [])
|
234
|
+
|
235
|
+
for error in error_logs:
|
236
|
+
errors.append({
|
237
|
+
"message": error.get('message', ''),
|
238
|
+
"source": error.get('source', ''),
|
239
|
+
"line": error.get('line', 0),
|
240
|
+
"column": error.get('column', 0),
|
241
|
+
"stack_trace": error.get('stack_trace', ''),
|
242
|
+
"timestamp": screenshot.get('timestamp', 0),
|
243
|
+
"screenshot_name": screenshot.get('name', 'unknown'),
|
244
|
+
"url": screenshot.get('url', '')
|
245
|
+
})
|
225
246
|
|
226
247
|
# Organize by error type
|
227
248
|
error_types = {}
|
@@ -243,29 +264,55 @@ class OutputManager:
|
|
243
264
|
|
244
265
|
def _extract_network(self, results: Dict) -> Dict:
|
245
266
|
"""Extract network request/response data"""
|
246
|
-
artifacts = results.get('artifacts', {})
|
247
267
|
all_requests = []
|
248
268
|
failed_requests = []
|
249
269
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
270
|
+
# Load comprehensive data from disk if available
|
271
|
+
comprehensive_data = self._load_comprehensive_data(results)
|
272
|
+
|
273
|
+
if comprehensive_data:
|
274
|
+
network_data = comprehensive_data.get('network_data', {})
|
275
|
+
all_network_events = network_data.get('all_network_events', [])
|
276
|
+
|
277
|
+
# Add all network events and identify failures
|
278
|
+
for event in all_network_events:
|
279
|
+
request_data = {
|
280
|
+
"url": event.get('url', ''),
|
281
|
+
"method": event.get('method', 'GET'),
|
282
|
+
"status_code": event.get('status', 0),
|
283
|
+
"timestamp": event.get('timestamp', 0),
|
284
|
+
"timing": event.get('timing', {}),
|
285
|
+
"screenshot_name": 'comprehensive'
|
286
|
+
}
|
287
|
+
all_requests.append(request_data)
|
261
288
|
|
262
|
-
failed
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
289
|
+
# Identify failed requests (4xx, 5xx status codes)
|
290
|
+
status = event.get('status', 0)
|
291
|
+
if status >= 400:
|
292
|
+
failed_requests.append(request_data)
|
293
|
+
else:
|
294
|
+
# Fallback: Collect from screenshot artifacts (old structure)
|
295
|
+
# Only if comprehensive_data not available
|
296
|
+
artifacts = results.get('artifacts', {})
|
297
|
+
for screenshot in artifacts.get('screenshots', []):
|
298
|
+
if isinstance(screenshot, dict):
|
299
|
+
network_data = screenshot.get('network_data', {})
|
300
|
+
requests = network_data.get('requests', [])
|
301
|
+
|
302
|
+
for request in requests:
|
303
|
+
all_requests.append({
|
304
|
+
**request,
|
305
|
+
"screenshot_name": screenshot.get('name', 'unknown'),
|
306
|
+
"timestamp": screenshot.get('timestamp', 0)
|
307
|
+
})
|
308
|
+
|
309
|
+
failed = network_data.get('failed_requests', {}).get('requests', [])
|
310
|
+
for request in failed:
|
311
|
+
failed_requests.append({
|
312
|
+
**request,
|
313
|
+
"screenshot_name": screenshot.get('name', 'unknown'),
|
314
|
+
"timestamp": screenshot.get('timestamp', 0)
|
315
|
+
})
|
269
316
|
|
270
317
|
# Organize by status code
|
271
318
|
by_status_code = {}
|
@@ -288,24 +335,42 @@ class OutputManager:
|
|
288
335
|
|
289
336
|
def _extract_console(self, results: Dict) -> Dict:
|
290
337
|
"""Extract all console messages"""
|
291
|
-
artifacts = results.get('artifacts', {})
|
292
338
|
all_messages = []
|
293
339
|
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
340
|
+
# Load comprehensive data from disk if available
|
341
|
+
comprehensive_data = self._load_comprehensive_data(results)
|
342
|
+
|
343
|
+
if comprehensive_data:
|
344
|
+
console_data = comprehensive_data.get('console_data', {})
|
345
|
+
all_console_logs = console_data.get('all_console_logs', [])
|
346
|
+
|
347
|
+
for log in all_console_logs:
|
348
|
+
all_messages.append({
|
349
|
+
"type": log.get('type', 'log'),
|
350
|
+
"message": log.get('text', ''),
|
351
|
+
"source": log.get('location', {}).get('url', ''),
|
352
|
+
"timestamp": log.get('timestamp', 0),
|
353
|
+
"screenshot_name": 'comprehensive'
|
354
|
+
})
|
355
|
+
else:
|
356
|
+
# Fallback: Collect from screenshot artifacts (old structure)
|
357
|
+
# Only if comprehensive_data not available
|
358
|
+
artifacts = results.get('artifacts', {})
|
359
|
+
for screenshot in artifacts.get('screenshots', []):
|
360
|
+
if isinstance(screenshot, dict):
|
361
|
+
console_data = screenshot.get('console_data', {})
|
362
|
+
|
363
|
+
# Collect all message types
|
364
|
+
for msg_type in ['errors', 'warnings', 'logs', 'info']:
|
365
|
+
messages = console_data.get(msg_type, {}).get('logs', [])
|
366
|
+
for msg in messages:
|
367
|
+
all_messages.append({
|
368
|
+
"type": msg_type,
|
369
|
+
"message": msg.get('message', ''),
|
370
|
+
"source": msg.get('source', ''),
|
371
|
+
"timestamp": screenshot.get('timestamp', 0),
|
372
|
+
"screenshot_name": screenshot.get('name', 'unknown')
|
373
|
+
})
|
309
374
|
|
310
375
|
# Organize by type
|
311
376
|
by_type = {}
|
@@ -335,9 +400,22 @@ class OutputManager:
|
|
335
400
|
|
336
401
|
def _extract_performance(self, results: Dict) -> Dict:
|
337
402
|
"""Extract performance metrics"""
|
338
|
-
artifacts = results.get('artifacts', {})
|
339
403
|
performance_data = []
|
340
404
|
|
405
|
+
# Load comprehensive data from disk if available
|
406
|
+
comprehensive = self._load_comprehensive_data(results)
|
407
|
+
|
408
|
+
if comprehensive and 'performance_data' in comprehensive:
|
409
|
+
perf = comprehensive.get('performance_data', {})
|
410
|
+
if perf:
|
411
|
+
performance_data.append({
|
412
|
+
"screenshot_name": 'comprehensive',
|
413
|
+
"timestamp": results.get('execution_time', 0),
|
414
|
+
"metrics": perf
|
415
|
+
})
|
416
|
+
|
417
|
+
# Fallback: from screenshot artifacts
|
418
|
+
artifacts = results.get('artifacts', {})
|
341
419
|
for screenshot in artifacts.get('screenshots', []):
|
342
420
|
if isinstance(screenshot, dict):
|
343
421
|
perf = screenshot.get('performance_data', {})
|
@@ -512,6 +590,44 @@ class OutputManager:
|
|
512
590
|
"min_memory_usage": min(memory_usage) if memory_usage else 0
|
513
591
|
}
|
514
592
|
|
593
|
+
def _load_comprehensive_data(self, results: Dict) -> Dict:
|
594
|
+
"""Load comprehensive data from disk or from results dict"""
|
595
|
+
# First try to get from results (if already loaded)
|
596
|
+
comprehensive = results.get('comprehensive_data', {})
|
597
|
+
if comprehensive:
|
598
|
+
return comprehensive
|
599
|
+
|
600
|
+
# Try to load from disk via screenshot artifacts
|
601
|
+
artifacts = results.get('artifacts', {})
|
602
|
+
screenshots = artifacts.get('screenshots', [])
|
603
|
+
|
604
|
+
if screenshots:
|
605
|
+
last_screenshot = screenshots[-1]
|
606
|
+
# Check if comprehensive_data_path is set
|
607
|
+
if isinstance(last_screenshot, dict) and 'comprehensive_data_path' in last_screenshot:
|
608
|
+
comp_path = Path(last_screenshot['comprehensive_data_path'])
|
609
|
+
if comp_path.exists():
|
610
|
+
try:
|
611
|
+
with open(comp_path, 'r', encoding='utf-8') as f:
|
612
|
+
return json.load(f)
|
613
|
+
except Exception as e:
|
614
|
+
self.logger.warning(f"Could not load comprehensive data from {comp_path}: {e}")
|
615
|
+
|
616
|
+
# Try to find comprehensive data file by naming convention
|
617
|
+
if isinstance(last_screenshot, dict) and 'path' in last_screenshot:
|
618
|
+
screenshot_path = Path(last_screenshot['path'])
|
619
|
+
if screenshot_path.exists():
|
620
|
+
# Look for companion comprehensive data file
|
621
|
+
comp_path = screenshot_path.parent / f"{screenshot_path.stem}_comprehensive_data.json"
|
622
|
+
if comp_path.exists():
|
623
|
+
try:
|
624
|
+
with open(comp_path, 'r', encoding='utf-8') as f:
|
625
|
+
return json.load(f)
|
626
|
+
except Exception as e:
|
627
|
+
self.logger.warning(f"Could not load comprehensive data from {comp_path}: {e}")
|
628
|
+
|
629
|
+
return {}
|
630
|
+
|
515
631
|
def _write_json(self, path: Path, data: Dict):
|
516
632
|
"""Write JSON data to file with proper formatting"""
|
517
633
|
with open(path, 'w', encoding='utf-8') as f:
|
@@ -317,11 +317,8 @@ class QueryEngine:
|
|
317
317
|
|
318
318
|
# Filter failed requests only
|
319
319
|
if 'failed' in filters and filters['failed']:
|
320
|
-
|
321
|
-
filtered_requests = [
|
322
|
-
req for req in all_requests
|
323
|
-
if req.get('url') in [f.get('url') for f in failed_reqs]
|
324
|
-
]
|
320
|
+
# Use failed_requests array directly (already filtered)
|
321
|
+
filtered_requests = network.get('failed_requests', [])
|
325
322
|
|
326
323
|
# Phase 1: Enhanced network filtering
|
327
324
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "cursorflow"
|
7
|
-
version = "2.7.
|
7
|
+
version = "2.7.2"
|
8
8
|
description = "🔥 Complete page intelligence for AI-driven development with Hot Reload Intelligence - captures DOM, network, console, performance, HMR events, and comprehensive page analysis"
|
9
9
|
authors = [
|
10
10
|
{name = "GeekWarrior Development", email = "rbush@cooltheory.com"}
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|