webtap-tool 0.7.1__tar.gz → 0.8.0__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.
Potentially problematic release.
This version of webtap-tool might be problematic. Click here for more details.
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/CHANGELOG.md +54 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/PKG-INFO +1 -1
- webtap_tool-0.8.0/docs/summaries/HANDOFF_2025-10-16.md +237 -0
- webtap_tool-0.8.0/extension/background.js +63 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/extension/manifest.json +10 -1
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/extension/sidepanel.html +31 -10
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/extension/sidepanel.js +150 -102
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/pyproject.toml +1 -1
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/__init__.py +4 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/api.py +50 -57
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/app.py +5 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/cdp/session.py +77 -25
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/commands/TIPS.md +125 -22
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/commands/_builders.py +7 -1
- webtap_tool-0.8.0/src/webtap/commands/_code_generation.py +110 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/commands/body.py +9 -5
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/commands/connection.py +21 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/commands/javascript.py +13 -25
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/commands/navigation.py +5 -0
- webtap_tool-0.8.0/src/webtap/commands/quicktype.py +268 -0
- webtap_tool-0.8.0/src/webtap/commands/to_model.py +84 -0
- webtap_tool-0.8.0/src/webtap/services/body.py +298 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/services/dom.py +19 -12
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/services/fetch.py +19 -0
- webtap_tool-0.8.0/src/webtap/services/main.py +381 -0
- webtap_tool-0.8.0/src/webtap/services/state_snapshot.py +88 -0
- webtap_tool-0.7.1/src/webtap/commands/to_model.py +0 -136
- webtap_tool-0.7.1/src/webtap/services/body.py +0 -113
- webtap_tool-0.7.1/src/webtap/services/main.py +0 -189
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/.gitignore +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/ARCHITECTURE.md +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/README.md +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/data/filters.json +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/extension/content.js +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/llms.txt +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/VISION.md +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/cdp/README.md +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/cdp/__init__.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/cdp/query.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/cdp/schema/README.md +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/cdp/schema/cdp_protocol.json +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/cdp/schema/cdp_version.json +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/commands/DEVELOPER_GUIDE.md +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/commands/__init__.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/commands/_tips.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/commands/_utils.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/commands/console.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/commands/events.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/commands/fetch.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/commands/filters.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/commands/inspect.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/commands/launch.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/commands/network.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/commands/selections.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/commands/server.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/commands/setup.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/filters.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/services/README.md +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/services/__init__.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/services/console.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/services/network.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/services/setup/__init__.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/services/setup/chrome.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/services/setup/desktop.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/services/setup/extension.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/services/setup/filters.py +0 -0
- {webtap_tool-0.7.1 → webtap_tool-0.8.0}/src/webtap/services/setup/platform.py +0 -0
|
@@ -15,6 +15,60 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
15
15
|
|
|
16
16
|
### Removed
|
|
17
17
|
|
|
18
|
+
## [0.8.0] - 2025-10-16
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
- **quicktype command**: Generate types for TypeScript, Go, Rust, Python, and 10+ languages from request/response bodies
|
|
22
|
+
- Auto-detects language from file extension (.ts, .go, .rs, etc.)
|
|
23
|
+
- Supports all quicktype CLI options via `options` dict parameter
|
|
24
|
+
- Language-aware header comments with event metadata
|
|
25
|
+
- Supports `expr` and `json_path` for data transformation
|
|
26
|
+
- **Request body support**: `body()` and `to_model()` now work with POST/PUT/PATCH requests
|
|
27
|
+
- Auto-detects `Network.requestWillBeSent` events and fetches POST data
|
|
28
|
+
- Returns event data for `expr` evaluation on any CDP event type
|
|
29
|
+
- **Code generation utilities**: New `_code_generation.py` module with shared transformation functions
|
|
30
|
+
- `parse_json()`, `extract_json_path()`, `validate_generation_data()`, `ensure_output_directory()`
|
|
31
|
+
- **BodyService.prepare_for_generation()**: Orchestrator method reducing duplication (2 queries → 1, 166 duplicate lines → 0)
|
|
32
|
+
- **Extension reload button**: Manual page list refresh for when auto-refresh doesn't update
|
|
33
|
+
- **Tips system**: Added contextual tips to `page()` and `pages()` commands from TIPS.md
|
|
34
|
+
- **Response builders**: `info_response()` now supports `tips` parameter (matches `table_response()`)
|
|
35
|
+
- **Extension UI**: Context menu for switching between sidepanel and popup window modes
|
|
36
|
+
- **Background service worker**: Manages UI mode switching and sidepanel close functionality
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
- **State management**: Immutable snapshot architecture for thread-safe SSE broadcasting
|
|
40
|
+
- New `StateSnapshot` frozen dataclass with atomic updates
|
|
41
|
+
- `WebTapService._create_snapshot()` and `_trigger_broadcast()` replace direct broadcasts
|
|
42
|
+
- All service mutations trigger snapshot updates via RLock-protected operations
|
|
43
|
+
- **CDPSession lifecycle**: DB thread now persists across connections (only dies on app exit)
|
|
44
|
+
- `disconnect()` preserves DB thread and events for reconnection
|
|
45
|
+
- New `cleanup()` method for proper app exit (stops DB thread)
|
|
46
|
+
- Added `atexit` hook for automatic cleanup on process termination
|
|
47
|
+
- Events persist across disconnect/reconnect cycles (cleared only by Clear button or exit)
|
|
48
|
+
- **Unexpected disconnect handling**: Preserves events for debugging instead of clearing
|
|
49
|
+
- `_handle_unexpected_disconnect()` no longer calls `clear_events()`
|
|
50
|
+
- Enhanced error messages for None close codes
|
|
51
|
+
- **Service layer**: Broadcast queue ownership moved to `WebTapService` with callback pattern
|
|
52
|
+
- `DOMService` and `FetchService` now use `_broadcast_callback` instead of direct queue access
|
|
53
|
+
- **Extension safety**: All dynamic HTML uses safe DOM creation instead of `innerHTML`
|
|
54
|
+
- New `showError()` and `showMessage()` helpers with auto-escaping
|
|
55
|
+
- Replaced UTF-8 cross (✕) with pure CSS icon
|
|
56
|
+
- **to_model command**: Refactored to use `body_service.prepare_for_generation()` (170 → 85 lines)
|
|
57
|
+
- Added `expr` parameter for custom transformations
|
|
58
|
+
- Parameter renamed from `response` to `event`
|
|
59
|
+
- **body command**: Renamed internal `get_response_body()` to `get_body()` with auto-detection
|
|
60
|
+
- Parameter renamed from `response` to `event`
|
|
61
|
+
|
|
62
|
+
### Fixed
|
|
63
|
+
- **Critical reconnection bug**: Page crashes now allow immediate reconnection
|
|
64
|
+
- `CDPSession._on_close()` clears `ws_app` and `page_info` state after detecting unexpected disconnect
|
|
65
|
+
- Previously "Already connected" error prevented reconnection after page kill
|
|
66
|
+
- **Error messages**: Fixed "Connection closed unexpectedly (code None)" → "Connection lost (page closed or crashed)"
|
|
67
|
+
- **Extension concurrency**: Added global operation lock to prevent concurrent button operations
|
|
68
|
+
- **SSE error handling**: Shows reconnect button instead of generic error message
|
|
69
|
+
|
|
70
|
+
### Removed
|
|
71
|
+
|
|
18
72
|
## [0.7.1] - 2025-10-12
|
|
19
73
|
|
|
20
74
|
### Added
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# WebTap Refactoring Session - October 16, 2025
|
|
2
|
+
|
|
3
|
+
## Accomplishments
|
|
4
|
+
|
|
5
|
+
### 🏗️ Major Architecture Refactoring
|
|
6
|
+
Completed a clean-break refactoring of the code generation pipeline, eliminating duplicate code and improving maintainability:
|
|
7
|
+
|
|
8
|
+
**Files Created:**
|
|
9
|
+
- `commands/_code_generation.py` - Pure transformation utilities (parse_json, extract_json_path, validate_generation_data, ensure_output_directory)
|
|
10
|
+
|
|
11
|
+
**Files Modified:**
|
|
12
|
+
- `services/body.py` - Enhanced BodyService with:
|
|
13
|
+
- `get_body()` now returns event_data (eliminates duplicate queries)
|
|
14
|
+
- `prepare_for_generation()` - new orchestration method for full data preparation pipeline
|
|
15
|
+
- Permissive handling of unknown event types (returns empty body with event for expr)
|
|
16
|
+
|
|
17
|
+
- `commands/to_model.py` - Refactored from 170→85 lines (50% reduction)
|
|
18
|
+
- `commands/quicktype.py` - Refactored from 272→187 lines (31% reduction)
|
|
19
|
+
|
|
20
|
+
**Key Improvements:**
|
|
21
|
+
- **Eliminated 166 duplicate lines** across both commands
|
|
22
|
+
- **Reduced DuckDB queries by 50%** (2→1 per generation call)
|
|
23
|
+
- **Universal expr support** - works with ANY CDP event type (WebSocket, Service Workers, etc.)
|
|
24
|
+
- **Language-aware headers** - quicktype auto-generates commented headers with event metadata
|
|
25
|
+
|
|
26
|
+
### 🔧 Pipeline Enhancements
|
|
27
|
+
|
|
28
|
+
**1. Empty Body Validation Reordering**
|
|
29
|
+
- Moved empty body check inside JSON parsing path
|
|
30
|
+
- `expr` now bypasses empty validation - can extract from events with no HTTP body
|
|
31
|
+
- Enables WebSocket frame support: `expr="json.loads(event['params']['response']['payloadData'])"`
|
|
32
|
+
|
|
33
|
+
**2. Universal Event Support**
|
|
34
|
+
- `get_body()` no longer rejects unknown event types
|
|
35
|
+
- Returns empty body + full event for expr to process
|
|
36
|
+
- Works with WebSocket frames, Service Workers, and future CDP events
|
|
37
|
+
|
|
38
|
+
**3. Code Generation Headers**
|
|
39
|
+
- Added configurable `HEADER_TEMPLATE` constant in quicktype.py
|
|
40
|
+
- Auto-detects language from extension
|
|
41
|
+
- Applies correct comment syntax (// for TS/Go/Rust, # for Python/Ruby)
|
|
42
|
+
- Includes event metadata: event_id, URL, method, timestamp
|
|
43
|
+
|
|
44
|
+
### 📚 Documentation Updates
|
|
45
|
+
|
|
46
|
+
**TIPS.md Enhanced:**
|
|
47
|
+
- Added request body examples for both `to_model()` and `quicktype()`
|
|
48
|
+
- Documented how to find POST events: `events({"method": "Network.requestWillBeSent"})`
|
|
49
|
+
- Explained quicktype `options` dict mapping to CLI flags
|
|
50
|
+
- Added comprehensive `js()` scope behavior documentation (fresh vs persistent)
|
|
51
|
+
- Succinct, practical examples without "supports" language
|
|
52
|
+
|
|
53
|
+
**Code Simplified:**
|
|
54
|
+
- Streamlined `js()` docstring (40→20 lines)
|
|
55
|
+
- Detailed usage patterns moved to TIPS.md
|
|
56
|
+
- Clear separation: docstrings = API contract, TIPS.md = usage patterns
|
|
57
|
+
|
|
58
|
+
## Current Status
|
|
59
|
+
|
|
60
|
+
✅ **Production Ready**
|
|
61
|
+
|
|
62
|
+
- All refactoring complete
|
|
63
|
+
- Linting passed: `ruff check packages/webtap/src/webtap` ✓
|
|
64
|
+
- Type checking passed: `basedpyright packages/webtap/src/webtap` ✓
|
|
65
|
+
- Tested with WebSocket frames (user confirmed working)
|
|
66
|
+
- No breaking changes to public API
|
|
67
|
+
|
|
68
|
+
## Key Files
|
|
69
|
+
|
|
70
|
+
### Architecture
|
|
71
|
+
- `packages/webtap/src/webtap/VISION.md` - Core philosophy: store CDP as-is, transform on-demand
|
|
72
|
+
- `packages/webtap/src/webtap/services/body.py` - Service layer orchestration
|
|
73
|
+
- `packages/webtap/src/webtap/commands/_code_generation.py` - Pure transformation utilities
|
|
74
|
+
|
|
75
|
+
### Modified Commands
|
|
76
|
+
- `packages/webtap/src/webtap/commands/to_model.py` - Pydantic model generation (refactored)
|
|
77
|
+
- `packages/webtap/src/webtap/commands/quicktype.py` - Multi-language type generation (refactored + headers)
|
|
78
|
+
- `packages/webtap/src/webtap/commands/javascript.py` - Simplified docs
|
|
79
|
+
|
|
80
|
+
### Documentation
|
|
81
|
+
- `packages/webtap/src/webtap/commands/TIPS.md` - Updated with request bodies, expr examples, js() scope
|
|
82
|
+
- `packages/webtap/src/webtap/commands/DEVELOPER_GUIDE.md` - No changes needed (general patterns)
|
|
83
|
+
|
|
84
|
+
## Architecture Decisions
|
|
85
|
+
|
|
86
|
+
### Service Layer Owns Orchestration
|
|
87
|
+
**Decision:** `prepare_for_generation()` lives in BodyService, not utils
|
|
88
|
+
|
|
89
|
+
**Rationale:**
|
|
90
|
+
- Service layer designed for orchestration with state access
|
|
91
|
+
- Has CDP session, cache, domain knowledge
|
|
92
|
+
- Utils stay pure (no state dependencies)
|
|
93
|
+
- Easier to test and maintain
|
|
94
|
+
|
|
95
|
+
### Permissive Event Handling
|
|
96
|
+
**Decision:** Unknown event types return empty body + full event (not error)
|
|
97
|
+
|
|
98
|
+
**Rationale:**
|
|
99
|
+
- `expr` becomes universal power move for ANY event
|
|
100
|
+
- No special cases needed for WebSocket/Service Workers
|
|
101
|
+
- Future-proof for new CDP events
|
|
102
|
+
- Clear error guidance suggests using `expr`
|
|
103
|
+
|
|
104
|
+
### Header Generation as Private Method
|
|
105
|
+
**Decision:** `_insert_header()` private method in quicktype.py (not shared util)
|
|
106
|
+
|
|
107
|
+
**Rationale:**
|
|
108
|
+
- Currently quicktype-specific
|
|
109
|
+
- Easy to move to shared utils if to_model needs it later
|
|
110
|
+
- Keeps separation of concerns
|
|
111
|
+
- Template easily customizable (global constant)
|
|
112
|
+
|
|
113
|
+
## Next Steps
|
|
114
|
+
|
|
115
|
+
### Immediate Tasks
|
|
116
|
+
✅ None - system is stable and production ready
|
|
117
|
+
|
|
118
|
+
### Testing Recommendations
|
|
119
|
+
- Test with various event types (WebSocket confirmed working)
|
|
120
|
+
- Verify header generation across all supported languages
|
|
121
|
+
- Test edge cases: empty bodies with expr, binary content, malformed JSON
|
|
122
|
+
|
|
123
|
+
## Future Work
|
|
124
|
+
|
|
125
|
+
### Nice-to-Have Enhancements
|
|
126
|
+
|
|
127
|
+
**1. HAR Export Command** (~100 lines)
|
|
128
|
+
```python
|
|
129
|
+
export_har(output="capture.har", filters={"url": "*api*"})
|
|
130
|
+
```
|
|
131
|
+
- Map CDP events (Network.*) → HAR format
|
|
132
|
+
- Query from DuckDB (already have the data)
|
|
133
|
+
- Straightforward schema mapping
|
|
134
|
+
|
|
135
|
+
**2. Service Worker Commands**
|
|
136
|
+
CDP has dedicated ServiceWorker domain:
|
|
137
|
+
- `service_workers()` - list active workers
|
|
138
|
+
- `dispatch_sync(registration_id, tag)` - trigger sync events
|
|
139
|
+
- `deliver_push(registration_id, data)` - test push notifications
|
|
140
|
+
- Events: `workerRegistrationUpdated`, `workerErrorReported`
|
|
141
|
+
|
|
142
|
+
**3. Header Template for to_model()**
|
|
143
|
+
If users want headers in Pydantic models:
|
|
144
|
+
- Extract `_insert_header()` to `_code_generation.py`
|
|
145
|
+
- Add `HEADER_TEMPLATE` to to_model.py
|
|
146
|
+
- Reuse language detection logic
|
|
147
|
+
|
|
148
|
+
### Refactoring Opportunities
|
|
149
|
+
|
|
150
|
+
**1. Consolidate Language Detection**
|
|
151
|
+
Both `to_model.py` and `quicktype.py` have identical `lang_map` dicts:
|
|
152
|
+
```python
|
|
153
|
+
# Could move to _code_generation.py
|
|
154
|
+
LANGUAGE_MAP = {
|
|
155
|
+
".ts": "TypeScript",
|
|
156
|
+
".py": "Python",
|
|
157
|
+
# ... etc
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
def detect_language(file_path: Path) -> str:
|
|
161
|
+
return LANGUAGE_MAP.get(file_path.suffix.lower(), "Unknown")
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**2. Event Metadata Extraction**
|
|
165
|
+
Header generation queries event data separately - could reuse from `prepare_for_generation()`:
|
|
166
|
+
```python
|
|
167
|
+
# Instead of querying again in _insert_header()
|
|
168
|
+
# Pass event_data from prepare_for_generation() result
|
|
169
|
+
result = prepare_for_generation(...)
|
|
170
|
+
_insert_header(..., event_data=result.get("event"))
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**3. Error Response Consistency**
|
|
174
|
+
Some error returns use dict directly, others use `error_response()` builder:
|
|
175
|
+
```python
|
|
176
|
+
# Inconsistent:
|
|
177
|
+
return {"error": "...", "suggestions": [...]} # body.py
|
|
178
|
+
return error_response("...", suggestions=[...]) # commands
|
|
179
|
+
|
|
180
|
+
# Could standardize on builder everywhere
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Technical Debt
|
|
184
|
+
|
|
185
|
+
### None Currently
|
|
186
|
+
- Code is well-structured with clear separation of concerns
|
|
187
|
+
- Test coverage assumed good (user confirmed functionality)
|
|
188
|
+
- Documentation comprehensive and accurate
|
|
189
|
+
- No blocking issues or workarounds
|
|
190
|
+
|
|
191
|
+
## Performance Metrics
|
|
192
|
+
|
|
193
|
+
**Before Refactoring:**
|
|
194
|
+
- 442 total command lines
|
|
195
|
+
- 166 duplicate lines
|
|
196
|
+
- 2 DuckDB queries per generation
|
|
197
|
+
|
|
198
|
+
**After Refactoring:**
|
|
199
|
+
- 272 total command lines (-38%)
|
|
200
|
+
- 0 duplicate lines (-100%)
|
|
201
|
+
- 1 DuckDB query per generation (-50%)
|
|
202
|
+
|
|
203
|
+
## Breaking Changes
|
|
204
|
+
|
|
205
|
+
**None** - Public API unchanged:
|
|
206
|
+
- `to_model(event, output, model_name, json_path, expr)` - same signature
|
|
207
|
+
- `quicktype(event, output, type_name, json_path, expr, ...)` - same signature
|
|
208
|
+
- Behavior enhanced (more event types supported) but backward compatible
|
|
209
|
+
|
|
210
|
+
## Notes for Next Session
|
|
211
|
+
|
|
212
|
+
### What Worked Well
|
|
213
|
+
- Clean break refactoring (no migrations)
|
|
214
|
+
- Service layer orchestration pattern
|
|
215
|
+
- Pure utilities in separate module
|
|
216
|
+
- Comprehensive TIPS.md documentation
|
|
217
|
+
|
|
218
|
+
### Lessons Learned
|
|
219
|
+
- `expr` is powerful enough to handle edge cases - avoid special casing
|
|
220
|
+
- Documentation belongs in TIPS.md, not scattered in docstrings
|
|
221
|
+
- Private methods improve readability even if only called once
|
|
222
|
+
- Permissive error handling (return empty + suggestions) > hard failures
|
|
223
|
+
|
|
224
|
+
### Code Quality
|
|
225
|
+
- ✅ Linting clean
|
|
226
|
+
- ✅ Type checking clean
|
|
227
|
+
- ✅ No console errors reported
|
|
228
|
+
- ✅ User testing confirmed working
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
**Session Duration:** ~3 hours
|
|
233
|
+
**Commits Made:** 0 (changes staged, ready to commit)
|
|
234
|
+
**Files Changed:** 6
|
|
235
|
+
**Lines Added:** ~280
|
|
236
|
+
**Lines Removed:** ~330
|
|
237
|
+
**Net Impact:** -50 lines, +infinite flexibility 🎯
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// WebTap Background Service Worker
|
|
2
|
+
// Handles UI mode switching (sidepanel vs popup window)
|
|
3
|
+
|
|
4
|
+
console.log("[WebTap] Background service worker loaded");
|
|
5
|
+
|
|
6
|
+
// Default mode
|
|
7
|
+
const DEFAULT_MODE = "sidepanel";
|
|
8
|
+
|
|
9
|
+
// Initialize context menu on install
|
|
10
|
+
chrome.runtime.onInstalled.addListener(() => {
|
|
11
|
+
createContextMenus();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
// Create context menu items
|
|
15
|
+
function createContextMenus() {
|
|
16
|
+
chrome.contextMenus.removeAll(() => {
|
|
17
|
+
chrome.contextMenus.create({
|
|
18
|
+
id: "open-sidepanel",
|
|
19
|
+
title: "Open as Side Panel",
|
|
20
|
+
contexts: ["action"],
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
chrome.contextMenus.create({
|
|
24
|
+
id: "open-popup",
|
|
25
|
+
title: "Open as Popup Window",
|
|
26
|
+
contexts: ["action"],
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
chrome.contextMenus.create({
|
|
30
|
+
id: "separator",
|
|
31
|
+
type: "separator",
|
|
32
|
+
contexts: ["action"],
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
chrome.contextMenus.create({
|
|
36
|
+
id: "close-sidepanel",
|
|
37
|
+
title: "Close Side Panel",
|
|
38
|
+
contexts: ["action"],
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Handle context menu clicks
|
|
44
|
+
chrome.contextMenus.onClicked.addListener((info, tab) => {
|
|
45
|
+
if (info.menuItemId === "open-sidepanel") {
|
|
46
|
+
chrome.sidePanel.open({ windowId: tab.windowId });
|
|
47
|
+
} else if (info.menuItemId === "open-popup") {
|
|
48
|
+
chrome.windows.create({
|
|
49
|
+
url: chrome.runtime.getURL("sidepanel.html"),
|
|
50
|
+
type: "popup",
|
|
51
|
+
width: 600,
|
|
52
|
+
height: 900,
|
|
53
|
+
focused: true,
|
|
54
|
+
});
|
|
55
|
+
} else if (info.menuItemId === "close-sidepanel") {
|
|
56
|
+
chrome.sidePanel.setOptions({ enabled: false, tabId: tab.id });
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Handle extension icon click (default: sidepanel)
|
|
61
|
+
chrome.action.onClicked.addListener(async (tab) => {
|
|
62
|
+
chrome.sidePanel.open({ windowId: tab.windowId });
|
|
63
|
+
});
|
|
@@ -3,7 +3,16 @@
|
|
|
3
3
|
"name": "WebTap DevTools",
|
|
4
4
|
"version": "0.2.0",
|
|
5
5
|
"description": "Chrome DevTools Protocol debugger via WebTap",
|
|
6
|
-
"permissions": [
|
|
6
|
+
"permissions": [
|
|
7
|
+
"activeTab",
|
|
8
|
+
"tabs",
|
|
9
|
+
"scripting",
|
|
10
|
+
"sidePanel",
|
|
11
|
+
"contextMenus"
|
|
12
|
+
],
|
|
13
|
+
"background": {
|
|
14
|
+
"service_worker": "background.js"
|
|
15
|
+
},
|
|
7
16
|
"side_panel": {
|
|
8
17
|
"default_path": "sidepanel.html"
|
|
9
18
|
},
|
|
@@ -189,15 +189,33 @@
|
|
|
189
189
|
.error-banner-dismiss {
|
|
190
190
|
background: transparent;
|
|
191
191
|
border: none;
|
|
192
|
-
color: #c62828;
|
|
193
192
|
cursor: pointer;
|
|
194
193
|
padding: 0;
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
194
|
+
width: 16px;
|
|
195
|
+
height: 16px;
|
|
196
|
+
position: relative;
|
|
197
|
+
flex-shrink: 0;
|
|
198
|
+
}
|
|
199
|
+
.error-banner-dismiss::before,
|
|
200
|
+
.error-banner-dismiss::after {
|
|
201
|
+
content: "";
|
|
202
|
+
position: absolute;
|
|
203
|
+
top: 50%;
|
|
204
|
+
left: 50%;
|
|
205
|
+
width: 12px;
|
|
206
|
+
height: 2px;
|
|
207
|
+
background: #c62828;
|
|
208
|
+
transition: background 0.2s;
|
|
209
|
+
}
|
|
210
|
+
.error-banner-dismiss::before {
|
|
211
|
+
transform: translate(-50%, -50%) rotate(45deg);
|
|
212
|
+
}
|
|
213
|
+
.error-banner-dismiss::after {
|
|
214
|
+
transform: translate(-50%, -50%) rotate(-45deg);
|
|
215
|
+
}
|
|
216
|
+
.error-banner-dismiss:hover::before,
|
|
217
|
+
.error-banner-dismiss:hover::after {
|
|
218
|
+
background: #b71c1c;
|
|
201
219
|
}
|
|
202
220
|
</style>
|
|
203
221
|
</head>
|
|
@@ -211,9 +229,8 @@
|
|
|
211
229
|
class="error-banner-dismiss"
|
|
212
230
|
id="dismissError"
|
|
213
231
|
title="Dismiss error"
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
</button>
|
|
232
|
+
aria-label="Dismiss error"
|
|
233
|
+
></button>
|
|
217
234
|
</div>
|
|
218
235
|
</div>
|
|
219
236
|
|
|
@@ -221,6 +238,10 @@
|
|
|
221
238
|
<option disabled>Loading pages...</option>
|
|
222
239
|
</select>
|
|
223
240
|
|
|
241
|
+
<div class="button-row">
|
|
242
|
+
<button id="reloadPages">Reload Pages</button>
|
|
243
|
+
</div>
|
|
244
|
+
|
|
224
245
|
<div class="button-row">
|
|
225
246
|
<button id="connect">Connect</button>
|
|
226
247
|
<button id="disconnect">Disconnect</button>
|